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: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ 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 mimocode # curl -fsSL https://mimo.xiaomi.com/install | bash (binary: mimo)
moshcode install openagents # curl -fsSL https://openagents.org/install.sh | bash
```

Expand All @@ -114,6 +115,7 @@ moshcode agents gemini # gemini --approval-mode=yolo
moshcode agents kimi # kimi --yolo (autonomous)
moshcode agents qwen # qwen --approval-mode=yolo (autonomous)
moshcode agents deepseek # deepseek-code --turbo (autonomous)
moshcode agents mimocode # mimo --dangerously-skip-permissions --trust (autonomous)
moshcode agents aider # aider --yes-always (autonomous)
moshcode agents openagents # openagents (dashboard)
```
Expand Down Expand Up @@ -457,8 +459,8 @@ of the traffic and a tenth of the price; folding them into `in` makes a $3
session look like a $60 one. Attribution is engine + directory + "started before
this run did", so a session that shares a directory with another agent can pick
up its neighbour's work — `--json` carries the run list when you need to check.
gemini, kimi, qwen, deepseek and openagents keep no readable usage log, so they
report no cost rather than zero cost.
gemini, kimi, qwen, deepseek, mimocode and openagents keep no readable usage
log, so they report no cost rather than zero cost.

### Driving it from a script or another agent

