Git worktrees
Isolated branches and files for sessions in Git projects.
Each Git-backed session gets its own worktree and branch, based on the repository's default branch rather than the branch currently checked out in your source repository. Multi-repository workspaces resolve the root and each child repository independently.
ao project add --path /path/to/repo --worker-agent codex
ao spawn --project my-repo --name fix-authWorktrees keep checked-out files separate while sharing the repository's Git object database.
How Orchestrator chooses the base branch
Orchestrator asks the selected remote for its default branch. If it cannot reach the remote, Orchestrator uses that remote's cached HEAD. If the remote has no default branch, a fetched branch named in the spawn request can seed the explicitly requested session branch.
Orchestrator records the base ref for each repository. Workspace and review diffs use it to recalculate the merge base after a rebase or when the repository default advances, so upstream-only changes do not appear as agent edits.
Typed project settings
The daemon stores project configuration as validated JSON in SQLite. Relevant fields include:
| Field | Purpose |
|---|---|
defaultBranch | Base branch for new session worktrees; auto resolves each repository's Git default. |
env | Extra environment variables passed to agent runtimes. |
symlinks | Repository-relative paths linked into each workspace. |
postCreate | Commands run after workspace creation. |
agentRules, agentRulesFile | Standing worker instructions. |
orchestratorRules, orchestratorRulesFile | Standing orchestrator instructions. |
Use ao project set-config <id> --help for flags. To pass the complete object with --config-json, first read the full-config warning.
Cleanup safety
ao session kill terminates the runtime, but preserves a worktree when cleanup cannot safely remove it. ao session cleanup reclaims eligible terminated workspaces and skips dirty ones; run with --dry-run first when you want to inspect the candidates. Each result is recorded, so a workspace already released is not offered again, and a skipped one is reported with its reason (uncommitted changes, a missing repository, or a worktree locked with git worktree lock) and a stable code such as dirty, missing_repo, locked_worktree or permission_error, which scripts can match in the ao session cleanup output or the /api/v1/sessions/cleanup response.
Only archiving a session (ao session kill, including the archive after a merged PR) and ao session cleanup remove worktrees. An agent that exits on its own keeps its worktree. In the background, AO only finishes a cleanup that was already accepted but interrupted (for example by a daemon restart) and, for sessions whose worktree folder is already gone, prunes git's leftover registration and records the release; it never removes a worktree that is still on disk. A stale lock that git worktree add left behind is lifted during cleanup; any other lock is kept and reported.
After cleanup, ao session delete <id> permanently removes the session record and its AO history; with --cleanup it cleans the worktree up first, never forced. Its session ID is never reused, and its spend stays in the agent account usage totals. In the desktop app, the trash icon on an archived session card does the same, cleaning up first.
To delete archived sessions automatically, choose a period under Settings → Sessions → Delete archived sessions (7, 30 or 90 days; Never by default). Only sessions whose worktree is already cleaned up are deleted: retention never removes a worktree, so a dirty or kept one keeps its session.