Skip to content

feat(app): full editable launch command line in the agent options box - #110

Merged
TraderSamwise merged 6 commits into
masterfrom
custom-agent-start
Jun 8, 2026
Merged

feat(app): full editable launch command line in the agent options box#110
TraderSamwise merged 6 commits into
masterfrom
custom-agent-start

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented Jun 8, 2026

Copy link
Copy Markdown
Owner

What

Pressing o in 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.

  • Env prefix — leading KEY=VALUE tokens become environment variables, e.g. CLAUDE_YOLO=1 claude --resume. They flow into the env -i … wrapper aimux already uses to launch every agent.
  • Full edit — swap the binary, rewrite args freely.
  • Smart wrapping — if the binary still equals the tool's configured command, aimux re-applies its hooks/session-id/preamble so turn-tracking and context capture keep working. Swap to a different binary and it launches without them. The overlay states which case applies.

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 extraArgs spawn/fork model to a structured LaunchOverride { command, args, env }, threaded through dashboard-ops → metadata server (/agents/spawn, /agents/fork) → dashboard-modeldashboard-tail-methods / forkSessionFromSourcecreateSession. The new env is merged into the managed-launch env wrapper across the claude, shell-integration, and arbitrary-binary branches. The separate teammate-creation extraArgs append path is left untouched.

New parseLaunchCommandLine() in shell-args.ts splits the env prefix / command / args.

Test

  • tsc --noEmit clean, eslint clean on changed files
  • Full suite: 1043 passed (updated 2 dashboard-tail-methods tests to the new API; added 6 parser tests)
  • tsc build succeeds

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Support for per-session custom launch commands and environment overrides when spawning or forking agents.
    • Tool options now parse full launch command lines and show a launch preview including env entries.
  • Style

    • Improved sidebar hover backgrounds and interaction feedback; branch labels now use compact branch chips.
    • Service rows streamlined to remove the secondary detail/preview line.

test and others added 4 commits June 7, 2026 19:19
…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>
@vercel

vercel Bot commented Jun 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app Ready Ready Preview, Comment Jun 8, 2026 4:38am

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@TraderSamwise, we couldn't start this review because you've reached your PR review rate limit.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d7c0815b-4150-4657-ae5b-e94096df2d50

📥 Commits

Reviewing files that changed from the base of the PR and between ad0ffff and 1c50880.

📒 Files selected for processing (1)
  • src/multiplexer/session-launch.ts
📝 Walkthrough

Walkthrough

This PR introduces a launch override feature allowing custom agent startup commands with environment variables, alongside UI improvements. The LaunchOverride type and parseLaunchCommandLine function enable users to specify commands in tool options, which flow through session creation, multiplexer, and dashboard operations to the server. UI components gain hover styling and use a new BranchChip component for consistent branch display.

Changes

UI Styling and Branch Chip Component

Layer / File(s) Summary
BranchChip component
app/components/status-dot.tsx
New exported BranchChip component renders a GitBranch icon with a styled, truncated branch name in a compact pill-shaped container.
Sidebar and dashboard styling updates
app/components/ProjectSidebar.tsx, app/components/WorktreeDashboard.tsx
Pressable elements across sidebar and dashboard now include hover:bg styling. WorktreeGroup and ServiceRow replace plain-text branch display with BranchChip component usage and remove the ServiceRow detail/preview line.

Launch Override Feature

