Skip to content

Git Worktrees

Kangentic uses git worktrees to give each agent an isolated copy of your repository. This lets multiple agents work on different tasks simultaneously without stepping on each other’s changes.

A git worktree is a linked working copy of your repository that shares the same .git directory. Each worktree can have a different branch checked out, so multiple branches can be worked on at the same time without cloning the repo multiple times.

When an agent is spawned for a task with worktrees enabled, Kangentic:

  1. Creates a new branch from the configured base branch (e.g., fix-websocket-a1b2c3d4)
  2. Creates a worktree in .kangentic/worktrees/{task-number}/ inside your project - the directory is named after the task’s ticket number (e.g., .kangentic/worktrees/42/), chosen once and never renamed. Tasks created before this naming keep their original {slug}-{id} folders. Branch names are unrelated to folder names and keep the slug form.
  3. Launches the agent in the worktree directory

The agent makes all its changes in the worktree. Your main working directory is never touched.

Each task has a Main / Worktree toggle that overrides the global worktree setting. Use this when you want a specific task to run directly in your main working directory (e.g., a quick config change) while keeping worktrees enabled for everything else.

Set this when creating a task or in the task detail dialog.

Tasks running in the main working directory all share one checkout, so only one of them can hold it. If a task would switch branches in a directory where another task’s agent is already live, Kangentic refuses the checkout and tells you which task is holding it and what to do: stop that task, or turn worktrees on so each gets its own copy. A Command Terminal counts as an occupant too, since it runs a real agent at the project root. Queued sessions count as well, because a queued task has already claimed the directory it will start in.

The refusal does not throw the whole operation away. Creating, unarchiving, or promoting a task still succeeds; the card simply arrives without an agent, and the toast says why rather than leaving you to guess. Worktrees are on by default precisely so this case does not come up.

Auto-generated branch names depend on whether the task’s base branch matches the project default:

<task-slug>-<8-char-id>
<flattened-base-branch>/<task-slug>-<8-char-id>

When the base branch equals the project default (e.g., both main), the name is plain:

  • fix-websocket-a1b2c3d4
  • prune-stale-worktrees-d4e5f678

When the base branch differs from the default, it is encoded as a namespace prefix (any / in the base is flattened to -), so git branch and GitHub’s branch list group work by base:

  • base release/1.2 + default main produces release-1.2/fix-regression-g7h8i9j0
  • base bugfix/inacc-adjustments + default main produces bugfix-inacc-adjustments/task-title-ab12cd34

The 8-character ID prevents collisions when tasks have similar titles. The resolved base branch is also shown in the task detail dialog so you can confirm what the worktree branched from without leaving the app.

An agent creating a task over MCP can name the branch explicitly with branchName, which is how it hands work it has already committed to a new task. Git allows a branch in only one working tree at a time, so a task naming a branch that is already checked out somewhere can never build its worktree.

Since v0.36.0, kangentic_create_task checks for that before writing anything and refuses the call, naming the branch and the path holding it. Nothing is created, so you no longer end up with a card that looks healthy but has no worktree and no session. The check fails open: if git cannot be probed, the create goes ahead.

Relatedly, a worktree or checkout failure on any spawn path now raises a notification instead of failing quietly, and a failed move no longer force-deletes an agent-supplied branch while cleaning up. Auto-generated branch leftovers are still cleaned as before.

The branch each worktree is cut from follows a priority order:

  1. Task’s base branch - per-task override set in the task creation dialog
  2. Action config’s base branch - per-transition override on a create_worktree action
  3. Board default - defaultBaseBranch in the team-shared kangentic.json, so everyone on a board forks from the same branch
  4. git.defaultBaseBranch - project or global setting (default: main)

Spawns and Update from base resolve the same ladder minus the per-transition rung: the task’s own base, then the board default, then git.defaultBaseBranch, then main.

Since v0.37.0, a task never starts from a base branch that is quietly behind origin.

  • A new worktree is cut from a fetched origin/<base>, not from whatever your local ref happened to be at your last pull.
  • A task running in the main directory gets the same treatment. A task with worktrees off still checks a branch out in the project directory when it names one: a custom branch name is fetched and checked out, and otherwise its base branch is checked out and fast-forwarded from origin. That fast-forward is non-fatal: local-only commits or a diverged branch keep your local state rather than failing the spawn. A task with neither a custom branch nor a base branch has nothing to check out, so git is left alone.
  • A spawn that reuses an existing worktree is measured, not moved. A background probe counts how far behind the base that tree is and marks the card’s spawn-progress labels with (base 3 behind). It never rewrites your branch and never delays the spawn - a worktree with work in it is not something to fast-forward behind your back.
  • A failed fetch says so. When the fetch genuinely fails on network or credentials, the remaining spawn labels read (base fetch failed) and a single toast per project explains it, rather than one per task. A repository with no origin remote stays quiet, since there is nothing to be behind.

