[ docs ]
decree-harness.
Generate an agent harness for your codebase in one command. It scans the repo and the decisions your team wrote down, keeps everything in decree.json, and writes code for Claude Code, MCP, TypeScript and Python.
Quickstart
Needs Node 20.12 or newer. Run it from the root of your repository.
# or put the key in .env export ANTHROPIC_API_KEY=sk-ant-... npx decree-harness
The wizard scans the repo, asks what the agent is for and which targets to write, plans the harness and generates it. Without an API key, --offline uses a heuristic planner that builds the same kind of spec from the scan alone:
npx decree-harness init --yes --offline --targets allThe planner and generated harness default to claude-opus-5; subagents default to claude-sonnet-5. Change either in decree.json or with --model.
What gets written
decree.jsonThe harness spec. Edit it, then run decree-harness generate..decree/profile.json (last scan), manifest.json (hashes of generated files), schema.jsonagent/README.mdOverview of the generated harness and how to run each targetagent/harness.mdDesign doc: prompt, every tool, safety flags, planner notesagent/evals.jsonEval casesagent/.env.exampleEnv vars the tools needagent/typescript/Standalone agent on the Anthropic TypeScript SDK: CLI, REPL, evalsagent/python/Standalone agent on the Anthropic Python SDK, with pytest testsagent/mcp-server/MCP server for Claude Code, Claude Desktop and Cursoragent/claude-code/CLAUDE.md, .claude/{agents,commands,skills,settings.json}, .mcp.jsonPick targets with --targets typescript,python,mcp,claude-code or all. When the code changes, run decree-harness generate again.
Decisions
init reads the decisions your repo already writes down and stores them in decree.json under decisions. It prints a summary such as Found 14 decisions: 2 live, 11 proposed, 1 superseded.
ADRsdocs/adr, docs/adrs, docs/decisions, doc/adr, adr/, architecture/decisions, decisions/. Title from the first heading, rule from the Decision section, rationale from Context. Accepted becomes live, Proposed stays proposed, Superseded, Deprecated and Rejected become superseded.Rules filesCLAUDE.md, AGENTS.md (nested ones govern their own directory), .cursor/rules/*.mdc (its globs become governs), .cursorrules, .github/copilot-instructions.md. Rule-like bullets become decisions and start as proposed.Post-mortemsdocs/postmortems, postmortems/, incidents/. Rule-like bullets under Action items, Lessons, Follow-ups and Prevention. They start as proposed.Each decision is live, proposed or superseded. Proposed decisions are not served to agents until you confirm them. Superseded ones are kept for history and never served. Its governs globs come from frontmatter, then from repo paths the text mentions, then from the directory of a nested rules file, and otherwise cover the whole repo (**).
decree-harness decisions [--status <s>] [--json]List decisions as a table of id, status, governs and source.decree-harness decisions extract [--dry-run] [--json]Re-read the repo. Keeps your statuses, adds new decisions and flags ones whose source is gone.decree-harness decisions for <paths...>Show exactly what get_decisions returns for those files or directories (--proposed to include proposed ones).decree-harness decisions confirm <id...>Mark proposed decisions live, so the agent follows them.decree-harness decisions supersede <id> [--by <new-id>]Retire a decision. With --by, supersededBy points to its replacement.decree-harness decisions reject <id>Retire a decision with no replacement (supersede without --by).Commands that change decisions regenerate the harness if it was generated before. Pass --no-generate to skip that.
$ npx decree-harness decisions for src/payments/refunds/create.ts get_decisions {"paths":["src/payments/refunds/create.ts"]} 3 decisions govern these paths, most specific first. Follow them, and cite the id when one constrains your change. [rule-refunds-agents-md-every-refund-must-carry-an-idempotency] Every refund must carry an idempotency key built with `refundKey()` Rule: Every refund must carry an idempotency key built with `refundKey()`. Governs: src/payments/refunds/** | Source: src/payments/refunds/AGENTS.md:4 [adr-0014-ledger-writes-go-through-ledgerservice] Ledger writes go through LedgerService Rule: Write to `ledger_entries` only through `LedgerService`, in the same transaction as the change that caused the entry. Governs: src/payments/**, src/ledger/** | Source: docs/adr/0014-ledger-writes-go-through-ledgerservice.md [adr-0021-store-money-as-integer-minor-units] Store money as integer minor units Rule: Store and pass amounts as integer minor units with a currency code. Never use floating point for money. Governs: ** | Source: docs/adr/0021-store-money-as-integer-minor-units.md
The get_decisions tool
When decree.json has decisions, every generated target gets a read-only get_decisions tool. Its input is { "paths": string[], "include_proposed"?: boolean }. It returns text: at most 8 live decisions whose globs match those paths, most specific first and repo-wide ones last. Superseded decisions are never returned.
The system prompt gets one line: call get_decisions with the files you are about to change, follow what it returns, cite the decision id, and stop if a request conflicts with a live decision. The TypeScript and Python agents and the MCP server read a decisions.json shipped with them. Claude Code calls the MCP tool, or a .claude/skills/decisions script when the MCP target is not generated. The generated CLAUDE.md explains how to look decisions up and lists none of them.
// the agent is about to edit a ledger adjustment get_decisions { "paths": ["src/ledger/adjust.ts"] } // result (text) 2 decisions govern these paths, most specific first. Follow them, and cite the id when one constrains your change. [adr-0014-ledger-writes-go-through-ledgerservice] Ledger writes go through LedgerService Rule: Write to `ledger_entries` only through `LedgerService`, in the same transaction as the change that caused the entry. Governs: src/payments/**, src/ledger/** | Source: docs/adr/0014-ledger-writes-go-through-ledgerservice.md [adr-0021-store-money-as-integer-minor-units] Store money as integer minor units Rule: Store and pass amounts as integer minor units with a currency code. Never use floating point for money. Governs: ** | Source: docs/adr/0021-store-money-as-integer-minor-units.md
Decisions in decree.json
decree.json lives at the root of your project and holds the tools, guardrails, targets and decisions. It is validated on every load. Print the full schema with decree-harness schema. Each entry in decisions has these fields:
idStable slug, e.g. adr-0003-store-events-in-postgres or rule-claude-md-never-write-raw-sql-outside-src.titleShort name for the decision.constraintThe rule an agent must follow, in one to three sentences.statuslive, proposed or superseded. Only live decisions are served by default.governsGlobs relative to the repo root. ** covers the whole repo.sourceWhere it came from, e.g. docs/adr/0003-store-events-in-postgres.md or CLAUDE.md:7.ownerOptional. Who owns the decision.supersededByOptional, on a superseded decision: the id of the decision that replaced it.rationaleOptional. Why the decision was made.Commands
decree-harness / initInteractive wizard: scan, ask for the goal and targets, plan, generatescan [--json]Scan only; writes .decree/profile.jsonplanScan and plan; writes decree.json onlygenerateRender decree.json into code (--targets, --out, --clean, --dry-run, --json)refine "<feedback>"Change the harness in plain English, e.g. refine "make it read-only"chatTalk to the agent in your terminal; tools run locally with approval promptsrun "<prompt>"One-shot run (--json for machine output)evalRun the eval cases and report pass or fail (tools run in dry-run mode by default)doctorCheck Node, API key, decree.json, required env vars, generated outputtoolsList the tools in decree.jsonschemaPrint the JSON schema for decree.jsonlogin --url <dashboard>Connect this machine to your self-hosted dashboard (logout, whoami)pushSync decree.json to the dashboard; a changed spec becomes a new versionUseful flags: --yes (non-interactive), --offline, --model <id>, --goal "<text>", --no-critique, -C <dir>.
Self-hosted dashboard
The dashboard keeps every version of decree.json and the eval runs against each one. trydecree.com doesn't host it yet, so run it yourself: it is a Next.js app on Supabase.
- Create a Supabase project and apply the SQL in
supabase/migrations. - In Supabase Auth, set the Site URL to your deployment and add
https://<your-domain>/auth/callbackas a redirect URL. - Deploy
frontend/to Vercel or any Node host withDECREE_DASHBOARD_ENABLED=true,NEXT_PUBLIC_SUPABASE_URLandNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY.
Then point the CLI at it:
npx decree-harness login --url https://decree.acme.dev
npx decree-harness push
npx decree-harness eval --pushIn CI, create a token under API tokens on your dashboard and set DECREE_API_URL and DECREE_TOKEN. Tool inputs and outputs never leave your machine.
Safety model
- Every tool carries readOnly, destructive and requiresApproval flags. Destructive tools always require a human yes (guardrails.approvalMode).
- File tools are confined to guardrails.allowedPaths, including symlink escapes.
- Shell tools substitute parameters with POSIX quoting and refuse guardrails.blockedCommands.
- Values of secret env vars are redacted from tool output before the model sees them.
- maxTurns and maxCostUsd cap every run.
- decree-harness never overwrites generated files you edited (tracked in .decree/manifest.json) unless you pass --force.
Questions or a repo where the scan misses something? hello@trydecree.com. The hosted workspace is open to design partners first.