Expand Down
2 changes: 1 addition & 1 deletion src/cli-schema.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ export const CORE_CLI_COMMANDS = [
+ "codex's rollout token counts, opencode's per-message cost, aider's chat history. a figure marked "
+ "`~` was worked out from published rates and is what the tokens WOULD cost on the api; unmarked "
+ "figures are the engine's own arithmetic. models with no rate show tokens and no cost — add yours "
+ "to ~/.moshcode/pricing.json. gemini, kimi, deepseek and openagents log nothing readable, "
+ "to ~/.moshcode/pricing.json. gemini, kimi, deepseek, mimocode and openagents log nothing readable, "
+ "so they report no cost rather than zero. under the table, `burn` is the same windows for every "
+ "engine — last 1 min, 15 min, 1 hour, 4 hours, 8 hours and the report window — with what the "
+ "requests inside each cost, that cost per hour, and the runs behind it; --json carries them as `burn`.",
Expand Down
2 changes: 1 addition & 1 deletion src/cost.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ export const COST_READERS = {
};

/** Engines moshcode can launch but cannot cost — named so the report can say so. */
export const UNCOSTED_ENGINES = ["gemini", "kimi", "deepseek", "openagents"];
export const UNCOSTED_ENGINES = ["gemini", "kimi", "deepseek", "mimocode", "openagents"];

/**
* Finish a run: price it, and record where the price came from.
Expand Down
58 changes: 57 additions & 1 deletion src/engines.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,58 @@ export const ENGINES = {
agentArgs: ["--turbo"],
install: { cmd: "npm", args: ["install", "-g", "@serjm/deepseek-code"] },
},
mimocode: {
desc: "MiMo Code — Xiaomi's agentic coding CLI (binary: mimo)",
// The installer names the binary `mimo`, not `mimocode`: the product is
// MiMo Code, the model family is MiMo, and the shell command is the short
// one. Its aliases below accept every spelling.
bin: "mimo",
// An opencode derivative (same `run`/`serve`/`acp`/`mcp` verbs, `--continue`,
// sessions, `--pure`) with a Claude-shaped permissions layer bolted on:
// `--dangerously-skip-permissions` (alias `--yolo`) auto-approves every
// tool call the config does not explicitly deny. `--never-ask` is the step
// past that — it also answers the agent's own questions — which is more
// than /agents means for every other engine here, so it stays off.
//
// `--trust` skips the workspace trust check. Without it a fresh directory
// opens on "Is this a project you created or one you trust?" and an
// autonomous session is not autonomous until someone presses Enter. The
// bypass flag then puts up a second dialog of its own on EVERY launch
// ("WARNING: Bypass Permissions mode", default "No, exit") that no flag
// suppresses; `boot` below answers it for swarms, and a human at
// `/agents mimocode` answers it once by hand.
agentArgs: ["--dangerously-skip-permissions", "--trust"],
// No agentsView: `mimo agent` is a management subcommand (create/list) that
// prints and exits, not a live view to land on.
install: { cmd: "bash", args: ["-c", "curl -fsSL https://mimo.xiaomi.com/install | bash"] },
// Its own updater knows it was installed by the curl script ("Using method:
// curl") and swaps the binary in place; on the current version it says so
// and exits 0 rather than re-downloading. Verified with 0.1.14.
upgrade: { cmd: "mimo", args: ["upgrade"] },
// The installer drops the binary in ~/.mimocode/bin and only appends that
// to a shell rc, so PATH will not see `mimo` until the next shell —
// including in the moshcode session that just installed it.
binDirs: [path.join(homedir(), ".mimocode", "bin")],
resume: ["--continue"],
// Dialogs the engine puts up BEFORE any work (PRD 0015), and the keys that
// answer them. Both observed on 0.1.14 under a pty. The trust check defaults
// to "Yes, I trust this folder", so Enter alone takes it — the opposite of
// Claude Code's, where Enter exits. The bypass warning defaults to "No,
// exit (recommended)", so it needs Down first.
boot: [
{ pattern: /\bIs this a project you created or one you trust\b/i, keys: ["Enter"], label: "trust this folder" },
{ pattern: /\bYes, I accept the risks and want to skip permissions\b/i, keys: ["Down", "Enter"], label: "accept bypass permissions" },
],
state: {
// opencode lineage, so opencode's permission wording — plus the two boot
// dialogs above, which wait on a human exactly as a permission prompt does.
blocked: [
/\bpermission (?:request|required)\b/i, /\ballow this (?:command|tool)\b/i,
/\bIs this a project you created or one you trust\b/i,
/\bWARNING: Bypass Permissions mode\b/i,
],
},
},
openagents: {
desc: "OpenAgents — multi-agent launcher + dashboard (openagents.org)",
// The package installs three identical bins — `agn`, `openagents`, and
Expand Down Expand Up @@ -326,6 +378,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",
// `mimo` is the binary the installer writes; the rest are how the product is
// spelled on mimo.xiaomi.com and in its own docs ("MiMo Code").
mimo: "mimocode", "mimo-code": "mimocode", xiaomi: "mimocode",
// 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",
Expand Down Expand Up @@ -445,6 +500,7 @@ 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
mimocode: (p) => ["run", p], // mimocode one-shot (opencode-derived: `mimo run <message>`)
// 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.
};
Expand All @@ -468,7 +524,7 @@ export function aiExecArgs(engine, prompt) {
*/
export function pickAiEngine(preferred) {
const wanted = preferred ? resolveEngine(preferred)?.[0] : null;
const order = preferred ? (wanted ? [wanted] : []) : ["claude", "codex", "opencode", "privacycode", "gemini", "kimi", "qwen", "deepseek", "aider"];
const order = preferred ? (wanted ? [wanted] : []) : ["claude", "codex", "opencode", "privacycode", "gemini", "kimi", "qwen", "deepseek", "mimocode", "aider"];
for (const key of order) {
if (Object.hasOwn(ENGINES, key) && Object.hasOwn(AI_EXEC, key) && isInstalled(ENGINES[key].bin, ENGINES[key].binDirs)) return key;
}
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"],
mimocode: ["--dangerously-skip-permissions", "--trust"],
openagents: [], // a launcher, not an agent: nothing of its own to auto-approve
aider: ["--yes-always"],
};
Expand All @@ -44,6 +45,7 @@ const EXPECTED_LAUNCH_ARGS = {
kimi: ["--yolo"], // no agents view — kimi has no agent list to land on
qwen: ["--approval-mode=yolo"],
deepseek: ["--turbo"],
mimocode: ["--dangerously-skip-permissions", "--trust"], // no agents view — `mimo agent` prints and exits
openagents: [], // bare launch opens the dashboard, which is its agent list
aider: ["--yes-always"],
};
Expand Down
Loading