When a card reports it is behind, Update from base in the task detail window’s kebab menu is the one-click fix: it fetches the task’s effective base and fast-forwards the worktree. It never merges and never rebases, so it can only ever move a branch that has no work of its own.

It appears for tasks that have a worktree and are not archived, and it is disabled while a session is active - updating a branch underneath a working agent is not something to do by accident. Every outcome reports back as a toast:

ResultWhat it means
Fast-forwarded N commitsThe worktree now matches the base
Already up to dateNothing to do
Cannot fast-forwardThe branch has commits of its own. The toast reports how far ahead and behind it is; rebase or merge inside the session instead
Uncommitted changesThe worktree is dirty. Commit or stash first, then re-run
Could not fetchOrigin was unreachable, so nothing was changed
No origin remoteThere is nothing to fetch from
Task ActionSessionWorktreeBranch
Move to active columnSpawns/resumesCreated (if new)Created (if new)
Move to To DoKilled, history wipedRemovedRemoved when Auto Cleanup is on (the default)
Move to Done / ArchiveSuspended, history keptRemoved (disk reclaimed)Removed when Auto Cleanup is on (the default); kept otherwise
Delete taskKilledRemovedRemoved

Moving a task to Done frees its disk space but keeps everything needed to resume: the conversation history is preserved, and dragging the task back to an active column recreates the worktree and resumes the agent with full context. In the normal case your work is already committed and merged (or pushed), so removing the worktree and branch loses nothing.

When a move would destroy real work - uncommitted files, or commits that exist only on the local branch about to be deleted - Kangentic shows a confirmation dialog first that red-flags exactly what would be lost. A clean move skips the prompt entirely. Moving to To Do is a full reset: it is treated as “not started”, so the session history is wiped along with the worktree.

The Auto Cleanup toggle (Settings > Git, git.autoCleanup) controls whether branches are deleted along with their worktrees. Turn it off to keep every task branch until you delete it yourself.

Removing a worktree also cleans up after the agents that ran in it. Several CLIs record folder trust per directory, keyed on the absolute path, and some of them do not inherit trust from a parent folder: Codex writes a trust_level entry into ~/.codex/config.toml, and Gemini, Grok Build, and Antigravity keep their own trusted-folder stores. Kangentic pre-approves each worktree on spawn so you are never prompted per task, then drops the entry again when the worktree goes, so those stores track live directories instead of accumulating one dead entry per task forever. The cleanup is best-effort: the worktree is already gone by then, and the worst case is a stale entry left behind.

When an agent completes its task, review the changes before merging:

Terminal window
# See what the agent changed
git diff main..fix-websocket-a1b2c3d4
# Merge when satisfied
git merge fix-websocket-a1b2c3d4

Since Kangentic uses standard git worktrees, you can interact with them using normal git commands:

Terminal window
# List all worktrees
git worktree list
# Navigate to a worktree (folders are named after the task number)
cd .kangentic/worktrees/42/

When an agent runs gh pr create or gh pr view in a worktree session, Kangentic automatically detects the PR URL from the terminal output and links it to the task. You can also link PRs manually with the kangentic_link_pr MCP tool from within an agent session.

Once a PR is linked, the task card shows a clickable PR status badge (open, draft, merged, or closed) that opens the PR. Kangentic refreshes linked-PR state in the background when you open a project and on a periodic timer - tune the interval with git.prRefreshIntervalMinutes (default: every 5 minutes; set to null to disable).

Since v0.36.0 the reconciles Kangentic performs itself are silent: the background sweep, the auto-link when a session goes idle, a PR URL spotted in the scrollback, the re-resolve that follows a link write, and the task detail’s own Link / refresh PR button all update the card without raising a toast. The discriminator is provenance, not volume: an agent’s own kangentic_update_task or kangentic_link_pr call is still announced, because that is genuinely news. Landing one PR used to raise three “Task updated by agent” toasts per task, two of which announced a round trip that netted to no change.

Next: Creating Tasks - configure worktree options when you create a task.

See also:

Kangentic is free and open source. A star helps other people find it.

Star on GitHub