[!NOTE]
Pre-release. Commands and options may still change. If something does not work as you
expect, open an issue.
- Sessions: a private index for every agent. Each agent registers a session and gets its own git index. Staging is private; the working tree is shared.
- Claims: exclusive write leases on paths. Before editing, a session claims the exact paths it will write. A claim is an exclusive lease on a path.
- A refusal names the holder. A claim on a held path is refused, and the refusal names the holder. A change to a path you did not claim cannot land.
- Edit in the shared tree, stage privately. Agents edit their claimed files in the one working tree and stage them with ordinary git, each into its own index.
- Landing: every change goes through the broker. onetree land audits the claims, runs the admitted payload gate and your tests, then moves the branch ref by compare-and-swap.
- A red candidate stays out. If the tests fail on the candidate, the landing is refused. The branch does not move, and the refusal is recorded.
- One tree, one history. One clone, one working tree, one linear history. Every claim, landing and refusal is an event in an append-only log kept in git: refs/onetree/wal.
- Sessions: a private index for every agent. Each agent registers a session and gets its own git index. Staging is private; the working tree is shared. In the picture: Three agent cards (Agent A, Agent B, Agent C) stand on the left. In the middle is a panel titled "One shared working tree" with five files. On the right are the commit broker and the branch main. A box labelled "index" appears inside each agent card: each session has registered and received its own private git index. Three session_register events appear in the event log at the bottom.
- Claims: exclusive write leases on paths. Before editing, a session claims the exact paths it will write. A claim is an exclusive lease on a path. In the picture: Agent A claims src/api.py, Agent B claims src/auth.py and Agent C claims tests/test_api.py. An arrow runs from each agent to its file, and the file row shows "claimed by A" (or B, or C) with a badge carrying the agent's letter. Three claim events are appended to the log.
- A refusal names the holder. A claim on a held path is refused, and the refusal names the holder. A change to a path you did not claim cannot land. In the picture: Agent C also asks for src/api.py, which Agent A holds. The request is refused: the row shows "C refused: held by A" and a crossed-out badge with the letter C. A refused event is appended to the log.
- Edit in the shared tree, stage privately. Agents edit their claimed files in the one working tree and stage them with ordinary git, each into its own index. In the picture: Each agent edits its own file in the shared working tree; the rows change to "edited by A", "edited by B" and "edited by C". Each agent then stages its file into its own index: the index box in each agent card now names the staged file.
- Landing: every change goes through the broker. onetree land audits the claims, runs the admitted payload gate and your tests, then moves the branch ref by compare-and-swap. In the picture: Agent A lands. A chip labelled "candidate A" travels from A's index to the commit broker. The broker's four steps turn green one after another: claims audit, payload gate, test referee, compare-and-swap. A new commit marked A appears on the branch main, the file row shows "landed by A", and the events land_intent and landed are appended to the log.
- A red candidate stays out. If the tests fail on the candidate, the landing is refused. The branch does not move, and the refusal is recorded. In the picture: Agent B tries to land. Its candidate passes the claims audit and the payload gate, but the test referee turns red: the tests fail on the candidate. The candidate is marked refused, a crossed-out circle shows that no commit was added to main, and a refused event is appended to the log.
- One tree, one history. One clone, one working tree, one linear history. Every claim, landing and refusal is an event in an append-only log kept in git: refs/onetree/wal. In the picture: Agent C lands the same way as A: four green steps, and a second new commit, marked C, on main. The final picture: three agents, one working tree, a linear branch carrying the commits of A and C, B's change still waiting in the tree, and an event log with twelve entries.
Works with Claude Code and Codex
Several Claude Code sessions or subagents on one repository, overwriting each other's files?
onetree keeps them in one working tree, without a git worktree for each: every file an agent is
about to edit is claimed for it first, a second agent asking for the same file is told who has
it, and finished work reaches the branch only after your tests pass.
For Claude Code: install onetree, set your repository up once, and add the plugin.
onetree init --test "python -m pytest -q" # in your repository, once
/plugin marketplace add EliasCodeFI/onetree
/plugin install onetree@onetree
The plugin claims each file before Claude edits it, refuses git checkout, reset, stash,
commit and the other git commands that would erase another agent's work, gives each subagent
claims of its own, and adds claim, release, claims and land tools. Claude lands finished
work with the land tool, which also works when Claude Code's shell sandbox is on.
For Codex: add the same hook to .codex/hooks.json in your repository, trust it with /hooks,
and land with onetree land -a -m "<message>".
{"hooks": {"PreToolUse": [{"matcher": "^(apply_patch|Bash)$",
"hooks": [{"type": "command", "command": "onetree hook codex pre-tool-use"}]}]}}
여기까지가 README 앞부분입니다. 나머지는 원문에서 읽을 수 있습니다. README 전문 보기 ↗