Oak doesn't run agents โ you bring your own: Claude Code, Codex, Cursor, Aider, a script of your own. What Oak gives them is a version-control model that fits how they work, and a CLI built to be driven by a program as well as a person.
The model#
- One branch per session. Start each agent run on its own branch (
oak switch -c, or a fresh mount). A session you don't like gets closed, andmainnever notices. - The agent writes the description. Commits carry no message, so the agent's summary of what it did goes in
oak descโ and becomes the commit message onmain. - The agent publishes; a person merges. The agent ends by pushing its branch. You review and merge.
- Mount instead of clone. For a big repo, or many agents at once, give each agent its own mount. See Example: a fleet of agents.
Install the agent skill#
oak skill install # writes .claude/skills/oak-vcs/ in this repo โ commit it
oak skill install --global # or ~/.claude/skills/oak-vcs/ for every project on this machine
The oak-vcs skill is a SKILL.md plus reference files in the open Agent Skills format. It teaches an agent to recognize an Oak repo (a .oak/ directory and no .git), to use oak instead of git, and the whole workflow on this site โ including the traps, like interactive commands that hang without a terminal. Committed to the repo, every collaborator's agent picks it up.
The files are baked into the CLI binary, so the skill always matches the CLI version that wrote it. Re-run oak skill install after oak upgrade.
For agents that read AGENTS.md rather than skills (Codex, Cursor, and others), oak init offers to write an AGENTS.md explaining Oak, plus a one-line CLAUDE.md that points at it.
Rules to give an agent#
If you'd rather put it in your own prompt or AGENTS.md, this is the core:
This repo uses Oak (the `oak` CLI), not git. Never run git commands here.
- Work on the current feature branch. main lives on the server; never try to push to it.
- `oak commit` takes no message. Describe the branch once with `oak desc "..."`;
it becomes the commit message on main, so write it for a reviewer.
- Finish every task with: oak desc "...", oak commit, oak push
(or `oak finish --desc-file <file> --json`).
- Do not run `oak merge`. A human merges.
- Prefer --json output. Commands that open a UI or prompt (bare `oak diff`,
`oak switch` with no name, `oak clone` with no repo, `oak split` without --plan)
hang without a terminal โ use `oak diff --print`/`--stat`/`--json` and pass names.
- `oak reset` / `oak restore` ask for confirmation; pass -f only after
`oak status` shows what you'd discard.
- First push of a brand-new repo: `oak push --repo <org>/<name>`. Never guess the
org โ ask if you don't know it.
- Lost? Run `oak agent state --json --compact`.
Machine-readable everything#
Every command an agent needs takes --json, and the results are designed to be acted on:
| Command | Use |
|---|---|
oak agent state --json --compact | One document: repo, branch, what's dirty, what's unpushed, and recommended_next_commands. The "where am I and what now?" call. |
oak status --json --compact | Bounded working-tree status. |
oak diff --json --hunks --max-bytes N | The diff, with a byte budget. |
oak commit --json, oak push --json, oak pull --json | Receipts with what happened and what to do next. |
oak finish --desc-file <file> --json | Describe, checkpoint, and publish in one step โ see below. |
oak conflict status, oak conflict show --json | Conflict state, file by file. |
oak ci status --json | The merge gate's verdict (also via exit code). |
oak branch triage --remote --json | Score every open branch, for an agent doing review. |
Many JSON payloads include recommended_next_commands: exact invocations for the natural next step. An agent should run one of those rather than improvise flags.
Exit codes are stable and meaningful โ 3 repository locked (retry), 4 dirty working tree, 5 conflicts, 6 network/server/auth โ so a wrapper can branch without parsing text. The table is in the CLI reference.
Finishing a task in one command#
oak finish --desc-file /tmp/desc.md --json
oak finish checks it can publish (is a remote linked? is anything blocking?) before changing anything, then sets the branch description, checkpoints uncommitted changes, and pushes. Inside a mount it also unmounts โ but only once the push has succeeded. If any step fails, nothing is lost: the JSON names the step and the command to run next.
Credentials for unattended agents#
oak login needs a browser once. An agent on a server, in CI, or in a container should use an API key instead:
export OAK_API_KEY=oak_...
For an agent, prefer a key that can do no more than its job โ a service account with only read and write scopes (so it can push but never merge), or a key scoped to a single repo. See API keys and tokens.
Running many agents at once#
Give each agent its own branch and its own working tree, so they can't step on each other. With mounts that costs seconds, not a clone per agent:
oak space new acme && cd acme
oak mount acme/web ./fix-login/web
oak mount acme/web ./add-search/web
claude -p "Task fix-login, mounted at ./fix-login/web ..." &
claude -p "Task add-search, mounted at ./add-search/web ..." &
wait
oak branch triage --remote
The example session walks through this end to end, and Agent spaces covers the scaffolding.
Feedback from agents#
Agents hit rough edges first. oak feedback files a bug or feature request from the terminal and returns a tracking reference (fb-N):
oak feedback -m "oak pull --json omits parent_head_after on fast-forward" --json
Without -m or --file it opens your editor on a terminal, and exits with an error (rather than hanging) when there's no terminal.
Privacy#
Oak makes no AI calls on your behalf and doesn't train on your code. Whatever agent you use is its own integration, with its own data policy.