Skip to main content

CLI for managing a grimoire datastore

Project description

4lt7ab-grimoire-cli

The standalone CLI for grimoire — a single-file semantic datastore backed by SQLite and sqlite-vec. Operates on a mount directory holding one or more grimoire databases, plus an embedded MCP server for AI client integration.

For the Python library, see 4lt7ab-grimoire.

Install

uv tool install '4lt7ab-grimoire-cli[fastembed]'
# or: pipx install '4lt7ab-grimoire-cli[fastembed]'

Both install into an isolated venv — clean uninstall, no impact on system Python. The fastembed extra pulls the bundled embedder (ONNX-based, no service required).

The grimoire command is now on your PATH. Confirm the install with grimoire --version.

The first grimoire mount create (and the first time you reuse the mount on a new machine) fetches the default embedder weights (~30 MB) from HuggingFace into the mount's __models__/ cache. Subsequent runs reuse the cache and stay offline. On macOS, if the fetch stalls on TLS errors, set HF_HUB_DISABLE_XET=1 once to bypass the xet CDN.

Mount model

A mount is a directory containing one or more grimoire databases plus a shared embedder model cache:

<mount>/
├── grimoire.db            # the default DB
├── <name>/
│   └── grimoire.db        # a named DB
├── __models__/            # shared embedder cache
└── grimoire.toml          # registry file (reserved, currently inert)

The mount resolves in this order: --mount <dir> flag > GRIMOIRE_MOUNT env var > ~/.grimoire.

Set the env var once per shell to avoid passing --mount everywhere:

export GRIMOIRE_MOUNT=$PWD/.grimoire

A mount can hold one default database at <mount>/grimoire.db plus any number of named databases under <mount>/<name>/grimoire.db. Pick which one a command targets with --db <name> / -d <name>; omit --db to target the default. Names must match [a-z0-9_-]+ and cannot begin with __ (reserved).

Mental model

A grimoire entry has two layers:

  • The entry itself: uniq_id (library-assigned ULID) + data (JSON blob).
  • Three opt-in sidecars keyed by that uniq_id:
    • entry_idx — typed filterable columns: uniq_ref (external reference), nominal_1/nominal_2 (categorical labels), ordinal_1/ordinal_2/ordinal_3 (sortable numbers).
    • entry_fts — FTS5 keyword text.
    • entry_vec — semantic vector + source text.

entry add creates an entry and optionally writes any subset of the three sidecars in the same call. Sidecar writes are PUT — supplying any of --ref/--ord-*/--nom-* wholesale-replaces the entry_idx row; supplying --match replaces the FTS row; supplying --search replaces the vec row. Deleting an entry cascade-cleans every sidecar via a DB trigger.

Quickstart

export GRIMOIRE_MOUNT=$PWD/.grimoire

# Create the mount + default DB. Idempotent.
grimoire mount create

# Add an entry with data, idx metadata, keyword text, and semantic text.
# Each idx/match/search flag is independent — pick any subset.
grimoire entry add \
    --data '{"habitat": "volcano"}' \
    --ref phoenix-001 \
    --nom-1 creature \
    --ord-1 1.0 \
    --match "phoenix fire-bird ashes" \
    --search "A solar phoenix reborn from its own ashes at dawn"

# Search.
grimoire search "creatures that come back from the dead"
grimoire match "phoenix"

# Browse entry_idx rows with filters.
grimoire query --equals nominal_1=creature --gte ordinal_1=0.5

# Look up entries by external reference.
grimoire fetch phoenix-001

# Inspect the database — model, dimension, schema version, per-table counts, file size.
grimoire info

Every command prints pretty-indented JSON. Pipe through jq for filtering and extraction.

Commands

Global options

Option Behavior
--mount <dir> Override the mount path for this invocation. Precedence: --mount > $GRIMOIRE_MOUNT > ~/.grimoire.
--version Print the CLI version and exit.
--help Print help for the command (or subcommand) and exit.

