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 issue <file> |
Writ runs the task and applies grants, budgets, protected-file rules, and completion checks. |
Start with basic use. Add a limit after the record shows which tools the project needs. Use a writ file only when Writ must own the full run.
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.
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.
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 issue bug-fixerFill 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 Writ must run the model and tools. This example lets the agent change source files, protects tests, sets a budget, and defines the commands that prove completion.
writ: bug-fixer
mandate: "Make the failing tests pass without changing tests."
grants:
- read: { paths: ["**/*"] }
- search: { scope: repo }
- shell: { commands: ["pytest *", "git diff"] }
- edit: { paths: ["src/**"] }
bounds:
iterations: 40
cost: $2.50
wall_clock: 20m
invariants:
- { layer: letter, untouched: "tests/**" }
satisfaction:
all:
- { layer: letter, run: "pytest -x -q", exit: 0 }Configure the runtime once. Then check, run, and read the task:
writ configure
writ check bug-fixer.yaml --explain
writ issue bug-fixer.yaml
writ review bug-fixerIn this mode, Writ checks each managed action. It counts model turns and cost. It checks workspace changes. It runs the completion command before it accepts the task.
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.
| Agent | Built-in tools | Local MCP | Remote MCP | Hosted tools |
|---|---|---|---|---|
| Claude | Covered | Covered | Covered | WebSearch and WebFetch are covered. |
| Codex | Most local tools | Covered | Covered | Hosted tools such as WebSearch are not visible. |
| Cursor | Covered in trusted workspaces | Covered | Covered | Early cloud turns may run before hooks load. |
| OpenCode | Permissioned tools | Covered | Covered | Coverage depends on permission events. |
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 configure |
Configure the model, judge, sandbox, and assent. |
writ issue |
Run a task under a writ. |
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 |
Check 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/.
