Reference

Commands

Everything persist --help lists, with options, what each command writes, and real output.

Every command that writes files accepts --dry-run (show planned writes without writing) and --force (overwrite existing files explicitly). Without --force an existing file is skipped and listed under "Skipped". Every command prints what it created, where, and a short "Next steps" list. persist <command> --help prints the options for any command.

Command Purpose
persist initInitialize repository memory.
persist adoptInspect an existing repository and propose reviewable memory.
persist feature create <name>Create feature memory docs.
persist adr create <title>Create a proposed ADR.
persist adr accept <name>Promote a proposed ADR to accepted repository memory.
persist adr supersede <old> <new-title>Record a changed decision.
persist module create <name>Create module memory docs.
persist doctorCheck whether repository memory is healthy.
persist test-gateRun the configured test command and require it to pass.
persist mcp add <server>Generate proposed, offline memory for an MCP server.
persist skill create <name>Generate an agent skill for Claude Code and the portable Agent Skills target.
persist skill listList built-in catalog skills.
persist fence addRecord the human-confirmed reason a path is shaped the way it is.
persist contextFind the area memory a task needs: cards first, decisions second.
persist context addScaffold a context card for an area of the codebase.
persist hooks syncRegenerate the generated hooks from the config. Never touches docs or config.

persist init

persist init [--ai-tools <list>] [--features] [--modules] [--yes] [--no-enable-hooks] [--dry-run] [--force] [--reinit]

Writes the six memory documents and the decision directory under docs/, the agent entry points (AGENTS.md, CLAUDE.md, the Cursor rule), twelve agent skills in both .claude/skills/ and .agents/skills/ (eleven without --modules: module-memory is generated only when module memory is enabled), the pre-commit and pre-push hooks, a GitHub Actions workflow, the Claude SessionStart hook, and .persist/config.json. It works in an empty folder. The full file list is in Repository memory.

On a terminal with no explicit flags it asks five questions, each with a default: which AI tools, whether to track features, whether to track modules, whether to enable the test gate (the detected command is printed first), and whether to enable the Chesterton fence. Any explicit flag, --yes, or a stdin that is not a terminal skips the questions; a non-TTY run prints a line saying it proceeded with defaults.

--ai-tools <list>
Comma-separated tools to generate files for: claude, codex, cursor, generic. Default is claude, codex, cursor. AGENTS.md is always written.
--yes
Take every default without prompting. For CI and scripted setup.
--features
Also write the opt-in feature memory index, docs/40-features/README.md.
--modules
Also write the opt-in module memory index, docs/30-modules/README.md.
--dry-run
Show planned writes without writing files.
--force
Overwrite existing files explicitly.
--reinit
Required together with --force when the directory already has .persist/config.json. Without it, --force refuses, so an existing installation is never overwritten by accident. Reinit rewrites every generated file, filled-in docs included, and resets the config to defaults. To refresh hooks only, use persist hooks sync.
--no-enable-hooks
Write the hooks but leave git config alone. By default init switches the hooks on for this clone (git config core.hooksPath .persist/hooks), and never over a core.hooksPath another tool already owns.

Init also reads package.json. A one-shot test script becomes testCommand; typecheck and lint scripts become pre-push gates. When it finds a manifest it also prints what it detected, marked as proposed:

$ persist init --features
persist repository memory for AI-assisted software work
────────────────────────────────────────
Persist OS init complete.
Test gate: npm run test:run (saved as testCommand in .persist/config.json).

Detected in this repository (proposed — review, nothing was accepted):
- Languages: JavaScript
- Package manager: npm (from `package.json`)
- Frameworks: none detected
- Tests: detected via `tests/` directory
If any signal is wrong, correct the source file noted. Run `persist adopt` to record this as proposed memory.

See Hooks, test gate, CI for what the gates do with those values.

persist adopt

persist adopt [--dry-run] [--force]

Inspects an existing repository through read-only manifest and marker files, then writes a proposed adoption report at docs/adopt/ADOPTION_REPORT.md and proposed framework ADRs under docs/adrs/proposed/ — both follow the configured docs and ADR directories when memory has moved. It never executes repository code and never produces accepted memory; every inferred signal names its source and waits for human review.