Mount administration

grimoire mount create

Create the mount directory, shared __models__/ cache, and the default database. Idempotent — safe to re-run. Loads the default embedder on first create to write the embedder lock.

grimoire mount destroy --yes

Wipe the entire mount: every database, the model cache, the registry. There is no undo. --yes is required.

grimoire mount add <name>

Create a named database in the mount. The mount itself must already exist (run mount create first).

grimoire mount ls

List databases in the mount as a JSON array of {"db": <str|null>, "path": <str>}. The default DB appears first with db: null; named DBs follow alphabetically.

grimoire mount remove <name> --yes

Delete a single named database file from the mount. The model cache and other databases are preserved. --yes is required.

Database inspection

grimoire info [--db <name>]

Show metadata for a database: embedder lock (model, dimension), schema_version, per-table row counts (entry_count, entry_idx_count, entry_fts_count, entry_vec_count), file path, file size. Does not load the embedder.

Entry CRUD

grimoire entry add [options]

Create an entry and optionally PUT-index its sidecars in one call.

Option Behavior
--db, -d Target a named DB. Omit for the default.
--data JSON value stored in entry.data (object, array, scalar, or null).
--ref entry_idx.uniq_ref value.
--nom-1, --nom-2 entry_idx.nominal_1 / nominal_2 values.
--ord-1, --ord-2, --ord-3 entry_idx.ordinal_1 / ordinal_2 / ordinal_3 (REAL) values.
--match Text written to the FTS5 row. PUT-replaces the entry's entry_fts row.
--search Text embedded via the bundled embedder. PUT-replaces the entry's entry_vec row.

Supplying any of --ref, --nom-*, --ord-* PUT-replaces the entry's entry_idx row; omitted columns become NULL. Omit all three to leave entry_idx untouched.

grimoire entry update <uniq_id> [options]

Update entry data and/or PUT-index sidecars. Omit --data to leave the data column untouched. Sidecar flags follow the same PUT semantics as entry add.

grimoire entry get <uniq_id> [<uniq_id>...]

Fetch one or more entries by uniq_id. Returns a JSON array of entry objects.

grimoire entry remove <uniq_id> --yes

Remove an entry. Sidecar rows are cascade-cleaned by DB trigger. --yes is required. Returns {"uniq_id": <id>, "removed": <bool>}removed=false if the id did not exist.

Reads

All four read commands return paired results: each match is {"entry": {...}, "<key>": ...}, where <key> is "index", "score", or "distance" depending on the command.

grimoire query [filters] [--cursor <id>] [--limit <n>]

Browse entry_idx rows ordered by uniq_id ASC, joined to entry for the data side. Returns [{"entry": {...}, "index": {...}}, ...].

Option Behavior
--db, -d Target a named DB.
--equals KEY=VAL Filter entry_idx.<KEY> IN (...). Repeatable. Valid keys: any of the seven entry_idx columns.
--gte KEY=NUMBER Filter entry_idx.<KEY> >= NUMBER. Repeatable. Valid keys: ordinal_1/ordinal_2/ordinal_3.
--lte KEY=NUMBER Filter entry_idx.<KEY> <= NUMBER. Repeatable.
--cursor Return rows with uniq_id > <cursor>. Pass the last id of the previous page.
--limit Maximum rows (default 100).
LAST=$(grimoire query --limit 100 | jq -r '.[-1].entry.uniq_id')
grimoire query --limit 100 --cursor "$LAST"

grimoire fetch <uniq_ref> [<uniq_ref>...]

Fetch entries whose entry_idx.uniq_ref is in the given list. Returns [{"entry": {...}, "index": {...}}, ...]. uniq_ref is non-unique (multiple entries may share one); entries without an entry_idx row are invisible to fetch.

grimoire match <query> [filters] [--limit <n>]

FTS5 BM25 keyword search. Free-form prose is tokenized into safe FTS5 syntax automatically: each word token is quoted and joined with OR, so apostrophes, punctuation, and bareword FTS5 operators (AND, OR, NOT, NEAR, *) in the query can't reach the parser.

