Skip to main content
nanograph

CLI Reference

nanograph <command> [options]

Global options

OptionDescription
--jsonEmit machine-readable JSON output for supported commands
--config <nanograph.toml>Load CLI defaults from a project config file. If omitted, ./nanograph.toml is used when present. Local secrets are loaded from ./.env.nano and then ./.env when present.
--helpShow help
--versionShow CLI version

See Project Config for nanograph.toml, .env.nano, alias syntax, and precedence.

Commands

version

Show CLI version and optional database manifest/dataset version info.

nanograph version [--db <db_path>]

With --db or db.default_path, includes current manifest db_version and per-dataset Lance versions.

describe

Describe schema + manifest summary for a database.

nanograph describe [--db <db_path>] [--format table|json] [--type <TypeName>]

If db.default_path is set in nanograph.toml, --db can be omitted.

--type filters the output down to a single node or edge type. JSON output includes agent-facing schema metadata such as description, instruction, derived key properties, unique properties, relationship summaries, and edge endpoint keys.

schema-diff

Compare two schema files without opening a database.

nanograph schema-diff --from <old_schema.pg> --to <new_schema.pg> [--format table|json]

This command classifies changes as additive, compatible_with_confirmation, breaking, or blocked, and emits remediation hints such as @rename_from("...") where applicable.

export

Export the full graph (nodes first, then edges) to stdout.

nanograph export [--db <db_path>] [--format jsonl|json]

If db.default_path is set in nanograph.toml, --db can be omitted.

  • jsonl is the portable seed format: nodes plus edges with from / to resolved through schema @key values
  • json keeps more debug-oriented internal detail for inspection

init

Create a new database from a schema file.

nanograph init [db_path] --schema <schema.pg>

Creates the <db_path>/ directory with schema.pg, schema.ir.json, and an empty manifest.

When missing, init also scaffolds nanograph.toml and .env.nano in the inferred project directory shared by the DB path and schema path. nanograph.toml is for shared defaults; .env.nano is for local secrets like OPENAI_API_KEY.

If db.default_path and/or schema.default_path are set in nanograph.toml, db_path and/or --schema can be omitted.

load

Load JSONL data into an existing database.

nanograph load [<db_path>] --data <data.jsonl> --mode <overwrite|append|merge>
ModeBehavior
overwriteReplace the entire current graph snapshot with the loaded data
appendAdd rows without deduplication
mergeUpsert by @key — update existing rows, insert new ones

merge requires at least one node type in the schema to have a @key property. If db.default_path is set in nanograph.toml, db_path can be omitted.

check

Parse and typecheck a query file without executing.

nanograph check [--db <db_path>] --query <queries.gq>

If the provided query path is relative and not found directly, nanograph also searches the configured query.roots from nanograph.toml. If db.default_path is set in nanograph.toml, --db can be omitted.

run

Execute a named query.

nanograph run [alias] [--db <db_path>] [--query <queries.gq>] [--name <query_name>] [options]
OptionDescription
--format table|csv|jsonl|jsonOutput format (default: table)
--param key=valueQuery parameter (repeatable)

Supports both read queries and mutation queries (insert, update, delete) in DB mode.

If the provided query path is relative and not found directly, nanograph also searches the configured query.roots from nanograph.toml. If db.default_path is set in nanograph.toml, --db can be omitted.

When the selected query includes @description("...") and/or @instruction("..."), the default table output prints that context before the result rows. Machine-oriented formats like json, jsonl, and csv remain unchanged.

Query aliases

nanograph.toml can define short aliases for run on both read and mutation queries:

[db]
default_path = "app.nano"

[query_aliases.search]
query = "queries/search.gq"
name = "semantic_search"
args = ["q"]
format = "table"

Then you can run:

nanograph run search "vector databases"

Multi-parameter aliases work the same way:

[query_aliases.family]
query = "queries/search.gq"
name = "family_semantic"
args = ["slug", "q"]
format = "table"
nanograph run family luke "chosen one prophecy"

Explicit --param values still work and override alias-derived positional params when both are provided.

Precedence is:

  1. explicit CLI flags such as --query, --name, --format, --db
  2. query_aliases.<alias>
  3. shared defaults like db.default_path and cli.output_format

See Project Config for the full alias model.

delete

Delete nodes by predicate with automatic edge cascade.

nanograph delete [<db_path>] --type <NodeType> --where <predicate>

Predicate format: property=value or property>=value, etc.

All edges where the deleted node is a source or destination are automatically removed. If db.default_path is set in nanograph.toml, db_path can be omitted.

changes

Read commit-gated CDC rows from the authoritative JSONL log.

