Skip to content

-a/--agent overwrites explicit pane commands in multi-window session configs, spawning duplicate agents #243

Description

@celsobenedetti

Summary

When workmux add is run with -a/--agent <name> on a session-mode config that defines multiple windows, the agent command overwrites the pane command of every window that doesn't already contain an agent pane — including explicitly configured editor/dev-server panes.

Example config:

mode: session
windows:
  - name: neovim
    panes:
      - command: nvim
  - name: agent
    panes:
      - command: <agent>
        focus: true

Run: workmux add my-task -a pi

Expected: window 1 runs nvim, window 2 runs pi.

Actual: window 1 also runs pi (a second agent) — nvim is gone.

Root cause

resolve_pane_configuration() in src/workflow/setup.rs runs per window whenever -a is passed. Its fallback logic replaces the focused/first pane's command with <agent> when no pane in that window "runs an agent":

if let Some(focused) = panes.iter_mut().find(|pane| pane.focus) {
    focused.command = Some("<agent>".into());   // clobbers explicit commands
    return panes;
}
if let Some(first) = panes.get_mut(0) {
    first.command = Some("<agent>".into());
    return panes;
}

The "agent" window is spared because its <agent> placeholder makes pane_runs_agent() return true. The "neovim" window is not — nvim is an explicit command, not an agent, so it gets overwritten.

This is particularly bad for multi-window configs where the user already designated which window runs the agent: -a should only affect <agent> placeholder resolution, never rewrite sibling windows' commands.

Reproduction

  1. Config as above.
  2. workmux add repro -a pi (or claude).
  3. Inspect panes: tmux list-panes -a -F '#{pane_current_command}' → both windows run the agent.

Proposed fix (pseudo code)

Never overwrite an explicit pane command. Inject <agent> only into command-less (plain shell) panes or empty layouts:

fn resolve_pane_configuration(panes, config, agent):
    if agent is None:
        return panes
    if any pane in panes runs the agent (placeholder or known agent):
        return panes                       # layout already has an agent pane

    # prefer focused pane without a command, else first pane without a command
    target = first pane where (focus and command is None)
             else first pane where command is None
    if target exists:
        target.command = "<agent>"
        return panes

    if panes is empty:
        return [ { command: "<agent>", focus: true } ]   # default layout

    return panes                           # all panes explicit: leave untouched

Behavior change: with -a and a layout whose panes all have explicit commands, no agent is injected — the -a flag then only affects <agent> placeholder substitution and branch naming. Users who want an agent pane add <agent> (or a command-less pane) explicitly. The default (no panes/windows config) is unaffected: empty layout still gets a fresh agent pane.

Notes

  • Present in v0.1.240 and latest master.
  • Existing tests codifying the old behavior (agent_sets_focused_pane, agent_sets_first_pane_when_no_focus, preserves_named_profile_selector) need updating to assert explicit commands are preserved.
  • Reproduced and verified locally; happy to open a PR with the fix + regression tests.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions