Docs
View as markdown

Use the interactive shell

Explore a relate store in the interactive shell, with multi-line statements, line editing and history, parameters, dot commands, and transactions.

cli

Before you start: Install relate

This guide shows you how to work in the relate interactive shell: start it on a store, run statements that span several lines, edit and recall what you typed, bind parameters, use the dot commands, group writes in a transaction, and leave. The shell opens when relate runs on a terminal with no statement to run. It reads one statement One unit of Cypher that relate parses, plans and runs, such as a MATCH … RETURN read or a CREATE write; a script holds several, separated by ;. Read more in the glossary at a time, runs it when it sees the closing ;, and prints the result as a table.

The transcripts on this page come from a terminal session with relate 0.1.2 and are not replayed by the docs checks. Each is followed by the same statements as a piped script, which the checks replay; a script and the shell share the statement splitter and the dot commands.

Prerequisites

  • relate on your PATH (Install relate).
  • A terminal. With stdin redirected or piped, relate with no statement prints its help instead of opening the shell.
  • An empty working directory. The first step writes the team graph shared across the docs to team.rl there.

Build the example store

Write the seed to a file and run it into a new store. This step writes team.rl:

cat > seed.cypher <<'EOF'
CREATE (ada:Person {name: 'Ada', role: 'engineer'}),
       (grace:Person {name: 'Grace', role: 'engineer'}),
       (noor:Person {name: 'Noor', role: 'maintainer'}),
       (relate:Project {name: 'relate', language: 'Rust'}),
       (tck:Project {name: 'opencypher-tck', language: 'Gherkin'}),
       (ada)-[:WORKS_ON {since: 2024}]->(relate),
       (grace)-[:WORKS_ON {since: 2023}]->(relate),
       (grace)-[:WORKS_ON {since: 2022}]->(tck),
       (noor)-[:MAINTAINS]->(relate),
       (ada)-[:KNOWS]->(grace);
EOF
relate query --database ./team.rl < seed.cypher

Start the shell

Open the store read-only An open mode (--read-only) that never writes, checkpoints or migrates the store; writes fail, and a directory store can be read beside its writer. Read more in the glossary for exploring, so nothing you type can change it:

relate --database ./team.rl --read-only

The shell prints a banner and the cypher> prompt:

Relate 0.1.2. End statements with ;  (.quit to exit)
cypher>

relate with no --database opens the shell on an in-memory store A relate database: a directory, a single .rl file, or :memory:, opened with --database. Read more in the glossary, which is gone when the shell exits. relate query --database <path> opens the same shell. Flags given at the start apply to the whole session: --mode changes the output, --timeout bounds each statement, and --read-only refuses every write.

Run a statement over several lines

Type the statement over as many lines as you like and end it with ;. Until the ;, the prompt changes to ...> and the shell keeps reading:

cypher> MATCH (p:Person)-[w:WORKS_ON]->(proj:Project)
   ...> WHERE w.since >= 2023
   ...> RETURN p.name AS person, proj.name AS project
   ...> ORDER BY person;
+---------+----------+
| person  | project  |
+---------+----------+
| "Ada"   | "relate" |
| "Grace" | "relate" |
+---------+----------+

Only a ; at the end of the statement submits it. A blank line doesn't, and a ; inside a string or a comment doesn't end the statement. The same lines as a piped script print the same table:

printf 'MATCH (p:Person)-[w:WORKS_ON]->(proj:Project)\nWHERE w.since >= 2023\nRETURN p.name AS person, proj.name AS project\nORDER BY person;\n' | relate query --database ./team.rl --read-only --mode table
+---------+----------+
| person  | project  |
+---------+----------+
| "Ada"   | "relate" |
| "Grace" | "relate" |
+---------+----------+

A statement that fails prints its error and returns to cypher>. Unlike a script, the shell keeps going after a failure.

Edit and recall input

On a terminal, the prompt is a line editor:

KeyEffect
Left, Right, Home, EndMove within the current line
Emacs-style editing keysEdit the current line
Up, DownWalk back and forward through what you submitted in this session
Ctrl-CDrop the statement you are typing and return to cypher>
Ctrl-DLeave the shell (on an empty line)

A statement you submitted over several lines comes back as one history entry. History lasts for the session only: the shell writes no history file, and there is no tab completion. Ctrl-C at the ...> prompt discards every line typed so far:

cypher> MATCH (n)
   ...>
cypher>

Bind parameters for the session

Pass --param name=value when you start the shell, once per parameter A named value a statement refers to as $name and the caller binds separately, such as with --param name=value on the CLI. Read more in the glossary. Every statement in the session can use $name; the shell has no command to set one later:

relate --database ./team.rl --read-only --param name=Grace
cypher> MATCH (p:Person {name: $name})-[w:WORKS_ON]->(proj:Project)
   ...> RETURN proj.name AS project, w.since AS since
   ...> ORDER BY since;
+------------------+-------+
| project          | since |
+------------------+-------+
| "opencypher-tck" | 2022  |
| "relate"         | 2023  |
+------------------+-------+

The same statement, piped with the same flag:

