Configuration
worktree stores config in local Git config under northguild.worktree.*.
Common Keys
defaultSourceBranch(example:origin/main) — see Default source branchopener(editor,herdrornone, defaulteditor)codeEditor(example:code)herdr.focus(trueorfalse, defaulttrue)herdr.agent(example:claude; the agent kind that starts in every new Herdr space. Unset means no agent, unlessworktree branchorcheckoutis given a brief, which falls back toagent.command’s program)agent.command(the command--agentruns to hand a brief to a coding agent, example:claude --bg)postCreate(a command to run in each new worktree, example:pnpm install; unset means infer from the lockfile)github.token(GitHub personal access token)github.autoAssign(trueorfalse, unset means you are asked, or assigned when non-interactive)jira.host(Your Jira workspace URL, example:https://company.atlassian.net)jira.email(Your Jira email address)jira.apiToken(Jira API token)branchPrefix.feature(example:feature/)branchPrefix.bugfix(example:fix/)branchPrefix.chore(example:chore/)
Default source branch
defaultSourceBranch answers two questions, and they are not the same one.
Where a new branch starts. worktree branch uses it when you pass no
--source, and prompts if it is unset.
What counts as unpushed work. list, cleanup and remove compare each
worktree against a base to decide how many commits it carries that nowhere else
has. That base is origin/HEAD — the repository’s own record of its default
branch — and defaultSourceBranch is the fallback when origin/HEAD is not
set, which happens in clones made before git began recording it.
It is also the base a merged branch is recognised against. Where a worktree is
ahead of it, the change it carries is compared with what that base already holds
— so a squash-merged or rebased branch, whose commits survive under new
identities, is seen for what it is rather than counted as work at risk. See
cleanup for what that does and does not permit.
origin/HEAD is asked first deliberately. If the config key were read first,
setting it to origin/develop because that is where you branch from would also
change which commits count as unpushed, and a worktree could be classified as
safe to delete on the strength of a preference about branching.
If neither resolves, no count is taken. Nothing is guessed and nothing is treated as zero, and a worktree whose directory still exists is never classified as safe to remove — an unanswered question is not an answer of “nothing”.
All three commands say so rather than leaving you to guess.
list and remove’s picker
name such a worktree as uncountable, and cleanup
reports it under its own heading rather than sweeping it or passing over it in
silence. To fix it, set the key or
restore the ref:
worktree config defaultSourceBranch origin/main
# or, to let git record it again:
git remote set-head origin --autoEditor Command
codeEditor is a command line, not just a program name. It is split on whitespace: the first word is the
program to launch, and anything after it is passed to that program as arguments, ahead of the worktree
path.
worktree config codeEditor code # runs: code <worktree-path>
worktree config codeEditor "code -n" # runs: code -n <worktree-path>The worktree path is always passed as a single argument, so a project or branch whose path contains a space opens correctly.
Quotes group, so an argument containing a space survives:
worktree config codeEditor 'open -a "Sublime Text"' # runs: open -a "Sublime Text" <worktree-path>Quote characters are removed by the split and never reach the program. Nothing else is interpreted: no
shell parses this value, so ~ and $EDITOR are passed through literally rather than expanded, and a
backslash is an ordinary character rather than an escape. Quote an argument like this instead of writing
an\ argument\ like\ this, and use an absolute path or a wrapper script on your PATH rather than
relying on expansion.
Agent Command
agent.command is the command that --agent runs to hand a brief to a coding agent. It does not start an agent on its own: without a brief, only herdr.agent does. The agent that starts in every new Herdr space, brief or not, is herdr.agent. Like codeEditor it is a command
line, not just a program name, and it is split the same way: the first word is the program to launch, and
anything after it is passed to that program as leading arguments.
worktree config agent.command claude
worktree config agent.command "claude --bg"
worktree config agent.command "codex exec"Only the first word is checked when you set the value, so flags and subcommands do not have to resolve to anything on their own:
worktree config agent.command "claude --bg" # accepted — only `claude` is looked up
worktree config agent.command "nope --bg" # rejected — Command not found: nopeworktree does not assume a particular agent. There is no default value, and nothing about this key is
specific to one vendor — any agent CLI of the same shape works. The same rules as
Editor Command apply: no shell parses the value, quotes group an argument containing a
space, and ~ and $VAR are not expanded.
The key is optional and unset by default.
When the worktree opens as a Herdr space, the agent is started by Herdr instead, and agent.command only
supplies what to start: its program is the agent kind when a brief is given and herdr.agent is unset, and its
arguments are reused when the program is that kind — without --bg or --background, which would take the
agent out of the pane. For claude, --name <repo>-<branch> is added. See
Agent Dispatch.
Post-create Command
postCreate is the command worktree branch runs in a new worktree to install its dependencies. It is a
command line, split and validated exactly like agent.command: the first word is the program and has to be
on PATH when you set it, quotes group an argument containing a space, and no shell parses the value.
worktree config postCreate "pnpm install"
worktree config postCreate "make setup"When it is set it is used as written, and it also turns the install on for a terminal run. When it is
unset, branch infers the command from the new worktree’s lockfile (pnpm-lock.yaml, package-lock.json,
yarn.lock, then bun.lock) and installs by default only when non-interactive. --no-install skips it for
one run. See branch.
The key is optional and unset by default.
Platform Support
worktree is developed and tested on macOS and Linux. Windows is not supported. Nothing here is
launched through a shell, so a .cmd or .bat shim — which is what code is on Windows — cannot be
started, and Herdr is a unix-socket application.
Commands
worktree config --list
worktree config --missing
worktree config --missing --names defaultSourceBranch,github.token
worktree config defaultSourceBranch origin/main
worktree config codeEditor code
worktree config opener herdr
worktree config herdr.focus false
worktree config herdr.agent claude
worktree config agent.command "claude --bg"
worktree config postCreate "pnpm install"
worktree config github.token <token>
worktree config jira.host https://company.atlassian.net
worktree config jira.email your-email@example.com
worktree config jira.apiToken <api-token>
worktree config branchPrefix.feature feature/
worktree config branchPrefix.bugfix fix/
worktree config branchPrefix.chore chore/Opener Notes
openerselects where a finished worktree is handed off:editorusescodeEditor,herdropens it as a Herdr space — and closes that space again when the worktree is removed, andnoneopens nothing: the command printsWorktree created at <path>and stops. Unset meanseditor.codeEditoris used only by theeditoropener — see Editor Command above and the Editor Integration guide.herdr.focusandherdr.agentapply only whenopenerisherdr. See Herdr Spaces.herdr.focusandherdr.agentare shown byworktree configonly when theherdrCLI is on yourPATH. Without it they are neither listed nor prompted for, so the feature stays out of the way. This gating never hides a key that already holds a value, and settingopenertoherdrun-hides both whether or not the CLI is found.openeritself is always shown. Naming a key with--names, or setting it directly, always works.
GitHub Integration Notes
worktree branch --github <issue-number>reads issues from the current repository remote.- Branch prefix keys are optional. If missing,
worktreeuses no prefix. - If
github.tokenis missing,worktreecan attempt to usegh auth tokenand then prompt. github.autoAssigndecides whether reading an issue also assigns it to you. It has three states, not two:truealways assigns,falsenever does, and leaving it unset means you are asked, once, and your answer is saved to this key. A non-interactive run does not ask: it assigns and saves nothing. Assigning needs a token with push access to the repository.worktree branch --assignand--no-assignoverride the key for a single run, whatever it holds. Seebranch.- If you answered no and want the offer back, set the key directly:
worktree config github.autoAssign truegithub.tokenandgithub.autoAssignare prompted together, behind one confirm, soworktree configcosts a single yes/no to anyone who does not use GitHub issues.
Jira Integration Notes
worktree branch --jira <issue-id>reads issues from your configured Jira workspace.- All three Jira config keys (
jira.host,jira.email,jira.apiToken) are required. - Branch prefix keys are optional. If missing,
worktreeuses no prefix. - Issue IDs are case-insensitive (both
dev-123andDEV-123work).
Recommended Team Baseline
- Agree on one source branch (
origin/mainfor most teams). - Standardize branch naming conventions.
- Keep editor command consistent across local setups.
- For Jira integration, share workspace URL and branch prefix conventions.