Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,13 @@ moshcode install codex # npm i -g @openai/codex
moshcode install kimi # curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash
moshcode install qwen # npm i -g @qwen-code/qwen-code
moshcode install deepseek # npm i -g @serjm/deepseek-code
moshcode install openagents # curl -fsSL https://openagents.org/install.sh | bash
```

`openagents` is the odd one out: a launcher that supervises the engines above
rather than a coding agent itself. Its installer ends by offering to pair the
machine with a workspace — press Enter to skip that.

### Autonomous agents versus raw starts

`agents` opens the engine's native **agent view** when it has one, so you land on
Expand All @@ -98,6 +103,7 @@ moshcode agents kimi # kimi --yolo
moshcode agents qwen # qwen --approval-mode=yolo (autonomous)
moshcode agents deepseek # deepseek-code --turbo (autonomous)
moshcode agents aider # aider --yes-always (autonomous)
moshcode agents openagents # openagents (dashboard)
```

`start` is the explicit raw path. It injects nothing, so the native engine keeps
Expand Down
37 changes: 37 additions & 0 deletions src/engines.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,38 @@ export const ENGINES = {
agentArgs: ["--turbo"],
install: { cmd: "npm", args: ["install", "-g", "@serjm/deepseek-code"] },
},
openagents: {
desc: "OpenAgents — multi-agent launcher + dashboard (openagents.org)",
// The package installs three identical bins — `agn`, `openagents`, and
// `agent-connector`. Take the descriptive one: `agn` is short enough to
// collide with something else on a machine we don't control.
bin: "openagents",
// Not a coding agent of its own: it launches and supervises the engines
// above, so it has no approvals to bypass and no yolo flag to pass. A bare
// launch opens the interactive dashboard, which IS its agent list, so both
// `/agents openagents` and `moshcode start openagents` land in the same
// place. (No `agentsView` for the same reason — it would spell the same
// empty argv twice.)
agentArgs: [],
install: { cmd: "bash", args: ["-c", "curl -fsSL https://openagents.org/install.sh | bash"] },
// Its own updater ("upgrade launcher to the latest npm release"), which
// knows it was installed as an unpacked tarball under ~/.openagents rather
// than by npm -g. Re-running the installer would work too, but it re-does
// the Node bootstrap and ends on the pairing prompt below.
upgrade: { cmd: "openagents", args: ["update"] },
// The installer unpacks to ~/.openagents/nodejs and writes the bin shims
// there, appending that directory to a shell rc — so PATH will not see
// `openagents` until the next shell, including in the moshcode session that
// just installed it.
binDirs: [path.join(homedir(), ".openagents", "nodejs", "node_modules", ".bin")],
// No `state`: the dashboard is a blessed TUI with no wording of its own we
// have verified, and a guessed pattern is worse than the shared ones.
//
// The installer ends by offering to pair this device with a workspace, and
// waits on a real answer — but only when stderr is a terminal, and Enter
// skips it. `moshcode install` inherits the terminal, so that prompt is
// yours to answer; run it where you can reach a keyboard.
},
aider: {
desc: "Aider — pair-programming in your terminal",
bin: "aider",
Expand Down Expand Up @@ -198,6 +230,9 @@ export const ENGINE_ALIASES = {
// `dsc` and `deepseek-code` are the binary names the package installs; accept
// both as engine names so whichever one someone has seen resolves.
ds: "deepseek", dsc: "deepseek", "deepseek-code": "deepseek",
// Same idea for openagents: `agn` and `agent-connector` are the other two
// binary names its package installs, and the domain is how it's advertised.
oa: "openagents", agn: "openagents", "agent-connector": "openagents", "openagents.org": "openagents",
};

/** Resolve a name/alias to `[key, engine]`, or null. */
Expand Down Expand Up @@ -281,6 +316,8 @@ const AI_EXEC = {
kimi: (p) => ["-p", p], // kimi prompt mode (prints the response, text by default)
qwen: (p) => ["-p", p], // qwen prompt mode (gemini-derived)
deepseek: (p) => ["--headless", "-p", p], // deepseek: -p runs one prompt and exits; --headless drops the TUI so stdout is pipe-clean
// openagents is absent on purpose: it answers no prompts itself, it starts
// the engines that do. ai() throws a named error rather than picking it.
};

/** argv that runs `prompt` headlessly on `engine` (throws if it has no headless mode). */
Expand Down
2 changes: 2 additions & 0 deletions test/engines.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const EXPECTED_AGENT_ARGS = {
kimi: ["--yolo"],
qwen: ["--approval-mode=yolo"],
deepseek: ["--turbo"],
openagents: [], // a launcher, not an agent: nothing of its own to auto-approve
aider: ["--yes-always"],
};

Expand All @@ -43,6 +44,7 @@ const EXPECTED_LAUNCH_ARGS = {
kimi: ["--yolo"], // no agents view — kimi has no agent list to land on
qwen: ["--approval-mode=yolo"],
deepseek: ["--turbo"],
openagents: [], // bare launch opens the dashboard, which is its agent list
aider: ["--yes-always"],
};

Expand Down