Option Behavior
--db, -d Target a named DB.
--equals KEY=VAL, --gte KEY=NUMBER, --lte KEY=NUMBER Apply entry_idx filters via JOIN. Same shape as query.
--limit Maximum hits (default 10).

Returns [{"entry": {...}, "score": <bm25>}, ...]. score is positive (higher = better).

grimoire search <query> [--limit <n>]

vec0 KNN semantic search. Embeds the query via the bundled embedder, then ranks by vector distance.

Option Behavior
--db, -d Target a named DB.
--limit Maximum hits (default 10).

Returns [{"entry": {...}, "distance": <float>}, ...]. distance is the raw vec0 distance (lower = better, non-negative).

MCP server

grimoire mcp serve

Run a FastMCP server over stdio, scoped to this mount. Wires the library's read+write surface as MCP tools an AI client can call directly. Mount administration (mount create/destroy/add/remove) stays CLI-only.

Tools exposed: info, add, update, get, remove, query, fetch, match, search. add and update both accept the data + idx + match + search kwargs (mirroring the CLI's entry add/entry update). For MCP update, passing data: null (or omitting it) leaves the data column alone — there's no way to MCP-update an entry's data to NULL because JSON can't distinguish "passed null" from "not passed."

Output format

Every command prints pretty-indented JSON to stdout. There is no table mode, no --raw, no auto-detect — JSON in, JSON out, pipe to jq to slice. Errors go to stderr via Typer's standard messaging.

Environment variables

Variable Default Behavior
GRIMOIRE_MOUNT ~/.grimoire Mount directory. Overridden by --mount.

Schema notes

Pre-v1, schema changes are not migrated in place. The library checks PRAGMA user_version against its expected SCHEMA_VERSION on every open; mismatches raise SchemaVersionError. Recreate the file (and re-index its contents) when this happens. Migration ergonomics get designed once v1 is on the table.

Uninstall

uv tool uninstall 4lt7ab-grimoire-cli
# or: pipx uninstall 4lt7ab-grimoire-cli

The mount directory at ~/.grimoire (or wherever you pointed GRIMOIRE_MOUNT) is left intact. Remove it manually with grimoire mount destroy --yes before uninstalling, or rm -rf after.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

4lt7ab_grimoire_cli-0.0.20.tar.gz (16.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

4lt7ab_grimoire_cli-0.0.20-py3-none-any.whl (15.0 kB view details)

Uploaded Python 3

File details

Details for the file 4lt7ab_grimoire_cli-0.0.20.tar.gz.

File metadata

  • Download URL: 4lt7ab_grimoire_cli-0.0.20.tar.gz
  • Upload date:
  • Size: 16.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for 4lt7ab_grimoire_cli-0.0.20.tar.gz
Algorithm Hash digest
SHA256 abbc763a82130fbd5ceea6b8dbf89badbf27f7dc04d9a19ec7cf093f846c8bed
MD5 a2f450539572e68f84c18bd5b008d6a5
BLAKE2b-256 f64518f5bd5857b68bc46e8c2421d3b0cee28ca2c32757a811c5c1608bb19690

See more details on using hashes here.

File details

Details for the file 4lt7ab_grimoire_cli-0.0.20-py3-none-any.whl.

File metadata

  • Download URL: 4lt7ab_grimoire_cli-0.0.20-py3-none-any.whl
  • Upload date:
  • Size: 15.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for 4lt7ab_grimoire_cli-0.0.20-py3-none-any.whl
Algorithm Hash digest
SHA256 3b30116c6511fe72cdda37937c234658f1c7f46c63978139859d0548621bbc97
MD5 7ece78cef21529c83eb458aea8baeef0
BLAKE2b-256 d9954f074e57aaf170f73af2b336e6a9e840733ca1f35acfad072fd584b96aff

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page