Layer / File(s) Summary
LaunchOverride type and parser
src/shell-args.ts, src/shell-args.test.ts
Defines LaunchOverride interface (command, args, optional env). Implements parseLaunchCommandLine to parse shell command lines with leading NAME=VALUE env assignments followed by command and args; tests cover parsing variants and errors.
Shell hooks environment injection
src/shell-hooks.ts, src/shell-hooks.test.ts
wrapCommandWithShellIntegration gains optional extraEnv parameter; env entries are stringified and appended to shell integration env args; tests verify ordering prevents overwriting Aimux vars.
Session creation with launch environment
src/multiplexer/session-launch.ts, src/multiplexer/session-launch.test.ts
createSession accepts optional launchEnv and threads it into Claude wrapper, shell-integration wrapper, and managed-launch-env fallback; injection of session-id/preamble flags is gated on whether the launched command matches the configured tool.
Multiplexer session management
src/multiplexer/index.ts
Multiplexer.createSession method signature adds launchEnv?: Record<string,string>. forkSessionFromSource accepts optional launchOverride and uses override.command/args/env for forked sessions when present.
Tool picker command-line override UI
src/multiplexer/tool-picker.ts
Tool-options overlay parses buffer via parseLaunchCommandLine, displays env entries and launch preview, and signals whether hooks apply. runSelectedTool signature changes to accept override?: LaunchOverride and sessions use override fields directly.
Dashboard tail methods agent launching
src/multiplexer/dashboard-tail-methods.ts, src/multiplexer/dashboard-tail-methods.test.ts
forkAgent and spawnAgent options now include launchOverride; implementations forward override command/args/env into session creation/forking. Tests updated to assert the new override shape and env propagation.
Dashboard operations wiring
src/multiplexer/dashboard-ops.ts
spawnDashboardAgentWithFeedback and forkDashboardAgentWithFeedback accept optional launchOverride and include it in POST payloads to /agents/spawn and /agents/fork.
Dashboard model lifecycle
src/multiplexer/dashboard-model.ts
Lifecycle handlers forward incoming launchOverride through to host.spawnAgent and host.forkAgent.
Metadata server API types
src/metadata-server.ts
Imports LaunchOverride and extends MetadataServerOptions.lifecycle.spawnAgent/forkAgent input types and the POST /agents/spawn and /agents/fork request body typings to include optional launchOverride.

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)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • TraderSamwise/aimux#107: Modifies the same UI components (ProjectSidebar.tsx, status-dot.tsx) for branch and status display rendering, creating direct overlap with this PR's UI improvements.
  • TraderSamwise/aimux#104: Touches createSession/session-launch behavior around CLAUDE session-id/back-end session-id logic; related to gating and wrapper behavior adjusted here.
  • TraderSamwise/aimux#39: Also modifies session-launch.ts logic and CLAUDE wrapper behavior; relevant to the preamble/session-id gating changes.

Poem

🐇 BranchChip gleams as I nibble the code,
Env vars hop in a tidy, parsed mode,
Hover states blossom on sidebar rows,
LaunchOverride seeds where the shell wind blows,
A rabbit-cheered release — quick, light, and bold!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: enabling full editable launch command lines in the agent options interface, which is the central change across the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch custom-agent-start

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Block 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 win

Prevent 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

📥 Commits

Reviewing files that changed from the base of the PR and between 2753549 and baa2575.

📒 Files selected for processing (14)
  • app/components/ProjectSidebar.tsx
  • app/components/WorktreeDashboard.tsx
  • app/components/status-dot.tsx
  • src/metadata-server.ts
  • src/multiplexer/dashboard-model.ts
  • src/multiplexer/dashboard-ops.ts
  • src/multiplexer/dashboard-tail-methods.test.ts
  • src/multiplexer/dashboard-tail-methods.ts
  • src/multiplexer/index.ts
  • src/multiplexer/session-launch.ts
  • src/multiplexer/tool-picker.ts
  • src/shell-args.test.ts
  • src/shell-args.ts
  • src/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>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/multiplexer/session-launch.ts (1)

410-411: ⚡ Quick win

Consider using isConfiguredToolCommand in the condition at line 494 for consistency.

You've introduced isConfiguredToolCommand at lines 410-411 to encapsulate the check toolCfg && toolCfg.command === command. At line 494, the same check is repeated explicitly. Using the isConfiguredToolCommand variable 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

📥 Commits

Reviewing files that changed from the base of the PR and between baa2575 and ad0ffff.

📒 Files selected for processing (4)
  • src/multiplexer/session-launch.test.ts
  • src/multiplexer/session-launch.ts
  • src/shell-hooks.test.ts
  • src/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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant