feat(app): full editable launch command line in the agent options box - #110
Conversation
…oard The 320px nav-rail service row was breaking: the non-shrinking path detail collapsed the service name to nothing and slid under the action button, and the 28px button made service rows taller than agent rows. - Drop the noisy path/preview detail in the sidebar (it stays in the full-width dashboard and the service detail screen); the service name now always shows. - Give agent and service child rows a uniform min-h so the action button no longer changes row height. - Left-align the worktree branch suffix right after the name, matching the full-width dashboard instead of pushing it ragged-right. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring back the pre-restyle BranchChip look the user liked — a GitBranch glyph plus the branch name in a subtle bordered mono pill — adapted to the current Linear palette. Shared from status-dot.tsx so the sidebar tree and the full-width dashboard render branch suffixes identically. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Web pointer feedback was missing — only active (press) states existed. Add a hover:bg-[#232429] highlight (mockup --hover) to the interactive rows in both the sidebar tree and the full-width dashboard, and bump press to the selected tone (#26272d) so hover and press read as distinct steps. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…line
Pressing "o" in the tool picker now opens an editable command line
pre-filled with the tool's default command + args, instead of an
append-only "extra args" field. Leading NAME=VALUE tokens become
environment variables (e.g. CLAUDE_YOLO=1 claude --resume), the binary
and args are fully editable, and aimux re-applies its hooks/session
tracking only when the binary is unchanged.
Cuts over the append-only extraArgs spawn/fork model to a structured
LaunchOverride { command, args, env } threaded through dashboard-ops,
the metadata server, and createSession; env is merged into the existing
managed-launch env wrapper for claude, shell-integrated tools, and
arbitrary binaries.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
More reviews will be available in 29 minutes and 48 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR introduces a launch override feature allowing custom agent startup commands with environment variables, alongside UI improvements. The ChangesUI Styling and Branch Chip Component
Launch Override Feature
Sequence Diagram(s)sequenceDiagram
participant ToolPicker
participant Multiplexer
participant MetadataServer
participant Host
ToolPicker->>Multiplexer: runSelectedTool({ override: LaunchOverride })
Multiplexer->>Multiplexer: createSession(command,args,launchEnv)
Multiplexer->>MetadataServer: POST /agents/spawn { launchOverride }
MetadataServer->>Host: lifecycle.spawnAgent(..., launchOverride)
Host->>Host: createSessionImpl(using override.command/args and env)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/multiplexer/session-launch.ts (2)
481-497:⚠️ Potential issue | 🟠 Major | ⚡ Quick winBlock reserved AIMUX env overrides from
launchEnv.At Line 484 and Line 496, user-provided env is merged/passed unfiltered, so
AIMUX_SESSION_ID,AIMUX_TOOL, and related integration keys can be overridden. That can corrupt turn tracking/context attribution.💡 Suggested fix
+const RESERVED_AIMUX_ENV_PREFIX = "AIMUX_"; +const ENV_KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/; + +function sanitizeLaunchEnv(input?: Record<string, string>): Record<string, string> { + if (!input) return {}; + return Object.fromEntries( + Object.entries(input).filter( + ([key]) => ENV_KEY_PATTERN.test(key) && !key.startsWith(RESERVED_AIMUX_ENV_PREFIX), + ), + ); +} @@ - if (toolCfg && toolConfigKey === "claude" && toolCfg.command === command && toolCfg.wrapperEnabled !== false) { + const safeLaunchEnv = sanitizeLaunchEnv(launchEnv); + if (toolCfg && toolConfigKey === "claude" && toolCfg.command === command && toolCfg.wrapperEnabled !== false) { @@ - ...(launchEnv ?? {}), + ...safeLaunchEnv, }, @@ - extraEnv: launchEnv, + extraEnv: safeLaunchEnv, @@ - } else if (launchEnv && Object.keys(launchEnv).length > 0) { + } else if (Object.keys(safeLaunchEnv).length > 0) { @@ - extraEnv: launchEnv, + extraEnv: safeLaunchEnv, });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/multiplexer/session-launch.ts` around lines 481 - 497, The user-provided launchEnv is currently merged directly into extraEnv in the wrapCommandWithShellIntegration calls, letting keys like AIMUX_SESSION_ID and AIMUX_TOOL be overridden; fix this by filtering reserved AIMUX keys before merging: add a small helper (e.g., filterReservedAIMUXEnv or sanitizeLaunchEnv) that removes any AIMUX_* keys (at minimum AIMUX_SESSION_ID and AIMUX_TOOL, plus any other internal AIMUX_* names) from launchEnv and use the sanitized result when constructing extraEnv for the wrapCommandWithShellIntegration calls so reserved variables cannot be overwritten.
440-460:⚠️ Potential issue | 🟠 Major | ⚡ Quick winPrevent tool flags/preambles from leaking into overridden commands.
At Line 440 and Line 457, preamble/session-id flags are still injected even when
command !== toolCfg.command. That breaks arbitrary override commands and contradicts the “different binary launches without hooks/preamble/session-id flags” behavior.💡 Suggested fix
+ const isConfiguredToolCommand = Boolean(toolCfg && toolCfg.command === command); const effectiveSuppressStartupPreamble = suppressStartupPreamble; - const effectiveSessionIdFlag = isClaudeResumeStyleLaunch ? undefined : sessionIdFlag; + const effectiveSessionIdFlag = + isConfiguredToolCommand && !isClaudeResumeStyleLaunch ? sessionIdFlag : undefined; @@ - const shouldInjectLaunchPreamble = Boolean(!effectiveSuppressStartupPreamble && preambleFlag && preamble.trim()); + const shouldInjectLaunchPreamble = Boolean( + isConfiguredToolCommand && !effectiveSuppressStartupPreamble && preambleFlag && preamble.trim(), + );🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/multiplexer/session-launch.ts` around lines 440 - 460, The preamble and session-id flags are being appended even when the caller has overridden the launch command; update the injection guards so these flags are only added when launching the tool's original command (i.e. when toolCfg?.command === command) — specifically: tighten shouldInjectLaunchPreamble to include toolCfg?.command === command (or only compute it when toolCfg exists and matches command), keep shouldInjectCodexDeveloperInstructions as-is or also ensure toolCfg?.command === command, and wrap the effectiveSessionIdFlag append (the expandedFlag logic that mutates finalArgs) behind the same toolCfg?.command === command check; use the existing symbols (shouldInjectLaunchPreamble, shouldInjectCodexDeveloperInstructions, injectCodexDeveloperInstructions, effectiveSessionIdFlag, finalArgs, toolCfg, command, backendSessionId) to locate and modify the conditionals so overridden commands do not receive preamble/session-id flags.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/multiplexer/session-launch.ts`:
- Around line 481-497: The user-provided launchEnv is currently merged directly
into extraEnv in the wrapCommandWithShellIntegration calls, letting keys like
AIMUX_SESSION_ID and AIMUX_TOOL be overridden; fix this by filtering reserved
AIMUX keys before merging: add a small helper (e.g., filterReservedAIMUXEnv or
sanitizeLaunchEnv) that removes any AIMUX_* keys (at minimum AIMUX_SESSION_ID
and AIMUX_TOOL, plus any other internal AIMUX_* names) from launchEnv and use
the sanitized result when constructing extraEnv for the
wrapCommandWithShellIntegration calls so reserved variables cannot be
overwritten.
- Around line 440-460: The preamble and session-id flags are being appended even
when the caller has overridden the launch command; update the injection guards
so these flags are only added when launching the tool's original command (i.e.
when toolCfg?.command === command) — specifically: tighten
shouldInjectLaunchPreamble to include toolCfg?.command === command (or only
compute it when toolCfg exists and matches command), keep
shouldInjectCodexDeveloperInstructions as-is or also ensure toolCfg?.command ===
command, and wrap the effectiveSessionIdFlag append (the expandedFlag logic that
mutates finalArgs) behind the same toolCfg?.command === command check; use the
existing symbols (shouldInjectLaunchPreamble,
shouldInjectCodexDeveloperInstructions, injectCodexDeveloperInstructions,
effectiveSessionIdFlag, finalArgs, toolCfg, command, backendSessionId) to locate
and modify the conditionals so overridden commands do not receive
preamble/session-id flags.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 8979e29c-45c1-44e5-acda-7c3966dcb10f
📒 Files selected for processing (14)
app/components/ProjectSidebar.tsxapp/components/WorktreeDashboard.tsxapp/components/status-dot.tsxsrc/metadata-server.tssrc/multiplexer/dashboard-model.tssrc/multiplexer/dashboard-ops.tssrc/multiplexer/dashboard-tail-methods.test.tssrc/multiplexer/dashboard-tail-methods.tssrc/multiplexer/index.tssrc/multiplexer/session-launch.tssrc/multiplexer/tool-picker.tssrc/shell-args.test.tssrc/shell-args.tssrc/shell-hooks.ts
Two issues found in review of the launch-override feature: - User-supplied env could override aimux's reserved control vars (AIMUX_SESSION_ID, AIMUX_TOOL, metadata/integration paths). Reorder so the reserved keys always win, in both the managed-env wrapper (session-launch.ts) and the shell-integration wrapper (shell-hooks.ts). - Session-id and preamble flags were still injected when the launch command was overridden to a different binary, contradicting the "different binary launches without aimux hooks" behavior. Gate both on the command still matching the tool's configured command. Adds regression tests for env precedence and overridden-binary launches. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/multiplexer/session-launch.ts (1)
410-411: ⚡ Quick winConsider using
isConfiguredToolCommandin the condition at line 494 for consistency.You've introduced
isConfiguredToolCommandat lines 410-411 to encapsulate the checktoolCfg && toolCfg.command === command. At line 494, the same check is repeated explicitly. Using theisConfiguredToolCommandvariable here would improve consistency and make the intent clearer.♻️ Suggested refactor
- } else if (toolCfg && toolCfg.command === command) { + } else if (isConfiguredToolCommand) { const wrapped = wrapCommandWithShellIntegration({Also applies to: 494-494
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/multiplexer/session-launch.ts` around lines 410 - 411, Replace the duplicated inline check (toolCfg && toolCfg.command === command) at the conditional around the earlier use (currently at the location with the explicit check) with the existing boolean variable isConfiguredToolCommand so the condition uses isConfiguredToolCommand for consistency with the earlier declaration; ensure you keep the same logical grouping/short-circuit behavior and update any combined boolean expressions to reference isConfiguredToolCommand instead of repeating toolCfg && toolCfg.command === command.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/multiplexer/session-launch.ts`:
- Around line 410-411: Replace the duplicated inline check (toolCfg &&
toolCfg.command === command) at the conditional around the earlier use
(currently at the location with the explicit check) with the existing boolean
variable isConfiguredToolCommand so the condition uses isConfiguredToolCommand
for consistency with the earlier declaration; ensure you keep the same logical
grouping/short-circuit behavior and update any combined boolean expressions to
reference isConfiguredToolCommand instead of repeating toolCfg &&
toolCfg.command === command.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2c7d91be-2355-4e31-bbd7-456d6777c8e0
📒 Files selected for processing (4)
src/multiplexer/session-launch.test.tssrc/multiplexer/session-launch.tssrc/shell-hooks.test.tssrc/shell-hooks.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/shell-hooks.ts
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
Pressing
oin the tool picker (when spawning/forking an agent) now opens an editable command line instead of an append-only "extra args" field. It pre-fills the tool's default command + args and lets you change everything.KEY=VALUEtokens become environment variables, e.g.CLAUDE_YOLO=1 claude --resume. They flow into theenv -i …wrapper aimux already uses to launch every agent.Why
Power users need to prepend env vars (e.g.
CLAUDE_YOLO=1) and otherwise tweak the exact launch command. The previous box could only append args.How
Cuts over the append-only
extraArgsspawn/fork model to a structuredLaunchOverride { command, args, env }, threaded throughdashboard-ops→ metadata server (/agents/spawn,/agents/fork) →dashboard-model→dashboard-tail-methods/forkSessionFromSource→createSession. The newenvis merged into the managed-launch env wrapper across the claude, shell-integration, and arbitrary-binary branches. The separate teammate-creationextraArgsappend path is left untouched.New
parseLaunchCommandLine()inshell-args.tssplits the env prefix / command / args.Test
tsc --noEmitclean, eslint clean on changed filesdashboard-tail-methodstests to the new API; added 6 parser tests)tscbuild succeeds🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Style