nanograph changes [<db_path>] [--since <db_version> | --from <db_version> --to <db_version>] [--format jsonl|json]

If db.default_path is set in nanograph.toml, db_path can be omitted.

CDC semantics (time machine)

  • Source of truth: CDC is read from _cdc_log.jsonl, gated by _tx_catalog.jsonl and manifest db_version.
  • Commit visibility: only fully committed transactions at or below current manifest db_version are visible.
  • Ordering: rows are emitted in logical commit order by (db_version, seq_in_tx).
  • Windowing:
    • --since X returns rows with db_version > X
    • --from A --to B returns rows in inclusive range [A, B]
  • Crash/recovery safety: trailing partial JSONL lines are truncated on open/read reconciliation; orphan tx/cdc tail rows beyond manifest visibility are ignored/truncated.
  • Retention impact: nanograph cleanup --retain-tx-versions N prunes old tx/cdc history, so time-machine replay is guaranteed only within retained versions.
  • Analytics materialization: nanograph cdc-materialize builds derived Lance dataset __cdc_analytics for analytics acceleration, but does not change CDC correctness semantics.

compact

Compact manifest-tracked Lance datasets and commit updated pinned versions.

nanograph compact [<db_path>] [--target-rows-per-fragment <n>] [--materialize-deletions <bool>] [--materialize-deletions-threshold <f32>]

If db.default_path is set in nanograph.toml, db_path can be omitted.

cleanup

Prune tx/CDC history and old Lance dataset versions while preserving replay/manifest correctness.

nanograph cleanup [<db_path>] [--retain-tx-versions <n>] [--retain-dataset-versions <n>]

If db.default_path is set in nanograph.toml, db_path can be omitted.

doctor

Validate manifest/dataset/log consistency and graph integrity.

nanograph doctor [<db_path>]

Returns non-zero when issues are detected. If db.default_path is set in nanograph.toml, db_path can be omitted.

cdc-materialize

Materialize visible CDC rows into derived Lance dataset __cdc_analytics for analytics acceleration. This does not change changes semantics; JSONL remains authoritative.

nanograph cdc-materialize [<db_path>] [--min-new-rows <n>] [--force]

If db.default_path is set in nanograph.toml, db_path can be omitted.

migrate

Apply schema changes to an existing database.

nanograph migrate [<db_path>] [options]

Edit the database's schema.pg first, then run migrate. The command diffs the old and new schema IR and generates a migration plan.

OptionDescription
--dry-runShow plan without applying
--auto-approveApply confirm-level steps without prompting
--format table|jsonOutput format (default: table)

Migration steps have safety levels:

LevelBehavior
safeApplied automatically (add nullable property, add new type)
confirmRequires --auto-approve or interactive confirmation (drop property, rename)
blockedCannot be auto-applied (add non-nullable property to populated type)

Use @rename_from("old_name") in the schema to track type/property renames. If db.default_path is set in nanograph.toml, db_path can be omitted.

Data format

JSONL with one record per line. Nodes and edges use different key names — mixing them up is a common error.

Nodes use "type" + "data":

{"type": "Person", "data": {"name": "Alice", "age": 30}}

Edges use "edge" + "from" + "to" (matched by node @key value within source/destination types):

{"edge": "Knows", "from": "Alice", "to": "Bob"}

Common mistake: Using {"type": "Knows", "src": "Alice", "dst": "Bob"} for edges. This is parsed as a node record and will fail with "unknown node type".

For each edge endpoint type, @key is required so from/to can be resolved.

Edges with properties:

{"edge": "Knows", "from": "Alice", "to": "Bob", "data": {"since": "2020-01-01"}}

nanograph export --format jsonl emits this same portable seed shape. It does not include internal storage fields like node id or edge id / src / dst.

Debug logging

RUST_LOG=debug nanograph run --db mydb.nano --query q.gq --name my_query

Upgrading from 0.6 to 0.7

The internal schema IR format changed in 0.7. Databases created with 0.6 will fail to open with a schema mismatch error. To migrate, export your data as JSON from the old CLI, then reimport with the new one:

# 1. Export data using your current (0.6) build
nanograph export --db mydb.nano --format jsonl > backup.jsonl

# 2. Build the new (0.7) CLI
cargo build -p nanograph-cli

# 3. Create a fresh database from the original schema
nanograph init mydb-v07.nano --schema mydb.nano/schema.pg

# 4. Load the exported data
nanograph load mydb-v07.nano --data backup.jsonl --mode overwrite

# 5. Verify
nanograph doctor mydb-v07.nano

If you no longer have the 0.6 binary, you can patch the manifest hash manually: compute the FNV-1a hash of the current schema.ir.json file and update schema_ir_hash in graph.manifest.json, then export.

See also