Marrow CLI
The local CLI is the primary Marrow client today. It runs against either a local Postgres + pgvector instance (full feature surface, including graph analysis) or against a hosted Marrow API (the api … subcommands).
Getting started
npm install
cp .env.example .env
npm run db:start
npm run db:migrate
npm run build
npm run db:start uses Docker Compose when available and falls back to an equivalent docker run for pgvector/pgvector:pg17.
For hosted-API calls, set:
export MARROW_API_BASE_URL=https://marrow.example.com
export MARROW_API_KEY=<raw API key>
For operator-only api admin … commands, also set MARROW_ADMIN_TOKEN.
Available commands
The CLI groups into five families. Every command supports --help.
Direct writes
Fast, validated writes for direct first-person material that does not need distillation.
node dist/cli.js add note --text "Built the first Marrow schema scaffold." --facets engineering-agent-tooling
node dist/cli.js add claim --text "Marrow stores source-grounded claims."
node dist/cli.js add entity --type tool --content '{"name":"Drizzle"}'
node dist/cli.js context add \
--kind preference \
--text "I want the Northstar work framed as cross-functional delivery, not just a product launch." \
--as-claim \
--claim "Avery prefers the Northstar work to be framed as cross-functional delivery rather than only a product launch." \
--facets rendering,positioning
Direct writes do not embed; run embeddings backfill afterwards if the new records should be semantically searchable.
Ingest, distillation, embeddings
# dry-run plans
node dist/cli.js ingest --dry-run --analyze-style path/to/source.md
node dist/cli.js ingest --dry-run --analyze-style --distill path/to/source.md
node dist/cli.js ingest-url --dry-run --focus "Northstar" https://example.com/page
# live writes (require --distill and --dated-at)
node dist/cli.js ingest --distill --dated-at 2026-04-30 path/to/source.pdf
node dist/cli.js ingest-url --distill --dated-at 2026-03-10 https://example.com/page
# replay a saved distillation for deterministic regression
node dist/cli.js ingest --distill-fixture path/to/distillation.json path/to/source.md
# backfill embeddings
node dist/cli.js embeddings backfill --dry-run
node dist/cli.js embeddings backfill --limit 10 --batch-size 5
node dist/cli.js embeddings backfill --include-style --source-run-id <source_run_id>
Live distillation supports OpenAI and Anthropic. Set MARROW_DISTILLER_PROVIDER and MARROW_DISTILLER_MODEL, or pass --distiller-provider / --distiller-model. Live writes require VOYAGE_API_KEY for embeddings.
Read, search, query, style
node dist/cli.js search "typescript drizzle zod"
node dist/cli.js search "technical writing voice" --style
node dist/cli.js search "source-grounded claims" --target claim --limit 5
node dist/cli.js query "What supports Avery's cross-functional delivery experience?"
node dist/cli.js style profile --scope technical-writing
node dist/cli.js style eval-tasks
query is the local equivalent of POST /v1/query. style profile is the local equivalent of POST /v1/style/profile.
Style A/B benchmark packets:
node dist/cli.js style eval-plan \
--guide-a path/to/baseline.md \
--guide-b path/to/marrow.md \
--source path/to/source-evidence.md \
--task technical-rewrite --json
node dist/cli.js style eval-run \
--guide-a path/to/baseline.md \
--guide-b path/to/marrow.md \
--source source-evidence.md \
--task technical-rewrite \
--out style-eval-result.json
Graph inspection, source runs, corrections
node dist/cli.js facets
node dist/cli.js predicates
node dist/cli.js inspect runs
node dist/cli.js inspect run <source_run_id>
node dist/cli.js neighbors <node_id> --node-type note
node dist/cli.js graph report
node dist/cli.js graph analyze
node dist/cli.js graph canonicalize --limit 10
node dist/cli.js graph enrich
node dist/cli.js graph export --out graph.json
node dist/cli.js source-run evidence <source_run_id> --out source-evidence.md
node dist/cli.js source-run rollback <source_run_id>
node dist/cli.js source-run rollback <source_run_id> --yes
node dist/cli.js feedback correction \
--supersedes claim:<claim_id> \
--text "Do not say Avery led the rollout strategy. …" \
--claim "Avery led cross-functional delivery and launch of the Northstar onboarding rollout; …" \
--facets onboarding-rollout,correction
Rollback and feedback correction are dry-run by default; add --yes to write.
Hosted-API client
The api … subcommands proxy to the hosted API using MARROW_API_BASE_URL and MARROW_API_KEY:
# customer
npm run dev -- api query "What evidence supports the rendering work?"
npm run dev -- api style-profile --scope technical-writing
npm run dev -- api ingest-url --yes --dated-at 2026-05-12 https://example.com/profile
npm run dev -- api ingest-file --yes --dated-at 2026-05-12 ./profile.md
npm run dev -- api ingest-jobs
npm run dev -- api ingest-job <job_id>
npm run dev -- api api-keys
npm run dev -- api create-api-key --name "Read-only query key" --scopes query,evidence,style
npm run dev -- api revoke-api-key <api_key_id>
npm run dev -- api account-export
# operator
npm run dev -- api admin create-account --email customer@example.com
npm run dev -- api admin create-invite --email customer@example.com --display-name "Customer Demo"
npm run dev -- api redeem-invite --invite-token <invite_token> --api-key-name "Customer demo CLI"
npm run dev -- api admin export-account --user-id <account_id>
npm run dev -- api admin delete-account --user-id <account_id> --yes
# deployment proofs
npm run dev -- api smoke --bootstrap
npm run dev -- api smoke --bootstrap --file-ingest
npm run dev -- api customer-proof --url https://example.com/profile \
--out .marrow/proofs/customer-proof.json \
--public-out .marrow/proofs/customer-proof.public.json \
--format summary
npm run proof:site-data -- .marrow/proofs/customer-proof.public.json site/data/customer-proof.js
npm run demo:hosted:gate -- --url https://example.com/profile
Configuration
The CLI reads .env (local) and .secrets/.env (hosted demo gate). Key environment variables:
| Variable | Purpose |
|---|---|
DATABASE_URL |
Local Postgres connection |
VOYAGE_API_KEY |
Voyage embeddings (required for live ingest) |
OPENAI_API_KEY / ANTHROPIC_API_KEY |
LLM distillation |
MARROW_DISTILLER_PROVIDER |
openai or anthropic |
MARROW_DISTILLER_MODEL |
Provider-specific model id |
MARROW_API_BASE_URL |
Hosted-API endpoint for api … commands |
MARROW_API_KEY |
Customer API key for hosted calls |
MARROW_ADMIN_TOKEN |
Operator token for api admin … commands |
MARROW_API_RATE_LIMIT_WINDOW_MS |
Hosted rate-limit window |
MARROW_API_RATE_LIMIT_REQUESTS |
Hosted rate-limit request count |
Never hardcode secrets in the repo. Keep them in .secrets/.env.