$ persist adopt
Persist OS adopt complete.
Inferred signals are proposed and require human review.
Languages: TypeScript
Package manager: pnpm
Frameworks: Next.js
Created:
- docs/adopt/ADOPTION_REPORT.md
- docs/adrs/proposed/ADR-PROPOSED-adopt-nextjs.md

Next steps:
- Review docs/adopt/ADOPTION_REPORT.md — everything in it is proposed.
- Run persist init to establish neutral repository memory if it does not exist yet.
- Accept or reject each proposed ADR under docs/adrs/proposed/.

That run was in a Next.js app with tsconfig.json and a pnpm-lock.yaml. The report records where each signal came from:

- Languages: TypeScript
- Package manager: pnpm (from `pnpm-lock.yaml`)
- Frameworks: Next.js (from `package.json`)
- Tests: detected via `"test"` script in package.json
- README present: no
- Docs folder present: no

persist feature create

persist feature create <name> [--dry-run] [--force]

Creates a numbered feature folder under the configured features directory (default docs/40-features/) with a plan and a task list. When a test command is configured, it also writes a test plan, so the scaffold never outruns the gate that enforces it.

$ persist feature create checkout
Persist OS feature create complete.
Feature: docs/40-features/F-001-checkout
Created:
- docs/40-features/F-001-checkout/PLAN.md
- docs/40-features/F-001-checkout/TASKS.md
- docs/40-features/F-001-checkout/TEST_PLAN.md

Next steps:
- Start in docs/40-features/F-001-checkout: fill PLAN.md (approach, boundaries, acceptance criteria).
- Then TASKS.md before you implement.
- Run persist doctor to check the memory is complete.

Without a test command the same run creates only PLAN.md and TASKS.md.

persist adr create

persist adr create <title> [--dry-run] [--force]

Creates a numbered ADR in the configured ADR directory (default docs/adrs/) with Status set to Proposed and sections for Context, Decision, Alternatives Considered, Consequences, and Related Documents.

$ persist adr create "Use PostgreSQL for primary storage"
Persist OS ADR create complete.
ADR: docs/adrs/ADR-0001-use-postgresql-for-primary-storage.md
Created:
- docs/adrs/ADR-0001-use-postgresql-for-primary-storage.md

Next steps:
- Open docs/adrs/ADR-0001-use-postgresql-for-primary-storage.md and fill: Context, Decision, Alternatives, Consequences.
- It is Proposed — set Status to Accepted once the team agrees.
- The Chesterton fence is enabled: if this decision revisits why specific source files are shaped the way they are, record the human-confirmed reason in FENCES.md (the chestertons-fence skill walks through it).

persist adr accept

persist adr accept <name> [--dry-run] [--force]

Promotes a proposed ADR to accepted. <name> is the slug, for example use-postgresql-for-primary-storage or mcp-figma. Two cases:

  • A proposal at docs/adrs/proposed/ADR-PROPOSED-<slug>.md (as written by adopt or mcp add) becomes the next numbered ADR-####-<slug>.md, and the proposal file is removed.
  • A numbered ADR that is still Proposed (as written by adr create) is accepted in place.
$ persist adr accept use-postgresql-for-primary-storage
Persist OS ADR accept complete.
Accepted: docs/adrs/ADR-0001-use-postgresql-for-primary-storage.md
Overwritten:
- docs/adrs/ADR-0001-use-postgresql-for-primary-storage.md

Next steps:
- docs/adrs/ADR-0001-use-postgresql-for-primary-storage.md is now Accepted and is repository source of truth.
- Drift checks now treat references to it as resolved.

persist adr supersede

persist adr supersede <old> <new-title> [--dry-run] [--force]

Records a changed decision. <old> must be an accepted ADR (a proposed one has nothing to supersede; accept it first). The command writes a new, accepted ADR with a ## Supersedes link back, and rewrites the old ADR's status line to Accepted — superseded by <new>. Nothing is deleted. The replacement title must not collide with another live decision or proposal: a colliding title is refused with the existing file named, because the doctor's duplicate-titles check would flag it anyway.

