Skip to content

Commit 708583a

Browse files
ralyodioclaude
andcommitted
feat(cli): /agents opens the engine's native agent view when it has one
`/agents <engine>` (and `moshcode agents <engine>`) previously always ran the engine's autonomous-session bypass flag — so `/agents claude` dropped you into a `claude --dangerously-skip-permissions` session, never your agent list. Engines can now declare an `agentsView` (the exact argv that opens their native agent list). Agent-mode launches use it when present, else fall back to the autonomous bypass flags as before: claude -> claude agents --dangerously-skip-permissions (agent view) opencode -> opencode agent list (agent view) codex -> codex --dangerously-bypass-approvals-and-sandbox (autonomous) gemini -> gemini --approval-mode=yolo (autonomous) aider -> aider --yes-always (autonomous) Only engines whose CLI actually has an agents subcommand get a view; codex has bypass flags but no agents subcommand, so it (and gemini/aider) keep the old autonomous behavior. Updated the agent-mode banner + README + engine tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 56c1547 commit 708583a

6 files changed

Lines changed: 43 additions & 16 deletions

File tree

README.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,17 @@ moshcode install codex # npm i -g @openai/codex
2525

2626
### Autonomous agents versus raw starts
2727

28-
`agents` intentionally starts an autonomous session by injecting each engine's
29-
native bypass or auto-approval mode. Use this only in an isolated container, VM,
30-
or workspace you trust:
28+
`agents` opens the engine's native **agent view** when it has one, so you land on
29+
your agent list. Engines without an agents view instead start an autonomous
30+
session by injecting the engine's native bypass or auto-approval mode. Either way,
31+
use this only in an isolated container, VM, or workspace you trust:
3132

3233
```sh
33-
moshcode agents claude # claude --dangerously-skip-permissions
34-
moshcode agents codex # codex --dangerously-bypass-approvals-and-sandbox
35-
moshcode agents gemini # gemini --approval-mode=yolo
36-
moshcode agents aider # aider --yes-always
37-
moshcode agents opencode # opencode --auto
34+
moshcode agents claude # claude agents --dangerously-skip-permissions (agent view)
35+
moshcode agents opencode # opencode agent list (agent view)
36+
moshcode agents codex # codex --dangerously-bypass-approvals-and-sandbox (autonomous)
37+
moshcode agents gemini # gemini --approval-mode=yolo (autonomous)
38+
moshcode agents aider # aider --yes-always (autonomous)
3839
```
3940

4041
`start` is the explicit raw path. It injects nothing, so the native engine keeps