printf 'MATCH (p:Person {name: $name})-[w:WORKS_ON]->(proj:Project)\nRETURN proj.name AS project, w.since AS since\nORDER BY since;\n' | relate query --database ./team.rl --read-only --param name=Grace --mode table
+------------------+-------+
| project          | since |
+------------------+-------+
| "opencypher-tck" | 2022  |
| "relate"         | 2023  |
+------------------+-------+

Script the CLI covers value types and quoting.

Use dot commands

A line that starts with . is a shell command, not Cypher. It runs when you press Enter and needs no ;:

CommandEffect
.helpLists what the shell accepts
.begin, .commit, .rollbackOpen, commit, or discard an explicit transaction
.checkpointWrites a checkpoint of a persistent store now
.infoPrints the store's metadata, node and relationship counts, and its indexes and constraints
.timer on, .timer offPrints each statement's run time after its result
.quit, .exitLeaves the shell

Any other dot command prints Error: unknown command <name>. Output format, headers and width are flags given at the start, not dot commands. The dot commands reference has each command's output and errors.

Group writes in a transaction

This section writes to team.rl, so start the shell without --read-only. Removing --read-only is what allows writes:

relate --database ./team.rl

Outside a transaction, each statement that writes commits as soon as it succeeds. To make several statements one unit, open a transaction A unit of work that commits as a whole or not at all; each statement is its own transaction unless an explicit begin … commit groups several. Read more in the glossary with .begin, check the result inside it, then .commit. This one adds Ines to the relate project:

cypher> .begin
cypher> MATCH (proj:Project {name: 'relate'})
   ...> MERGE (i:Person {name: 'Ines', role: 'engineer'})
   ...> MERGE (i)-[:WORKS_ON {since: 2026}]->(proj);
cypher> MATCH (:Person)-[:WORKS_ON]->(:Project {name: 'relate'}) RETURN count(*) AS people;
+--------+
| people |
+--------+
| 3      |
+--------+
cypher> .commit

The write prints nothing. Statements inside the transaction see its writes, so the count is 3 before .commit. .rollback in place of .commit discards them. If a statement fails inside the transaction, every later statement prints semantic error: transaction failed; rollback required until you run .rollback.

The same transaction as a piped script. MERGE makes it safe to run after the session, because a second run finds Ines already there:

cat > ines.cypher <<'EOF'
.begin
MATCH (proj:Project {name: 'relate'})
MERGE (i:Person {name: 'Ines', role: 'engineer'})
MERGE (i)-[:WORKS_ON {since: 2026}]->(proj);
.commit
EOF
relate query --database ./team.rl --mode envelope < ines.cypher
{"columnTypes":[],"columns":[],"notifications":[],"planCache":"miss","rows":[],"timings":{"elapsed_ms":0.46883400000000003,"execute_ms":0.249917,"lex_parse_ms":0.00625,"lower_ms":0.008791,"parse_ms":0.207125,"plan_ms":0.006917,"result_generation_ms":0.000125,"rewrite_ms":0.00033299999999999996},"truncated":false}

Leave the shell

Type .quit or .exit, or press Ctrl-D on an empty line. At the ...> prompt, Ctrl-D first runs the lines entered so far, then leaves. On a line with text, Ctrl-D edits the line and does not leave. The shell exits 0, even after a statement failed in the session.

On a store opened for writing, the shell writes a checkpoint as it exits. A transaction still open at exit is rolled back, and the shell says so on stderr before it exits:

cypher> .begin
cypher> .quit
Warning: exiting with an open transaction; rolling back uncommitted changes. Use .commit before exiting to persist them.

Verify

Read the store back, read-only. Ines works on relate after the transaction committed:

relate --database ./team.rl --read-only --mode table "MATCH (p:Person)-[:WORKS_ON]->(:Project {name: 'relate'}) RETURN p.name AS name ORDER BY name"
+---------+
| name    |
+---------+
| "Ada"   |
| "Grace" |
| "Ines"  |
+---------+

If it goes wrong

What you seeCauseRemedy
The relate help text instead of a promptstdin is piped or redirected, so there is no terminal to read fromRun relate from a terminal, or pipe the script to relate query
The ...> prompt keeps coming backThe statement has no closing ;, or an open quote or comment is swallowing itType ; and Enter, or press Ctrl-C to start over
semantic error: WriteOnReadOnlyAccessDatabase: No write operations are allowed on this database. The database is in read-only mode on this Neo4j instance.The shell was started with --read-onlyLeave and start it again without --read-only to write
semantic error: transaction failed; rollback requiredA statement failed inside a .begin transactionRun .rollback, then the transaction again
Failed to open Relate: storage locked: <path>, exit code 5Another process holds the store for writingWait for it to exit, or open with --read-only (a directory store can be read beside its writer; a .rl store only while no writer holds it)
warning: line editor unavailable (<reason>); falling back to plain stdinThe terminal doesn't support the line editorThe shell still works; arrow keys and history are off for the session
  • Dot commands: every dot command with its output and errors
  • Output modes: the --mode values a session can start with
  • CLI flags: --param, --read-only, --timeout and the rest
  • Script the CLI: the same statements and dot commands from a file