IPython/Jupyter magic commands for Neo4j Cypher queries (%cypher / %%cypher)
Project description
ipython-neo4j
IPython / Jupyter magic commands for Neo4j Cypher queries. A modern replacement for icypher built on the neo4j-rust-ext Bolt driver with first-class graph visualization via neo4j-viz.
%load_ext ipython_neo4j
%neo4j bolt://localhost:7687 -u neo4j -p secret
%cypher MATCH (m:Movie) RETURN m.title AS title, m.released AS year LIMIT 10
Installation
pip install ipython-neo4j
Or with uv:
uv add ipython-neo4j
To use .env file support via %neo4j --env-file, install the optional extra:
pip install "ipython-neo4j[dotenv]"
Requirements: Python ≥ 3.10, Neo4j 6.x.
Quick start
# 1. Load the extension
%load_ext ipython_neo4j
# 2. Connect
%neo4j bolt://localhost:7687 -u neo4j -p secret
# 3. Run a read query — renders as an HTML table
%cypher MATCH (m:Movie) RETURN m.title AS title LIMIT 5
# 4. Multi-line query in a cell
%%cypher
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
RETURN p.name AS actor, count(m) AS films
ORDER BY films DESC
LIMIT 10
# 5. Get a pandas DataFrame
%%cypher --df -o df
MATCH (m:Movie) RETURN m.title AS title, m.released AS year
df.describe()
# 6. Visualize a subgraph
%%cypher --viz
MATCH (p:Person)-[r:ACTED_IN]->(m:Movie)
RETURN p, r, m
LIMIT 30
Magic commands
%neo4j — connect / status / disconnect
%neo4j [URI] [-u USERNAME] [-p PASSWORD] [-d DATABASE]
[--env-file FILE]
[--status] [--close]
| Flag | Description |
|---|---|
URI |
Bolt URI, e.g. bolt://localhost:7687 or neo4j+s://host |
-u / --username |
Neo4j username |
-p / --password |
Neo4j password |
-d / --database |
Target database (default: neo4j) |
--env-file FILE |
Load connection settings from a .env file |
--status |
Show current connection status |
--close |
Close the active connection |
%cypher / %%cypher — read queries
%cypher [flags] QUERY
%%cypher [flags]
<query body>
%wcypher / %%wcypher — write queries
Identical to %cypher / %%cypher but write and schema operations are explicitly allowed.
Use this to make write intent visible in notebooks.
Common flags for %cypher / %%cypher / %wcypher / %%wcypher
| Flag | Description |
|---|---|
--write / -w |
Allow write / schema queries (alternative to %%wcypher) |
--no-preflight |
Skip the EXPLAIN query-type pre-flight check |
-o VAR |
Store the CypherResult in the notebook variable VAR |
--df |
Return / store a pandas DataFrame instead of a CypherResult |
--viz |
Render an interactive graph visualization (requires neo4j-viz) |
-P EXPR |
Query parameters — a Python expression evaluated in the notebook namespace |
-u / --uri |
Override connection URI for this query only |
--username |
Override username for this query only |
-p / --password |
Override password for this query only |
-d / --database |
Override database for this query only |
Configuring the connection
Connection settings are resolved in this priority order (highest wins):
explicit flag on %neo4j > --env-file values > shell env vars > built-in defaults
Option 1 — Direct flags (most explicit)
%neo4j bolt://localhost:7687 -u neo4j -p secret -d mydb
Option 2 — .env file
Create a .env file (and add it to .gitignore):
NEO4J_URI=bolt://localhost:7687
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=secret
NEO4J_DATABASE=mydb
Then in your notebook:
%neo4j --env-file .env
%neo4j --env-file secrets.env -d override_db # file + per-flag override
Requires python-dotenv:
pip install python-dotenv
Option 3 — IPython %env magic (no file needed)
%env NEO4J_URI=bolt://localhost:7687
%env NEO4J_USERNAME=neo4j
%env NEO4J_PASSWORD=secret
%env NEO4J_DATABASE=mydb
%neo4j # picks up the vars automatically
Option 4 — Shell environment variables
Set variables before launching Jupyter, then call %neo4j with no arguments:
export NEO4J_URI=bolt://localhost:7687
export NEO4J_USERNAME=neo4j
export NEO4J_PASSWORD=secret
export NEO4J_DATABASE=mydb
jupyter lab
%neo4j # auto-connects from env
Option 5 — python-dotenv directly in a cell
from dotenv import load_dotenv
load_dotenv(".env") # populates os.environ
%neo4j # reads from env
Option 6 — Per-query connection override
Override the global connection for a single query without changing it:
%%cypher -u bolt://other-host:7687 --username analyst -p readonly -d reporting
MATCH (n:Report) RETURN n LIMIT 5
Read / write safety
%cypher (and %%cypher) block write and schema queries by default.
Before executing, an EXPLAIN pre-flight call is made to detect the query type:
| Neo4j type | Meaning | Default behaviour |
|---|---|---|
r |
Read | ✅ Allowed |
w |
Write | ❌ Blocked |
rw |
Read + write | ❌ Blocked |
s |
Schema (DDL) | ❌ Blocked |
To allow writes, use --write or the dedicated %%wcypher magic:
# Either of these works:
%%cypher --write
CREATE (n:Person {name: 'Alice'}) RETURN n
%%wcypher
CREATE INDEX person_name IF NOT EXISTS FOR (n:Person) ON (n.name)
Skip the pre-flight check when you know the query is safe (e.g. on slow connections):
%%cypher --no-preflight
MATCH (n) RETURN n LIMIT 100
Multi-statement cells
Statements can be separated by a semicolon at the end of a line — the same convention used in Cypher Shell and Neo4j Browser:
%%wcypher
CREATE INDEX person_name IF NOT EXISTS FOR (n:Person) ON (n.name);
CREATE CONSTRAINT person_id IF NOT EXISTS FOR (n:Person) REQUIRE n.id IS UNIQUE
Each statement is EXPLAIN'd individually. If any statement is a write or schema
operation the entire cell is blocked unless --write / %%wcypher is used.
Note: Mid-line semicolons — e.g. inside string literals like
WHERE name = 'O;Brien'— are not treated as statement separators.
When multiple statements are present, each result is displayed with a numbered header
and the last result is stored when -o VAR is used.
Working with results
%%cypher -o result
MATCH (p:Person)-[:ACTED_IN]->(m:Movie)
RETURN p.name AS name, m.title AS title
LIMIT 20
# CypherResult renders as an HTML table in Jupyter automatically
result # display HTML table
result.df # pandas DataFrame shorthand
result.to_dataframe() # same
len(result) # number of rows
result.keys # column names
result.counters # write counters (nodes_created, etc.)
result.summary # full Neo4j ResultSummary
result.visualize() # render neo4j-viz graph
result.visualize(color_by="caption") # with custom coloring
result.to_graph() # VisualizationGraph object
Query parameters
Pass a Python expression (evaluated in the notebook namespace) with -P:
params = {"year": 2000, "name": "Tom Hanks"}
%%cypher -P params -o movies
MATCH (p:Person {name: $name})-[:ACTED_IN]->(m:Movie)
WHERE m.released >= $year
RETURN m.title AS title, m.released AS year
Graph visualization
Return Node and Relationship objects and render them with --viz:
%%cypher --viz
MATCH (p:Person)-[r:ACTED_IN]->(m:Movie)
RETURN p, r, m
LIMIT 40
Or call .visualize() programmatically on any CypherResult:
%%cypher -o g
MATCH (p:Person)-[r:DIRECTED]->(m:Movie) RETURN p, r, m LIMIT 20
g.visualize(color_by="caption")
Visualization is powered by neo4j-viz and is installed automatically as a dependency.
Error rendering
Neo4j errors (syntax errors, type errors, auth failures, connectivity issues) are rendered as styled HTML in the cell output rather than raw Python tracebacks:
%cypher MATCH (n) RETURN @@bad@@
# → Cypher Syntax Error: rendered with error code and query context
Reloading after code changes
When developing ipython-neo4j itself, reload the extension without restarting the kernel:
%reload_ext ipython_neo4j
Development
git clone https://github.com/neo4j-labs/ipython-neo4j
cd ipython-neo4j
uv sync --all-groups
# unit tests (no Neo4j required)
uv run pytest tests/test_connection.py tests/test_result.py tests/test_magic.py -v
# integration tests (requires Neo4j)
# credentials in integration.env
uv run pytest tests/test_integration.py -v
# run the demo notebook
uv run jupyter lab notebooks/demo.ipynb
Integration tests use:
- Read-only demo (
integration.envdefault):neo4j+s://demo.neo4jlabs.com— user/db:movies - Local write tests:
bolt://localhost:7687— user:neo4j, password:password
License
Apache 2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ipython_neo4j-0.1.0.tar.gz.
File metadata
- Download URL: ipython_neo4j-0.1.0.tar.gz
- Upload date:
- Size: 1.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d18d1620e96f8c4c4bb8c264badd217a06577ffb90c9bd5c24a957d6bafc031
|
|
| MD5 |
648ee7659f043a253ebcafc75158096e
|
|
| BLAKE2b-256 |
34fbfe0aa2b7edecca54bf4b62aeafdd3cdcffc45d3d5b5baeac47ac3ab397dc
|
File details
Details for the file ipython_neo4j-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ipython_neo4j-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
039ba2a0ebd4a3af7b0699cb72812ce444fcf899615d438584efe99d1fd2a6b0
|
|
| MD5 |
81c51ef768a83042ea5c9607fe690319
|
|
| BLAKE2b-256 |
fba137e8bb5b0694cc56e7e820e7e4915d8a8906f282089576ee5f288ec74ec2
|