Skip to content

Commit 0f258d5

Browse files
committed
🤖 feat: add first-class mux run CLI command
Replace the internal agentSessionCli.ts with a user-facing `mux run` command: - Add `mux run` subcommand with Commander.js for proper --help - Smart defaults: local runtime, medium thinking, auto-generated workspace ID - Human-friendly timeout parsing (5m, 300s, etc.) - Clean flag names (--json, --thinking, --dir) - Full documentation in docs/cli.md Update terminal-bench to use the new entry point: - benchmarks/terminal_bench/mux-run.sh now invokes src/cli/run.ts - Simpler invocation with fewer verbose flags Usage: mux run "Fix the tests" mux run --dir /project --runtime "ssh user@host" "Deploy" echo "Add logging" | mux run --json _Generated with `mux`_
1 parent 07ea67d commit 0f258d5

File tree

9 files changed

+334
-228
lines changed

9 files changed

+334
-228
lines changed

benchmarks/terminal_bench/mux-run.sh

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ MUX_TRUNK="${MUX_TRUNK:-main}"
2929
MUX_WORKSPACE_ID="${MUX_WORKSPACE_ID:-mux-bench}"
3030
MUX_THINKING_LEVEL="${MUX_THINKING_LEVEL:-high}"
3131
MUX_MODE="${MUX_MODE:-exec}"
32+
MUX_RUNTIME="${MUX_RUNTIME:-}"
3233

3334
resolve_project_path() {
3435
if [[ -n "${MUX_PROJECT_PATH}" ]]; then
@@ -77,21 +78,21 @@ ensure_git_repo "${project_path}"
7778
log "starting mux agent session for ${project_path}"
7879
cd "${MUX_APP_ROOT}"
7980

80-
cmd=(bun src/cli/debug/agentSessionCli.ts
81-
--config-root "${MUX_CONFIG_ROOT}"
82-
--project-path "${project_path}"
83-
--workspace-path "${project_path}"
84-
--workspace-id "${MUX_WORKSPACE_ID}"
81+
cmd=(bun src/cli/run.ts
82+
--dir "${project_path}"
8583
--model "${MUX_MODEL}"
8684
--mode "${MUX_MODE}"
87-
--json-streaming)
85+
--thinking "${MUX_THINKING_LEVEL}"
86+
--config-root "${MUX_CONFIG_ROOT}"
87+
--workspace-id "${MUX_WORKSPACE_ID}"
88+
--json)
8889

8990
if [[ -n "${MUX_TIMEOUT_MS}" ]]; then
9091
cmd+=(--timeout "${MUX_TIMEOUT_MS}")
9192
fi
9293

93-
if [[ -n "${MUX_THINKING_LEVEL}" ]]; then
94-
cmd+=(--thinking-level "${MUX_THINKING_LEVEL}")
94+
if [[ -n "${MUX_RUNTIME}" ]]; then
95+
cmd+=(--runtime "${MUX_RUNTIME}")
9596
fi
9697

9798
# Terminal-bench enforces timeouts via --global-agent-timeout-sec

benchmarks/terminal_bench/mux_agent.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class MuxAgent(AbstractInstalledAgent):
6262
"MUX_APP_ROOT",
6363
"MUX_WORKSPACE_ID",
6464
"MUX_MODE",
65+
"MUX_RUNTIME",
6566
)
6667

