Skip to content

feat(app): structured launch options with per-tool default args/env - #111

Merged
TraderSamwise merged 5 commits into
masterfrom
feat/structured-launch-options
Jun 8, 2026
Merged

feat(app): structured launch options with per-tool default args/env#111
TraderSamwise merged 5 commits into
masterfrom
feat/structured-launch-options

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Summary

Reworks the agent-launch o options dialog into a structured, power-user-friendly editor and adds per-tool launch defaults.

  • Structured o dialog — two editable fields, Extra args and Env vars, with cursor-aware line editing (emacs-style ctrl-a/e/u/k/w, arrows, home/end), a read-only Defaults: preview of the tool's base command, and a live preview of the final launch command with inline parse errors.
  • Env var prepending — you can set env like CLAUDE_YOLO=1 that gets wrapped into the launch (env KEY=VALUE … <command> <args>), the original motivation for this work.
  • Per-tool defaults — new optional defaultArgs / defaultEnv on ToolConfig. They apply on a plain launch and prefill (editable) in the o dialog, so configured defaults are visible and overridable.
  • Smart-wrapping invariant — aimux session-id flag, startup preamble, and shell hooks are injected only when the launch command still matches the tool's own binary (isConfiguredToolCommand). Swapping the binary opts out cleanly. Reserved aimux env vars always win over user-supplied env.

Implementation

  • src/line-editor.ts (new) — reusable LineState + applyLineEdit + renderLineWindow with horizontal scroll and reverse-video cursor.
  • src/shell-args.tsLaunchOverride, parseShellArgs, parseEnvAssignments.
  • src/multiplexer/tool-picker.ts — structured overlay, formatEnvDefaults, defaultsLaunchOverride.
  • src/config.tsToolConfig.defaultArgs / defaultEnv.

Test plan

  • src/line-editor.test.ts, src/multiplexer/tool-picker.test.ts, src/shell-args.test.ts cover line editing, defaults override construction, env formatting, and shell-arg parsing.
  • tsc --noEmit clean; full vitest suite green; yarn build succeeds.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Tools can now include default CLI arguments and environment variables applied at launch.
    • Added an inline single-line editor with cursor, navigation, edit shortcuts and rendered cursor highlighting for editing args/env.
  • Refactor

    • Redesigned tool-options overlay to use a structured edit state with improved validation and clearer error handling.
  • Tests

    • Added comprehensive tests for editor behavior, env parsing, and launch-default handling.

test and others added 4 commits June 8, 2026 13:44
Introduces src/line-editor.ts: a single-line text input with a cursor
(insert at cursor, ←/→, home/end, backspace/delete, and emacs ctrl
a/e/u/k/w bindings) plus renderLineWindow, which horizontally scrolls so
the cursor stays visible within a width and draws a reverse-video cursor.

