Skip to content

Commit e793c89

Browse files
🤖 fix: support Electron flags (--no-sandbox) in packaged AppImage (#1183)
## Summary Fix `./mux.AppImage --no-sandbox` and other Electron flags not working - they were incorrectly falling through to CLI help instead of launching the desktop app. ## Problem After the previous CLI argv fix (#1161), Electron flags like `--no-sandbox` in packaged AppImage were treated as unknown CLI arguments: ``` ./mux.AppImage --no-sandbox # showed CLI help instead of launching desktop ``` ## Root Cause `isElectronLaunchArg()` immediately returned `false` for all packaged Electron flags, not distinguishing between: - **CLI flags** (`--help`, `--version`) → should show CLI help - **Electron flags** (`--no-sandbox`, `--disable-gpu`) → should launch desktop ## Solution - Add `CLI_GLOBAL_FLAGS` constant listing flags that should show CLI help - Update `isElectronLaunchArg()` to return `true` for non-CLI flags in packaged mode - Add runtime sanity check (dev mode only) to warn if flags get out of sync - Add tests for the new behavior ## Manual Test Results | Command | Result | |---------|--------| | `./mux.AppImage --no-sandbox` | ✅ Launches desktop | | `./mux.AppImage --disable-gpu` | ✅ Launches desktop | | `./mux.AppImage --help` | ✅ Shows CLI help | | `./mux.AppImage --version` | ✅ Shows version | | `./mux.AppImage server --help` | ✅ Shows server options | | `bunx electron . --no-sandbox` | ✅ Launches desktop (dev mode) | --- _Generated with `mux` • Model: `anthropic:claude-sonnet-4-20250514` • Thinking: `low`_
1 parent e389455 commit e793c89

File tree

3 files changed

+71
-7
lines changed

3 files changed

+71
-7
lines changed

‎src/cli/argv.test.ts‎

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { describe, expect, test } from "bun:test";
22
import {
3+
CLI_GLOBAL_FLAGS,
34
detectCliEnvironment,
45
getParseOptions,
56
getSubcommand,
@@ -8,6 +9,19 @@ import {
89
isElectronLaunchArg,
910
} from "./argv";
1011

12+
describe("CLI_GLOBAL_FLAGS", () => {
13+
test("contains expected help and version flags", () => {
14+
expect(CLI_GLOBAL_FLAGS).toContain("--help");
15+
expect(CLI_GLOBAL_FLAGS).toContain("-h");
16+
expect(CLI_GLOBAL_FLAGS).toContain("--version");
17+
expect(CLI_GLOBAL_FLAGS).toContain("-v");
18+
});
19+
20+
test("has exactly 4 flags", () => {
21+
expect(CLI_GLOBAL_FLAGS).toHaveLength(4);
22+
});
23+
});
24+
1125
describe("detectCliEnvironment", () => {
1226
test("bun/node: firstArgIndex=2", () => {
1327
const env = detectCliEnvironment({}, undefined);
@@ -123,11 +137,26 @@ describe("isElectronLaunchArg", () => {
123137
const env = detectCliEnvironment({}, undefined);
124138
expect(isElectronLaunchArg(".", env)).toBe(false);
125139
expect(isElectronLaunchArg("--help", env)).toBe(false);
140+
expect(isElectronLaunchArg("--no-sandbox", env)).toBe(false);
141+
});
142+
143+
test("returns true for Electron flags in packaged mode (--no-sandbox, etc.)", () => {
144+
const env = detectCliEnvironment({ electron: "33.0.0" }, undefined);
145+
expect(isElectronLaunchArg("--no-sandbox", env)).toBe(true);
146+
expect(isElectronLaunchArg("--disable-gpu", env)).toBe(true);
147+
expect(isElectronLaunchArg("--enable-logging", env)).toBe(true);
126148
});
127149

128-
test("returns false for packaged Electron (flags are real CLI args)", () => {
150+
test("returns false for CLI flags in packaged mode (--help, --version)", () => {
129151
const env = detectCliEnvironment({ electron: "33.0.0" }, undefined);
130152
expect(isElectronLaunchArg("--help", env)).toBe(false);
153+
expect(isElectronLaunchArg("-h", env)).toBe(false);
154+
expect(isElectronLaunchArg("--version", env)).toBe(false);
155+
expect(isElectronLaunchArg("-v", env)).toBe(false);
156+
});
157+
158+
test("returns false for '.' in packaged mode", () => {
159+
const env = detectCliEnvironment({ electron: "33.0.0" }, undefined);
131160
expect(isElectronLaunchArg(".", env)).toBe(false);
132161
});
133162

@@ -154,6 +183,11 @@ describe("isElectronLaunchArg", () => {
154183
const env = detectCliEnvironment({ electron: "33.0.0" }, true);
155184
expect(isElectronLaunchArg(undefined, env)).toBe(false);
156185
});
186+
187+
test("returns false for undefined subcommand in packaged mode", () => {
188+
const env = detectCliEnvironment({ electron: "33.0.0" }, undefined);
189+
expect(isElectronLaunchArg(undefined, env)).toBe(false);
190+
});
157191
});
158192

159193
describe("isCommandAvailable", () => {

‎src/cli/argv.ts‎

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,37 @@ export function getArgsAfterSplice(
7070
return argv.slice(env.firstArgIndex);
7171
}
7272

73+
/**
74+
* Global CLI flags that should show help/version, not launch desktop.
75+
* Commander auto-adds --help/-h. We add --version/-v in index.ts.
76+
*
77+
* IMPORTANT: If you add new global flags to the CLI in index.ts,
78+
* add them here too so packaged Electron routes them correctly.
79+
*/
80+
export const CLI_GLOBAL_FLAGS = ["--help", "-h", "--version", "-v"] as const;
81+
7382
/**
7483
* Check if the subcommand is an Electron launch arg (not a real CLI command).
75-
* In dev mode (electron --inspect .), argv may contain flags or "." before the subcommand.
76-
* These should trigger desktop launch, not CLI processing.
84+
* In dev mode, "." or flags before the app path should launch desktop.
85+
* In packaged mode, Electron flags (--no-sandbox, etc.) should launch desktop,
86+
* but CLI flags (--help, --version) should show CLI help.
7787
*/
7888
export function isElectronLaunchArg(
7989
subcommand: string | undefined,
8090
env: CliEnvironment = detectCliEnvironment()
8191
): boolean {
82-
if (env.isPackagedElectron || !env.isElectron) {
83-
return false;
92+
if (!env.isElectron) return false;
93+
94+
if (env.isPackagedElectron) {
95+
// In packaged: flags that aren't CLI flags should launch desktop
96+
return Boolean(
97+
subcommand?.startsWith("-") &&
98+
!CLI_GLOBAL_FLAGS.includes(subcommand as (typeof CLI_GLOBAL_FLAGS)[number])
99+
);
84100
}
85-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional: false from startsWith should still check "."
86-
return subcommand?.startsWith("-") || subcommand === ".";
101+
102+
// Dev mode: "." or any flag launches desktop
103+
return subcommand === "." || subcommand?.startsWith("-") === true;
87104
}
88105

89106
/**

‎src/cli/index.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import { Command } from "commander";
2424
import { VERSION } from "../version";
2525
import {
26+
CLI_GLOBAL_FLAGS,
2627
detectCliEnvironment,
2728
getParseOptions,
2829
getSubcommand,
@@ -79,11 +80,23 @@ if (subcommand === "run") {
7980
const gitCommit =
8081
typeof versionRecord.git_commit === "string" ? versionRecord.git_commit : "unknown";
8182

83+
// Global flags are defined in CLI_GLOBAL_FLAGS (argv.ts) for routing logic.
84+
// Commander auto-adds --help/-h. We define --version/-v below.
8285
program
8386
.name("mux")
8487
.description("Mux - AI agent orchestration")
8588
.version(`${gitDescribe} (${gitCommit})`, "-v, --version");
8689

90+
// Sanity check: ensure version flags match CLI_GLOBAL_FLAGS
91+
if (process.env.NODE_ENV !== "production") {
92+
const versionFlags = ["-v", "--version"];
93+
for (const flag of versionFlags) {
94+
if (!CLI_GLOBAL_FLAGS.includes(flag as (typeof CLI_GLOBAL_FLAGS)[number])) {
95+
console.warn(`Warning: version flag "${flag}" not in CLI_GLOBAL_FLAGS`);
96+
}
97+
}
98+
}
99+
87100
// Register subcommand stubs for help display (actual implementations are above)
88101
// `run` is only available via bun/node CLI, not bundled in Electron
89102
if (isCommandAvailable("run", env)) {

0 commit comments

Comments
 (0)