Background
agent_cmd is configured today under [session] in ~/.wt/config.toml / .wt.toml:
[session]
agent_cmd = "claude"
It is only consumed by tmux session mode (wt session add, wt session) — the panes-mode and windows-mode tmux managers send_keys the configured agent command into the dedicated agent pane/window.
The other three commands that spawn a wt shell — wt new, wt use, and entering a worktree from the wt ls picker — go through spawn_wt_shell and drop the user into a bare interactive shell. There is no way to ask wt new to also start claude (or aider, or any other agent) automatically, even though the user has already named that command in their config.
This is a friction point for the core use case of the tool: spinning up a worktree to run an agent in. Users routinely wt new feature/foo followed immediately by claude (or whatever) — the second step should not be required.
What to build
Extend agent-command support to the non-session shell flows:
- Honour the existing
agent_cmd config value on wt new, wt use, and shells launched from the wt ls picker — but opt-in, so the default behaviour (bare wt shell) does not change for existing users.
- Add a
--agent boolean flag to wt new, wt use, and wt ls. When passed, after the wt shell is spawned, the configured agent_cmd is auto-run as the first command inside the new shell. Exiting the agent returns the user to the (wt) prompt; no tmux required.
- Add a
--agent-cmd <cmd> flag on the same commands. When passed, it overrides the config value for this invocation and implies --agent. Useful for one-off agent choices (wt new foo --agent-cmd aider) and for scripts.
- Precedence (highest to lowest):
--agent-cmd <cmd> > [session].agent_cmd from config > nothing (no agent runs).
Expected behaviour after this lands
$ wt new feature/auth --agent
Entering worktree: feature/auth
[claude starts inside the (wt) shell...]
$ wt use feature/auth --agent-cmd aider
Entering worktree: feature/auth
[aider starts inside the (wt) shell, regardless of config]
$ wt new feature/auth # unchanged behaviour
Entering worktree: feature/auth
(wt) $
Implementation notes
- The agent command should run inside the spawned wt shell (not as the foreground process), so that ^C or natural exit drops the user back to the
(wt) prompt rather than tearing down the whole shell. This matches how session mode works today (the agent runs in its own pane; exiting it does not destroy the session).
- For each shell wrapper in
src/shell.rs, append the agent invocation to the wrapper init script:
- bash — append the command to the temp rcfile written in
spawn_bash (currently a one-liner that sources ~/.bashrc and prefixes PS1).
- zsh — write a small
.zshrc (or extend the existing .zshenv) in the temp ZDOTDIR that runs the command after the user's startup chain finishes. Take care to do this in interactive contexts only.
- fish — append to the
--init-command argument used by spawn_fish.
- generic (
spawn_shell fallback) — emit a one-line warning to stderr that --agent is only supported on bash / zsh / fish, then proceed without running the agent.
- Plumb a new optional parameter (e.g.
agent: Option<String>) through spawn_wt_shell so the four shell-specific wrappers can decide what to inject. Resolve the value once in cmd_new / cmd_use / the wt ls selection branch by combining the CLI flag with Config::load_for_repo(...).session.agent_cmd.
- The
--agent-cmd <cmd> and --agent flags should be mutually compatible (--agent-cmd implies --agent); passing both with conflicting intent is fine — --agent-cmd wins.
- Keep
agent_cmd in [session] for now (it's already there and used by session mode); document in the README that it is now also consulted by wt new / wt use / wt ls when --agent is passed. A future refactor could promote it to a top-level [agent] section, but that is out of scope.
Acceptance criteria
Out of scope
- Promoting
agent_cmd out of [session] into a top-level [agent] config section.
- A way to launch the agent as the foreground process (replacing the wt shell rather than running inside it).
- Splitting agent vs. editor for the non-session flow —
editor_cmd parity can be a separate follow-up if desired.
Blocked by
None — can start immediately.
Background
agent_cmdis configured today under[session]in~/.wt/config.toml/.wt.toml:It is only consumed by tmux session mode (
wt session add,wt session) — the panes-mode and windows-mode tmux managerssend_keysthe configured agent command into the dedicated agent pane/window.The other three commands that spawn a wt shell —
wt new,wt use, and entering a worktree from thewt lspicker — go throughspawn_wt_shelland drop the user into a bare interactive shell. There is no way to askwt newto also startclaude(oraider, or any other agent) automatically, even though the user has already named that command in their config.This is a friction point for the core use case of the tool: spinning up a worktree to run an agent in. Users routinely
wt new feature/foofollowed immediately byclaude(or whatever) — the second step should not be required.What to build
Extend agent-command support to the non-session shell flows:
agent_cmdconfig value onwt new,wt use, and shells launched from thewt lspicker — but opt-in, so the default behaviour (bare wt shell) does not change for existing users.--agentboolean flag towt new,wt use, andwt ls. When passed, after the wt shell is spawned, the configuredagent_cmdis auto-run as the first command inside the new shell. Exiting the agent returns the user to the(wt)prompt; no tmux required.--agent-cmd <cmd>flag on the same commands. When passed, it overrides the config value for this invocation and implies--agent. Useful for one-off agent choices (wt new foo --agent-cmd aider) and for scripts.--agent-cmd <cmd>>[session].agent_cmdfrom config > nothing (no agent runs).Expected behaviour after this lands
Implementation notes
(wt)prompt rather than tearing down the whole shell. This matches how session mode works today (the agent runs in its own pane; exiting it does not destroy the session).src/shell.rs, append the agent invocation to the wrapper init script:spawn_bash(currently a one-liner that sources~/.bashrcand prefixesPS1)..zshrc(or extend the existing.zshenv) in the temp ZDOTDIR that runs the command after the user's startup chain finishes. Take care to do this in interactive contexts only.--init-commandargument used byspawn_fish.spawn_shellfallback) — emit a one-line warning to stderr that--agentis only supported on bash / zsh / fish, then proceed without running the agent.agent: Option<String>) throughspawn_wt_shellso the four shell-specific wrappers can decide what to inject. Resolve the value once incmd_new/cmd_use/ thewt lsselection branch by combining the CLI flag withConfig::load_for_repo(...).session.agent_cmd.--agent-cmd <cmd>and--agentflags should be mutually compatible (--agent-cmdimplies--agent); passing both with conflicting intent is fine —--agent-cmdwins.agent_cmdin[session]for now (it's already there and used by session mode); document in the README that it is now also consulted bywt new/wt use/wt lswhen--agentis passed. A future refactor could promote it to a top-level[agent]section, but that is out of scope.Acceptance criteria
wt new <name> --agentspawns the wt shell and auto-runs the configuredagent_cmdinside it. Exiting the agent leaves the user at the(wt)prompt.wt use <name> --agent-cmd <cmd>spawns the wt shell and auto-runs<cmd>inside it, regardless of config.wt lshonours the same flags (passed on thewt lsinvocation) aswt new/wt use.wt new <name>with neither flag preserves today's behaviour exactly (regression test).agent_cmd = "claude"in config,wt new foo --agent-cmd aiderrunsaider;wt new foo --agentrunsclaude;wt new fooruns nothing.--print-pathcontinues to print the path and exit without spawning a shell or running an agent (these flags are mutually exclusive in effect).agent_cmdis now consulted bywt new/wt use/wt ls(gated on--agent), in addition to session mode. The "CLI Reference" section gains the--agentand--agent-cmdflags.Out of scope
agent_cmdout of[session]into a top-level[agent]config section.editor_cmdparity can be a separate follow-up if desired.Blocked by
None — can start immediately.