---
title: "Two agent sessions on one repository | CommitCycle"
description: "One worktree per session. The layout that lets two agents work on one repository without one of them authorising the other's writes."
url: https://commitcycle.com/docs/operations/parallel-sessions/
language: en
---

# Two sessions at once

> One worktree per session. The layout that lets two agents work on one repository without one of them authorising the other's writes.

**One worktree per session.** Two agents working on one repository at the same time get two working directories, each on its own branch, each holding its own task.

That is the whole rule. The rest of this page is why it is not a style preference, and how to lay it out.

## Why one directory cannot hold two tasks

CC binds a session to a task through the **git branch** — the hook reads the branch, resolves it to a task, and resolves the task to a grant. Nothing else identifies a session: no state file, no daemon, no `cycle use <task>` to forget to run. The thing developers already switch when they change work is the branch, so that is what CC reads.

A working directory has exactly one branch. So a working directory has exactly one task, whether the two sessions inside it meant to share one or not.

### What that cost, once

This is not a hypothetical. On 2026-08-05, a task passed the gate from the console, which created and checked out its branch **in a worktree where another session was still working**. The second session kept going, and four of its commits landed on the first task’s branch.

Because the hook resolves branch → task → grant, every one of those writes was authorised against a grant belonging to a task that did not make them — a grant that had the `enforcement` zone open for write, a zone the working session must never touch. Meanwhile the audit trail credited the wrong task with the work.

Nothing escaped, and the reason is the uncomfortable part: those four commits happened to touch only unprotected paths. **What contained it was the accident of what that session was editing, not the design.**

The lesson recorded with it is the one worth carrying: CC sells change management for parallel AI agents, and its session↔task binding had quietly assumed one agent per repository. Producing the failure took two sessions in one worktree — a customer’s ordinary Tuesday, not an edge case.

## The layout

`git worktree` gives you a second checkout of the same repository, sharing one `.git`, with its own directory and its own branch.

```bash
git worktree add ../myrepo-second
cd ../myrepo-second
```

Keep it as a **sibling** of the repository, not a child. A worktree created inside the repository directory is a checkout of a repository nested in its own history, and it turns up in every file list that walks the tree — including the one the closing gate computes.

A linked worktree is a clean checkout: it carries no `node_modules` and no build output, so install dependencies there before you build. In CommitCycle’s own monorepo, where `cycle` runs from source, the first `cycle` command fails with `MODULE_NOT_FOUND` until you do. Measured there on 2026-08-22 across three fresh worktrees: `pnpm install --frozen-lockfile`, then `pnpm --filter @commitcycle/contracts build` and `pnpm --filter @commitcycle/cli build`, about four minutes each, paid by every parallel session on its own. The `contracts` build is not optional there even though that package is a closed zone: its emitted types are what the CLI compiles against, and a fresh worktree has none until it builds them.

Then start the second piece of work from inside it:

```bash
cycle start "the second thing" --goal "…" --non-goals "…" --criteria "…"
```

All three answers are needed: the gate refuses to start a task without its non-goals.

`cycle start` runs intake → scope → branch → gate → grant → record, and it creates and checks out the branch **in whichever working directory you run it from**. That is what keeps the two sessions apart: the branch is born where the work will happen.

When the task closes, take the directory away:

```bash
git worktree remove ../myrepo-second
```

## What actually makes them independent

- **One grant per working directory.** Grants live under `.zones/state/`, which is never committed. It is not shared between worktrees, so each directory holds exactly one grant — the one for the branch it is on. Two sessions cannot reach each other’s access.
- **One `CLAUDE.local.md` per working directory.** The active-task block lives in this gitignored file at the root of each worktree, written for the task its branch names. Two sessions read two different blocks, and neither rewrites the other’s.
- **Every `cycle` command works inside a linked worktree.** In a linked worktree `.git` is a one-line file pointing at the real one; the CLI follows that pointer. It did not always — a close once ran inside a worktree and was told it was not on a task branch, which was the tool arguing against its own advice.
- **`cycle sync`** pulls the grant for the branch in _that_ directory. Run it there, not in the primary checkout.

## Three things that will bite you

**A branch can only be checked out in one worktree.** Git refuses the second attempt:

```plaintext
fatal: 'main' is already used by worktree at '/path/to/other'
```

That is git protecting you from the shared-HEAD problem this whole page is about. Branch from the remote ref instead of the local branch:

```bash
git checkout -b task/CC-101-something origin/main
```

**A worktree inside the repository gets swept up by anything that walks the tree.** The closing gate ignores editor-created session worktrees for exactly this reason — a session worktree is harness machinery, not work, and a stale one blocked a real close before that exception existed. Your own worktrees get no such exemption, so keep them outside.

**The grant expires on its own, per directory.** A long-running second session hits its own expiry independently of the first. That is the design — nobody has to remember to close access — but it means “it stopped working” in one worktree says nothing about the other. `cycle status` in that directory names what is open to it.

## What this does not solve

Two sessions in the **same** directory. Nothing here makes that safe, and nothing in CC currently detects it: the binding is the branch, one directory has one branch, so two sessions sharing a directory share a task whether they intend to or not.

The remedies proposed after the 2026-08-05 incident — the gate creating a branch without checking it out, and the hook denying when a declared task disagrees with the branch’s task — are written in decision D-43, which is still PROPOSED in the decision log, and not built. One narrow piece of the second exists: the hook refuses a write to another task’s record file while the branch names a different task (CC-51). Beyond that, the layout above _is_ the mechanism.

## What to read next

- [Two accounts on one machine](https://commitcycle.com/docs/operations/accounts/) — the other half: which identity a repository uses when a laptop holds more than one
- [Grants](https://commitcycle.com/docs/concepts/grants/) — what a grant opens, and why it expires
- [The closing gate](https://commitcycle.com/docs/operations/closing-gate/) — how a close computes what a branch actually changed
- [Install](https://commitcycle.com/docs/start/install/) — the plugin, the CLI, and which one enforces