$ persist adr supersede use-postgresql-for-primary-storage "Use SQLite for primary storage"
Persist OS ADR supersede complete.
Superseded: docs/adrs/ADR-0001-use-postgresql-for-primary-storage.md (now marked superseded by ADR-0002-use-sqlite-for-primary-storage)
New decision: docs/adrs/ADR-0002-use-sqlite-for-primary-storage.md
Created:
- docs/adrs/ADR-0002-use-sqlite-for-primary-storage.md
Overwritten:
- docs/adrs/ADR-0001-use-postgresql-for-primary-storage.md

Next steps:
- Fill docs/adrs/ADR-0002-use-sqlite-for-primary-storage.md: Context (what changed), Decision, Alternatives, Consequences.
- ADR-0001-use-postgresql-for-primary-storage stays in history as superseded; update any memory that still relies on it.
- Run persist doctor — it flags memory that still references the superseded decision.
- The Chesterton fence is enabled: supersede is the moment a past decision is revisited — if source files shaped by the old decision change, record why in FENCES.md (the chestertons-fence skill walks through it).

persist module create

persist module create <name> [--dry-run] [--force]

Creates a module folder under the configured modules directory (default docs/30-modules/) for a responsibility boundary: what it owns, what it does not, its tasks, its test plan, and its decisions.

$ persist module create billing
Persist OS module create complete.
Module: docs/30-modules/billing
Created:
- docs/30-modules/billing/MODULE.md
- docs/30-modules/billing/TASKS.md
- docs/30-modules/billing/TEST_PLAN.md
- docs/30-modules/billing/DECISIONS.md

Next steps:
- Open docs/30-modules/billing/MODULE.md and describe what this module owns and does not own.
- Record durable decisions in DECISIONS.md, or link an ADR.

persist doctor

persist doctor [--json]

Checks that the memory is structurally healthy, that completion claims have evidence, and that memory references decisions that exist and are accepted. Read-only, deterministic, no network. Exit code 0 means healthy, 1 warnings only, 2 errors. --json emits the same report as machine-readable JSON with schemaVersion: "persist.doctor.v1". Every check and severity is listed in Doctor.

persist test-gate

persist test-gate

Runs the testCommand from .persist/config.json and exits with that command's exit code. The command is split on whitespace and executed directly, without a shell. When testCommand is null the gate does not pretend to pass; it prints that it was skipped, and why, and exits 0:

$ persist test-gate
Persist OS test gate skipped: the gate is off — set testCommand in .persist/config.json to a one-shot test command (e.g. "pnpm run test:run") or re-run `persist init` to detect one.

The generated pre-push hook runs this command. Details in Hooks, test gate, CI.

persist fence add

persist fence add <path> --why "<reason>" [--by <name>] [--adr <link>] [--dry-run]
persist fence add <path> --no-constraint --by <name> [--dry-run]

Records why a path is shaped the way it is, for reasoning that never rose to an ADR. The reason comes from a person; the command writes it in the exact shape doctor and the SessionStart hook read. It refuses a path that does not exist, and refuses to run outside an initialised repository, because a fence recorded there is never loaded. When a human confirms nothing in the file is deliberate, --no-constraint records that answer instead of a reason: --by is required, and --why and --adr cannot be combined with it. A real reason later replaces a No constraint entry; --no-constraint never replaces a real reason.

$ persist fence add src/billing.js --why "Writes four collections in one transaction so the ledger and the audit trail cannot diverge." --by Priya
Persist OS fence add complete.
Fenced: src/billing.js
Created:
- docs/60-engineering/FENCES.md

Fencing a path that is already fenced keeps the standing reason and adds a dated crossing. A path may carry a symbol — src/billing.js:writeOrder — which matches changes to the file. The loop end to end is in Doctor.

persist context

persist context "<task>" [--json] [--limit <n>]