bin/moshcode.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ function printEngineStatus() {
7878

7979
async function launchEngine(key, engine, args, { agentMode = false } = {}) {
8080
if (agentMode) {
81-
console.error(`⚠ agent mode: ${key} ${engine.agentArgs.join(" ")}native approvals/permissions are bypassed or auto-approved.`);
81+
console.error(`⚠ agent mode: ${key} ${agentLaunchArgs(engine).join(" ")}${engine.agentsView ? " — opening its agent view" : " — native approvals/permissions are bypassed or auto-approved"}.`);
8282
}
8383
const result = await openSession(engine, agentMode ? agentLaunchArgs(engine, args) : args);
8484
if (!result.ok) {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "moshcode",
3-
"version": "0.7.0",
3+
"version": "0.8.0",
44
"type": "module",
55
"description": "moshcode — a metal wrapper for coding engines and native UGig/CoinPay workflow CLIs, with OpenPRD and moshscript",
66
"bin": {

src/engines.mjs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
// runs the engine's official installer; `/agents <name>` (or `moshcode <name>`)
33
// opens a passthrough session on it. moshcode itself stays lean (no vendored
44
// fork). Add engines here.
5+
//
6+
// `agentsView` (optional) is the exact argv that opens the engine's native
7+
// agent list/view — used by `/agents <name>` when the engine actually has one
8+
// (claude, opencode). It's the FULL leading args (subcommand + any flags that
9+
// subcommand accepts), because not every agents-subcommand takes the engine's
10+
// bypass flag (e.g. `opencode agent list` takes none). Engines without an
11+
// `agentsView` fall back to `agentArgs` — an autonomous session with native
12+
// approvals bypassed/auto-approved.
513
import { spawn } from "node:child_process";
614
import { existsSync, statSync } from "node:fs";
715
import path from "node:path";
@@ -11,13 +19,15 @@ export const ENGINES = {
1119
desc: "opencode — the open-source coding agent (SST/anomalyco)",
1220
bin: "opencode",
1321
agentArgs: ["--auto"],
22+
agentsView: ["agent", "list"], // `opencode agent list` — lists agents; the `agent` subcommand takes no bypass flag
1423
install: { cmd: "bash", args: ["-c", "curl -fsSL https://opencode.ai/install | bash"] },
1524
upgrade: { cmd: "opencode", args: ["upgrade"] },
1625
},
1726
claude: {
1827
desc: "Claude Code — Anthropic's agentic CLI",
1928
bin: "claude",
2029
agentArgs: ["--dangerously-skip-permissions"],
30+
agentsView: ["agents", "--dangerously-skip-permissions"], // `claude agents …` — the background-agents view; accepts the skip flag
2131
install: { cmd: "npm", args: ["install", "-g", "@anthropic-ai/claude-code"] },
2232
// Claude Code authenticates via its own stored login (~/.claude). An
2333
// inherited ANTHROPIC_API_KEY hijacks that subscription auth — and if the
@@ -92,9 +102,14 @@ export function engineList() {
92102
return Object.entries(ENGINES).map(([k, v]) => ` ${k.padEnd(10)} ${v.desc}`).join("\n");
93103
}
94104

95-
/** Prepend an engine's autonomous-mode flags to caller-supplied arguments. */
105+
/**
106+
* Args for an agent-mode launch (`/agents <engine>` / `moshcode agents <engine>`):
107+
* the engine's native agents-view invocation when it has one (so you land on your
108+
* agent list), else its autonomous bypass flags. Caller-supplied args follow.
109+
*/
96110
export function agentLaunchArgs(engine, args = []) {
97-
return [...(engine.agentArgs || []), ...args];
111+
const lead = engine.agentsView || engine.agentArgs || [];
112+
return [...lead, ...args];
98113
}
99114

100115
/**

src/tui.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ async function openEngine(key, engine, args, { agentMode = false } = {}) {
154154
console.log(info(`${key} isn't installed — try ${acid("/install " + key)} first.`));
155155
}
156156
if (agentMode) {
157-
console.log(err(`agent mode: ${key} ${engine.agentArgs.join(" ")}native approvals/permissions are bypassed or auto-approved.`));
157+
console.log(err(`agent mode: ${key} ${agentLaunchArgs(engine).join(" ")}${engine.agentsView ? " — opening its agent view" : " — native approvals/permissions are bypassed or auto-approved"}.`));
158158
}
159159
console.log(info(`opening ${bone(key)}${agentMode ? " autonomously" : " raw"} — hand-off to its CLI, exit it to come back…`));
160160
console.log(hr());

test/engines.test.mjs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import test from "node:test";
1717
import { ENGINES, agentLaunchArgs } from "../src/engines.mjs";
1818

1919
const BIN = fileURLToPath(new URL("../bin/moshcode.mjs", import.meta.url));
20+
// The autonomous-session bypass flags each engine declares (engine.agentArgs).
2021
const EXPECTED_AGENT_ARGS = {
2122
opencode: ["--auto"],
2223
claude: ["--dangerously-skip-permissions"],
@@ -25,6 +26,16 @@ const EXPECTED_AGENT_ARGS = {
2526
aider: ["--yes-always"],
2627
};
2728

29+
// What an agent-mode launch actually runs (agentLaunchArgs): the engine's native
30+
// agents-view invocation where it has one, else its autonomous bypass flags.
31+
const EXPECTED_LAUNCH_ARGS = {
32+
opencode: ["agent", "list"],
33+
claude: ["agents", "--dangerously-skip-permissions"],
34+
codex: ["--dangerously-bypass-approvals-and-sandbox"],
35+
gemini: ["--approval-mode=yolo"],
36+
aider: ["--yes-always"],
37+
};
38+
2839
function tempDir(prefix = "moshcode-engines-") {
2940
return mkdtempSync(path.join(tmpdir(), prefix));
3041
}
@@ -75,15 +86,15 @@ test("every engine declares its reviewed autonomous-mode arguments", () => {
7586
);
7687
for (const [key, engine] of Object.entries(ENGINES)) {
7788
assert.deepEqual(agentLaunchArgs(engine, ["--user-arg", "two words"]), [
78-
...EXPECTED_AGENT_ARGS[key],
89+
...EXPECTED_LAUNCH_ARGS[key],
7990
"--user-arg",
8091
"two words",
8192
]);
8293
}
8394
});
8495

85-
for (const [key, expected] of Object.entries(EXPECTED_AGENT_ARGS)) {
86-
test(`agents ${key} injects autonomous flags before user arguments`, async () => {
96+
for (const [key, expected] of Object.entries(EXPECTED_LAUNCH_ARGS)) {
97+
test(`agents ${key} injects its agent-launch args before user arguments`, async () => {
8798
const nativeBin = tempDir();
8899
mkdirSync(nativeBin, { recursive: true });
89100
writeEngine(nativeBin, key);

0 commit comments

Comments
 (0)