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.