Looks up the area memory a task needs. Context cards (docs/context/) are scored first with deterministic BM25 over their Answers, Also Known As, Purpose, title, Rules, Pitfalls, and Start Here fields — no embeddings, no model calls, no network. The answer is pointers, never whole files, and every match names the terms it matched on. When no card covers the task, the closest recorded decisions and fences are listed instead, marked as such. The matching areas of LESSONS.md come last (at most two, three lessons each), followed by a More lessons line naming the other areas.

$ persist context "simplify the billing write"
Start here for "simplify the billing write":

Billing (docs/context/billing.md) — matched: simplify, bill, write (via src/billing.js)
  src/billing.js — writeOrder: the four-collection write and its reason
  Rules: Fence `src/billing.js` — four collections land in one transaction, and why
  Pitfall: LESSONS: simplifying the write splits the ledger from the audit trail

The habit around it: run the lookup before starting, read only what it points at, and when the work is done add the task to the area card's Answers list, phrased the way it was asked. A prompt hook (persist context --hook) injects the pointers per prompt in Claude Code and Codex.

persist context add

persist context add <name> --purpose "<one line>" [--dry-run]

Scaffolds a context card with the exact shape the lookup parses and empty sections for the agent to fill by hand. It refuses to overwrite an existing card, and refuses to run outside an initialised repository, because a card recorded there is never loaded.

$ persist context add billing --purpose How billing writes land.
Persist OS context add complete.
Card: docs/context/billing.md
Created:
- docs/context/billing.md

Next steps:
- Fill the sections in docs/context/billing.md: Start Here paths, Rules pointers, and above all the Answers list with the task you were just given, phrased the way it was asked.
- Run persist context "<task>" to check the card is found before calling the work done.

persist hooks sync

persist hooks sync [--dry-run]

Regenerates the git hooks and the Claude SessionStart hook from .persist/config.json, and nothing else. This is the repair the doctor's hook-drift warning points at: after an upgrade, or after editing the gates or testCommand. Hooks that already match are reported as unchanged. .claude/settings.json is created when missing and otherwise left alone, because it often holds your own settings. Docs, config and agent files are never touched.

persist mcp add

persist mcp add <server> [--dry-run] [--force]

Writes proposed, offline memory for an MCP server: docs/ai/mcp/<server>.md plus a proposed adoption ADR, and a capture-mcp-context skill skeleton that tells the agent to record durable context from that server into the file. Persist OS never connects to the server; the agent, which already has the MCP connection, does the recording, and a human reviews it.

$ persist mcp add figma --dry-run
Persist OS mcp add dry run complete.
MCP memory: docs/ai/mcp/figma.md (proposed — review before adopting)
Capture skill installed so agents record durable MCP context into this memory.
Planned creates:
- docs/ai/mcp/figma.md
- docs/adrs/proposed/ADR-PROPOSED-mcp-figma.md
- .claude/skills/capture-mcp-context/SKILL.md
- .agents/skills/capture-mcp-context/SKILL.md

Files that already exist are skipped and listed as such; nothing is overwritten without --force.

persist skill create

persist skill create <name> [--dry-run] [--force]

Writes a SKILL.md to both .claude/skills/<name>/ and .agents/skills/<name>/. A catalog name gets the built-in content; any other name gets a valid skeleton to fill in. A catalog skill may ship an executable scripts/ directory (security-review ships a read-only secret scan); a skill always works with its scripts deleted.

persist skill list

$ persist skill list
Persist OS skill catalog

- implement-task: Implement Task
- write-tests: Write Tests
- create-adr: Create ADR
- drift-review: Drift Review
- completion-report: Completion Report
- module-memory: Module Memory
- plan-feature: Plan Feature
- security-review: Security Review
- conventions-adherence: Conventions Adherence
- chestertons-fence: Chesterton's Fence
- adr-compliance: ADR Compliance
- context: Context Lookup

Skills from earlier releases that are no longer in the catalog are not deleted on upgrade; persist doctor names each of the four skills still retired (with the skill that replaced it) and prints the command to remove it. Skills you create yourself stay silent.