Read-side introspection for git worktrees.
Claude Code's --worktree [name] flag (and its DuplexSession
equivalent) creates fresh git worktrees so an agent's writes can land
somewhere other than the current working tree. Hosts that orchestrate
worktree-isolated chats need a way to enumerate the worktrees that
exist for a given repo, see what branches they're on, and notice when
one is locked or prunable.
This module is a thin Elixir API over git worktree list --porcelain.
It is read-only on purpose; mutations (pruning, removing worktrees) are
out of scope so consumers that only want to introspect don't opt into
write semantics.
Why shell out
Reading .git/worktrees/ directly is brittle: git tracks locked,
prunable, detached-HEAD, and bare-repo state in ways that have
evolved across releases. Asking git itself is the cheap, correct
option, and git is already a transitive dependency of any
worktree-using workflow.
Example
{:ok, root} = ClaudeWrapper.Worktrees.for_repo(".")
{:ok, worktrees} = ClaudeWrapper.Worktrees.list(root)
for wt <- worktrees do
IO.puts("#{wt.path} #{wt.branch || "(detached)"}")
end
Summary
Functions
Address worktrees for the repository containing path.
List every worktree git knows about for this repository.
The configured repository path.
Types
@type t() :: %ClaudeWrapper.Worktrees{repo_path: String.t()}
Functions
@spec for_repo(String.t()) :: {:ok, t()} | {:error, ClaudeWrapper.Error.t()}
Address worktrees for the repository containing path.
path can be any directory inside the repo; git's -C handling
resolves the .git itself. Runs git worktree list --porcelain once
to validate that path is in fact inside a git repository.
Returns {:error, %ClaudeWrapper.Error{kind: :not_a_git_repo}} when
path is not inside a repository (the path is in :reason),
{:error, %ClaudeWrapper.Error{kind: :git_failed}} for other non-zero
git exits, and {:error, %ClaudeWrapper.Error{kind: :git_unavailable}}
when the git binary cannot be spawned.
@spec list(t()) :: {:ok, [ClaudeWrapper.Worktrees.Worktree.t()]} | {:error, ClaudeWrapper.Error.t()}
List every worktree git knows about for this repository.
Spawns git -C <repo_path> worktree list --porcelain and parses the
output. The first entry is the main worktree (is_main? == true).
Returns the same error shapes as for_repo/1.
The configured repository path.