6768
def __init__(

docs/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- [Introduction](./intro.md)
66
- [Install](./install.md)
7+
- [CLI](./cli.md)
78
- [Why Parallelize?](./why-parallelize.md)
89

910
# Features

docs/benchmarking.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Optional environment overrides:
1818
| `MUX_MODEL` | Preferred model (supports `provider/model` syntax) | `anthropic/claude-sonnet-4-5` |
1919
| `MUX_THINKING_LEVEL` | Optional reasoning level (`off`, `low`, `medium`, `high`) | `high` |
2020
| `MUX_MODE` | Starting mode (`plan` or `exec`) | `exec` |
21+
| `MUX_RUNTIME` | Runtime type (`local`, `worktree`, or `ssh <host>`) | `worktree` |
2122
| `MUX_TIMEOUT_MS` | Optional stream timeout in milliseconds | no timeout |
2223
| `MUX_CONFIG_ROOT` | Location for mux session data inside the container | `/root/.mux` |
2324
| `MUX_APP_ROOT` | Path where the mux sources are staged | `/opt/mux-app` |
@@ -65,7 +66,7 @@ The adapter lives in `benchmarks/terminal_bench/mux_agent.py`. For each task it:
6566

6667
1. Copies the mux repository (package manifests + `src/`) into `/tmp/mux-app` inside the container.
6768
2. Ensures Bun exists, then runs `bun install --frozen-lockfile`.
68-
3. Launches `src/cli/debug/agentSessionCli.ts` to prepare workspace metadata and stream the instruction, storing state under `MUX_CONFIG_ROOT` (default `/root/.mux`).
69+
3. Launches `mux run` (`src/cli/run.ts`) to prepare workspace metadata and stream the instruction, storing state under `MUX_CONFIG_ROOT` (default `/root/.mux`).
6970

7071
`MUX_MODEL` accepts either the mux colon form (`anthropic:claude-sonnet-4-5`) or the Terminal-Bench slash form (`anthropic/claude-sonnet-4-5`); the adapter normalises whichever you provide.
7172

docs/cli.md

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Command Line Interface
2+
3+
Mux provides a CLI for running agent sessions without opening the desktop app.
4+
5+
## `mux run`
6+
7+
Run an agent session in any directory:
8+
9+
```bash
10+
# Basic usage - run in current directory
11+
mux run "Fix the failing tests"
12+
13+
# Specify a directory
14+
mux run --dir /path/to/project "Add authentication"
15+
16+
# Use SSH runtime
17+
mux run --runtime "ssh user@myserver" "Deploy changes"
18+
19+
# Plan mode (proposes a plan, then auto-executes)
20+
mux run --mode plan "Refactor the auth module"
21+
22+
# Pipe instructions via stdin
23+
echo "Add logging to all API endpoints" | mux run
24+
25+
# JSON output for scripts
26+
mux run --json "List all TypeScript files" | jq '.type'
27+
```
28+
29+
### Options
30+
31+
| Option | Short | Description | Default |
32+
| ---------------------- | ----- | -------------------------------------------------- | ----------------- |
33+
| `--dir <path>` | `-d` | Project directory | Current directory |
34+
| `--model <model>` | `-m` | Model to use (e.g., `anthropic:claude-sonnet-4-5`) | Default model |
35+
| `--runtime <runtime>` | `-r` | Runtime: `local`, `worktree`, or `ssh <host>` | `local` |
36+
| `--mode <mode>` | | Agent mode: `plan` or `exec` | `exec` |
37+
| `--thinking <level>` | `-t` | Thinking level: `off`, `low`, `medium`, `high` | `medium` |
38+
| `--timeout <duration>` | | Timeout (e.g., `5m`, `300s`, `300000`) | No timeout |
39+
| `--json` | | Output NDJSON for programmatic use | Off |
40+
| `--quiet` | `-q` | Only output final result | Off |
41+
| `--workspace-id <id>` | | Explicit workspace ID | Auto-generated |
42+
| `--config-root <path>` | | Mux config directory | `~/.mux` |
43+
44+
### Runtimes
45+
46+
- **`local`** (default): Runs directly in the specified directory. Best for one-off tasks.
47+
- **`worktree`**: Creates an isolated git worktree under `~/.mux/src`. Useful for parallel work.
48+
- **`ssh <host>`**: Runs on a remote machine via SSH. Example: `--runtime "ssh user@myserver.com"`
49+
50+
### Output Modes
51+
52+
- **Default (TTY)**: Human-readable streaming with tool call formatting
53+
- **`--json`**: NDJSON streaming - each line is a JSON object with event data
54+
- **`--quiet`**: Suppresses streaming output, only shows final assistant response
55+
56+
### Examples
57+
58+
```bash
59+
# Quick fix in current directory
60+
mux run "Fix the TypeScript errors"
61+
62+
# Use a specific model with extended thinking
63+
mux run -m anthropic:claude-sonnet-4-5 -t high "Optimize database queries"
64+
65+
# Run on remote server
66+
mux run -r "ssh dev@staging.example.com" -d /app "Update dependencies"
67+
68+
# Scripted usage with timeout
69+
mux run --json --timeout 5m "Generate API documentation" > output.jsonl
70+
71+
# Plan first, then execute
72+
mux run --mode plan "Migrate from REST to GraphQL"
73+
```
74+
75+
## `mux server`
76+
77+
Start the HTTP/WebSocket server for remote access (e.g., from mobile devices):
78+
79+
```bash
80+
mux server --port 3000 --host 0.0.0.0
81+
```
82+
83+
Options:
84+
85+
- `--host <host>` - Host to bind to (default: `localhost`)
86+
- `--port <port>` - Port to bind to (default: `3000`)
87+
- `--auth-token <token>` - Optional bearer token for authentication
88+
- `--add-project <path>` - Add and open project at the specified path
89+
90+
## `mux version`
91+
92+
Print the version and git commit:
93+
94+
```bash
95+
mux version
96+
# mux v0.8.4 (abc123)
97+
```

scripts/check-bench-agent.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ if [[ ! -f "$MUX_RUN_SH" ]]; then
1515
fi
1616

1717
# Extract the agent CLI path from mux-run.sh
18-
# Looks for line like: cmd=(bun src/cli/debug/agentSessionCli.ts
18+
# Looks for line like: cmd=(bun src/cli/run.ts
1919
CLI_PATH_MATCH=$(grep -o "bun src/.*\.ts" "$MUX_RUN_SH" | head -1 | cut -d' ' -f2)
2020

2121
if [[ -z "$CLI_PATH_MATCH" ]]; then

src/cli/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ if (subcommand === "server") {
77
process.argv.splice(2, 1);
88
// eslint-disable-next-line @typescript-eslint/no-require-imports
99
require("./server");
10+
} else if (subcommand === "run") {
11+
// Remove 'run' from args since run.ts uses Commander which handles its own parsing
12+
process.argv.splice(2, 1);
13+
// eslint-disable-next-line @typescript-eslint/no-require-imports
14+
require("./run");
1015
} else if (subcommand === "version") {
1116
// eslint-disable-next-line @typescript-eslint/no-require-imports
1217
const { VERSION } = require("../version") as {

0 commit comments

Comments
 (0)