Writ connects to Claude, Codex, Cursor, or OpenCode through the agent's native hook. You keep using the same agent. Writ records the tool calls that the hook reports. It can stop calls before they run.
The first connection needs no writ file, model key, or MCP configuration.
you → your agent → native hook → Writ decision + record
↓
agent runs tool
| Level | Start with | You get |
|---|---|---|
| Basic | writ connect <agent> |
A record of visible built-in, MCP, remote MCP, and hosted tool calls. Nothing is blocked. |
| Normal | Add --read-only or --allow |
Calls outside the tool limit stop for approval. |
| Advanced | writ sessions --agent <agent> |
Select one observed session. A writ adds path, command, domain, or exact-tool grants when the hook can enforce them. |
Start with basic use. Add a limit after the record shows which tools the project needs. Add a writ file when the task needs more exact authority.
On macOS, Linux, or Windows Git Bash:
curl -fsSL https://writ.build/install.sh | shOn Windows PowerShell:
irm https://writ.build/install.ps1 | iexThe installer selects the release for the operating system and processor. It verifies the SHA-256 checksum before it installs Writ.
writ --versionRun one command for your agent:
writ connect claude
writ connect codex
writ connect cursor
writ connect opencodeChoose the command for your agent. Start or restart the agent. Then use it as usual.
$ writ connect codex
Connected Codex to Writ.
Built-in tools: limited
MCP tools: watching
Remote MCP tools: watching
Hosted tools: not visible
Scope: global.
Writ now records visible tool calls.
Nothing is blocked.
Start or restart Codex. Use it as usual.
After a tool call, review what happened:
writ review
The status output tells you what the selected agent reports to its hook. Coverage differs by agent. Tool results come from the agent. Writ does not independently prove the effects of a connected tool call.
Tool-call records contain normalized arguments and a digest of the exact provider arguments. Writ keeps the exact provider arguments transient unless it creates an explicit approval request. The approval request can store the exact arguments after redaction.
Allow normalized read and search tools:
writ connect codex --read-onlyOr allow exact agent tool names or normalized tool names:
writ connect cursor --allow read --allow searchA call outside the limit stops and creates an approval request:
writ approvals
writ approve <request-id>Ask the agent to retry the call after approval. The approval is bound to the tool name and arguments.
Check or remove a connection:
writ connect status codex
writ disconnect codexThe default connection applies in every project for your user account. Limit the connection to the current project when needed:
writ connect codex --project
writ connect status codex --project
writ disconnect codex --projectWhen both scopes exist, Writ applies both limits. A project connection can narrow a global limit. It cannot widen one.
Writ stores its state outside the repository:
~/.writ/
config.yaml
connections/
writs/
projects/<project-id>/
record.db
connections/
organization.json
Set WRIT_HOME to use another directory. Writ does not create a project
.writ directory. When you connect from a Git worktree, Writ adds /.writ/
to the local .git/info/exclude file. This keeps a local .writ directory out
of Git without changing the shared .gitignore.
writ issue and writ start reject a Writ home that is the project root or
is inside it. Set WRIT_HOME to a directory outside the project before you
start a managed or attached run.
Create a writ that can be used from any project:
writ init bug-fixer --global
# edit ~/.writ/writs/bug-fixer.yaml
writ check bug-fixer
writ plan bug-fixer --agent claude
writ sessions --agent claude
writ start bug-fixer --agent claude --session <session-id>Fill in the mandate and grants before you run writ check. A writ file in the
current project takes precedence over a global writ with the same name.
Use a writ file when a tool list is too broad. This example limits reads to source and test files. It also allows Claude's visible WebSearch tool.
writ: source-review
mandate: "Find the code that controls retry behavior."
grants:
- read: { paths: ["src/**", "tests/**"] }
- web_search: {}Make one tool call in the intended Claude session so Writ can observe its ID. Then check the writ, select that session, and start the writ:
writ check source-review.yaml --explain
writ plan source-review.yaml --agent claude
writ sessions --agent claude
writ start source-review.yaml --agent claude --session <session-id>
# Continue in Claude.
writ finish --agent claude
writ review source-reviewwrit start does not launch an agent or replace its harness. It applies the
writ only to the selected session. Other sessions keep their normal connection
policy. One agent can have one active writ in a project.
Keep using your existing workflow to give the task to the agent. Writ records
the mandate, but the native hook does not insert it into the agent prompt.
Run writ finish --agent <agent> only when you accept that the selected
session satisfied the writ. That command writes a human satisfaction
attestation. Run writ finish --agent <agent> --cancel to stop the attached
writ without an attestation.
Writ checks the complete grants allowlist and every authored clause before activation. The command stops and names each unsupported entry and missing event. It does not silently ignore an unobserved tool source, cost bound, completion check, worktree-effect rule, or another term that the selected hook cannot enforce.
An attached writ is default deny across the complete agent tool surface. The hook must provide complete pre-tool coverage. Claude currently provides this coverage. Codex, Cursor, and OpenCode remain available for basic and normal connections, but their current hook contracts cannot run an attached writ.
An omitted bound is authored-unbounded. The managed writ issue adapter adds
operational defaults of 25 iterations, $1.00, and 15 minutes when those bounds
are omitted. An attached writ starts only when its /grants coverage row and
every authored clause are enforced.
Do not put secrets in a writ document or a --set value. Attached activation
state stores the bound document.
Use writ issue <file> when you explicitly want Writ's managed model-loop
adapter. That adapter can count model turns and cost, verify worktree changes,
run completion checks, and apply the clauses that native hooks cannot support.
Advanced deployments can also:
- connect a local or remote MCP server with
writ proxy; - inherit a signed organization policy with
writ policy; - export and verify a signed record with
writ record exportandwrit record verify; - attach a receipt from an independent witness with
writ record witness.
writ gate is a model API observer. It routes the configured model and records
admitted turns plus provider-reported usage. It does not enforce tools,
results, effects, authored cost or wall-clock bounds, remedies, or complete
measured cost. Fixed relay safety guards remain separate from authored clauses.
A valid writ contains a grant, so gate use needs writ plan --target gate and
explicit --allow-partial acceptance.
| Agent | Built-in tools | Local MCP | Remote MCP | Hosted tools | Full attached writ |
|---|---|---|---|---|---|
| Claude | Covered | Covered | Covered | WebSearch and WebFetch are covered. | Supported |
| Codex | Most local tools | Covered | Covered | Hosted tools such as WebSearch are not visible. | Not supported |
| Cursor | Covered in trusted workspaces | Covered | Covered | Early cloud turns may run before hooks load. | Not supported |
| OpenCode | Permissioned tools | Covered | Covered | Coverage depends on permission events. | Not supported |
Run writ connect status <agent> for the installed connection. Writ records
only events that the agent sends to its hook.
| Command | Purpose |
|---|---|
writ connect |
Add Writ to Claude, Codex, Cursor, or OpenCode. |
writ disconnect |
Remove the Writ-owned hook. |
writ approvals |
List stopped calls. |
writ approve / writ deny |
Decide an argument-bound call. |
writ review |
Read the latest run in the terminal or a local browser. |
writ record |
Export, witness, or verify a signed run record. |
writ init |
Create a writ file. |
writ check |
Validate and explain a writ file. |
writ plan |
Show whether a target can enforce the grants policy and authored clauses. |
writ sessions |
List recently observed sessions for a connected agent. |
writ start |
Apply a writ to an existing connected agent. |
writ finish |
Attest satisfaction or cancel an attached writ. |
writ configure |
Configure the model, judge, sandbox, and assent. |
writ issue |
Run a writ with Writ's managed model loop. |
writ proxy |
Govern a local or remote MCP server. |
writ policy |
Configure a signed organization policy. |
writ witness |
Run an independent checkpoint witness. |
writ gate |
Observe model API traffic for an external agent. |
writ amend |
Change the terms of an active writ. |
Read Install Writ, Connect and review, or Run one bounded task.
The documentation source is in docs/.
task check
task buildRead CONTRIBUTING.md before you send a change.
Writ uses the Apache License 2.0.
Brand files are in blog/brand/.