Makes the tool-picker renderBox ANSI-aware (stripAnsi width + truncateAnsi
truncation + visible-aware padding) so the reverse-video cursor cell no
longer breaks box layout, and guards against negative width on tiny
terminals. No overlay behavior change yet; wiring follows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "o" overlay is now a structured editor with two cursor-editable
fields — "Extra args" (appended to the tool's defaults) and "Env vars"
(space-separated NAME=VALUE) — switched with Tab/↑↓. The tool's default
command is shown read-only so users no longer retype
--dangerously-skip-permissions, and a live preview plus inline
validation show the resulting launch. Enter builds a LaunchOverride that
keeps the tool's own command, so aimux hooks/session tracking always
apply.

Replaces the toolOptions* host fields with a single launchOptionsState,
adds parseEnvAssignments to shell-args, and uses the new line editor for
in-field cursor movement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a separate "O" (shift-o) overlay in the tool picker that opens the
full editable command line (binary + args + env, smart-wrapping) — the
power-user path — now with cursor movement via the line editor and a
clear "full command" framing plus the hooks/raw note. The common cases
stay on the structured "o" overlay.

Wires a new "tool-advanced" overlay kind through dashboard-control
routing and render dispatch and a handleToolAdvancedKey wrapper. Picker
help now reads "[o] options  [O] full command".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… overlay

Add optional defaultArgs/defaultEnv to ToolConfig. These apply on a plain
launch and prefill (editable) in the "o" options dialog, so configured
defaults are visible and overridable. Drop the Shift-O advanced full-command
overlay in favor of the structured args + env editor.

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 11:08am

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR refactors the tool-picker overlay UI to use structured, in-memory line editors for managing launch arguments and environment variables, extends the tool configuration schema with user-default overrides, and introduces foundational text-editing and environment-parsing utilities.

Changes

Structured Launch Options Overlay

Layer / File(s) Summary
Line Editor Module
src/line-editor.ts, src/line-editor.test.ts
New LineState interface and functions to edit, cursor-navigate, and render single-line text with ANSI reverse-video cursor highlight and horizontal scrolling. Tests cover character insertion, navigation key handling (left/right/home/end/ctrl+a/ctrl+e), deletion behaviors (backspace/delete/ctrl+u/ctrl+k/ctrl+w), and paste input normalization.
Environment Variable Parsing
src/shell-args.ts, src/shell-args.test.ts
New parseEnvAssignments function tokenizes and validates whitespace-separated NAME=VALUE pairs into a string-to-string map. Tests verify normal parsing, blank input, quoted values with spaces, and error handling on invalid tokens.
Tool Configuration Defaults Schema
src/config.ts
ToolConfig interface extended with optional defaultArgs (CLI arguments) and defaultEnv (environment variables) for user-default tool overrides.
Tool Picker Overlay Refactor
src/multiplexer/tool-picker.ts, src/multiplexer/tool-picker.test.ts, src/multiplexer/index.ts
Introduces structured LaunchOptionsState with separate line-editor instances for args and env input; exports formatEnvDefaults and defaultsLaunchOverride helpers. Replaces legacy string-buffer tool-options flow with stateful overlay rendering that parses user input on Enter, displays inline errors, and merges tool defaults via defaultsLaunchOverride. Updates renderBox for ANSI-aware truncation and centralizes overlay redrawing via redrawOverlay. Refactors handleToolOptionsKey to manage field switching and incremental line edits; clears launchOptionsState on picker transitions. Multiplexer class gains launchOptionsState field. Tests verify env formatting and default override construction.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • TraderSamwise/aimux#110: Introduces LaunchOverride and launchEnv types used by agent spawn/fork endpoints; this PR's defaultsLaunchOverride helper and refactored overlay feed into that same launch-override plumbing.

Poem

🐰 I tidy lines with a hop and a nod,
Cursor blinks where the carrots were trod.
Args and env in tidy parade,
Parsed and trimmed, no mess is made.
A small rabbit cheers the structured upgrade.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.00% 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 clearly describes the main change: adding structured launch options and per-tool default args/env configuration, which aligns with the core objective of reworking the agent-launch dialog and adding per-tool launch defaults.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/structured-launch-options

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

The advanced full-command overlay that consumed it was removed, leaving no
production callers. Delete the function and its test block.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@TraderSamwise

Copy link
Copy Markdown
Owner Author

Review-loop note (sub-agent findings, resolution recorded):

A parallel review pass flagged two astral-plane edge cases in src/line-editor.ts:

  1. renderLineWindow indexes a code-point array ([...base]) with a UTF-16 code-unit cursor, so a supplementary-plane char (emoji) would desync the highlighted cell.
  2. deleteRange (backspace / ctrl-w / delete) slices on code-unit boundaries, which could split a surrogate pair into a lone surrogate.

Resolution: intentionally not fixed. This is a single-line editor for shell launch args and env vars — its realistic input domain is ASCII/BMP shell syntax (flags, paths, KEY=VALUE), where cursor offset and code-point index coincide and slicing is always boundary-safe. Adding surrogate-aware cursor tracking would be complexity for an input that won't occur here. Noting it as a known limitation rather than carrying the extra code. (The third finding — the dead parseLaunchCommandLine export — was fixed in 26f7591.)

@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/shell-args.test.ts (1)

37-53: ⚡ Quick win

Consider adding test coverage for variable name validation and multi-equals edge cases.

The existing tests correctly verify the core functionality and error handling. Adding coverage for these realistic edge cases would strengthen the test suite:

  1. Invalid variable name patterns – Test that names starting with digits or containing hyphens are rejected (e.g., 123FOO=value, FOO-BAR=value) to validate the regex boundary behavior.
  2. Values containing equals signs – Test that FOO=bar=baz correctly parses as {FOO: "bar=baz"} to document support for values with embedded = (common in URLs, base64, etc.).
📋 Example test cases
it("rejects variable names starting with digits", () => {
  expect(() => parseEnvAssignments("123FOO=value")).toThrow('invalid env var "123FOO=value"');
});

it("rejects variable names containing hyphens", () => {
  expect(() => parseEnvAssignments("FOO-BAR=value")).toThrow('invalid env var "FOO-BAR=value"');
});

it("supports values containing equals signs", () => {
  expect(parseEnvAssignments("URL=http://example.com?a=1&b=2")).toEqual({
    URL: "http://example.com?a=1&b=2"
  });
});
🤖 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/shell-args.test.ts` around lines 37 - 53, Add unit tests to cover
variable-name validation and multi-equals values for parseEnvAssignments: add
tests that assert parseEnvAssignments("123FOO=value") and
parseEnvAssignments("FOO-BAR=value") throw the same 'invalid env var "<token>"'
error pattern used by existing tests, and add a test that
parseEnvAssignments("FOO=bar=baz") (or an actual URL with =) returns { FOO:
"bar=baz" } to verify values with embedded '=' are parsed as part of the value.
🤖 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/shell-args.test.ts`:
- Around line 37-53: Add unit tests to cover variable-name validation and
multi-equals values for parseEnvAssignments: add tests that assert
parseEnvAssignments("123FOO=value") and parseEnvAssignments("FOO-BAR=value")
throw the same 'invalid env var "<token>"' error pattern used by existing tests,
and add a test that parseEnvAssignments("FOO=bar=baz") (or an actual URL with =)
returns { FOO: "bar=baz" } to verify values with embedded '=' are parsed as part
of the value.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b2da6bbf-1c0c-4af3-9fde-1f39ca627ebc

📥 Commits

Reviewing files that changed from the base of the PR and between e971d95 and 26f7591.

📒 Files selected for processing (2)
  • src/shell-args.test.ts
  • src/shell-args.ts
💤 Files with no reviewable changes (1)
  • src/shell-args.ts

@TraderSamwise
TraderSamwise merged commit b3b70e6 into master Jun 8, 2026
3 checks passed
@TraderSamwise
TraderSamwise deleted the feat/structured-launch-options branch June 8, 2026 11:13
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