Docs menu

Working with agents

.md

How to set up Claude Code, Codex, Cursor and friends to work on Oak โ€” and the rules they should follow.

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, and main never 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 on main.
  • 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:

CommandUse
oak agent state --json --compactOne document: repo, branch, what's dirty, what's unpushed, and recommended_next_commands. The "where am I and what now?" call.
oak status --json --compactBounded working-tree status.
oak diff --json --hunks --max-bytes NThe diff, with a byte budget.
oak commit --json, oak push --json, oak pull --jsonReceipts with what happened and what to do next.
oak finish --desc-file <file> --jsonDescribe, checkpoint, and publish in one step โ€” see below.
oak conflict status, oak conflict show --jsonConflict state, file by file.
oak ci status --jsonThe merge gate's verdict (also via exit code).
oak branch triage --remote --jsonScore 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.

Something here wrong or missing? Run oak feedback -m "โ€ฆ" or email [email protected].