we code in /tmp as root · we use cli only · everything we build has a tui
Drive every coding agent
from one CLI.
moshcode installs and drives the coding agents you already use — opencode, Claude Code, codex and seven more — then keeps their sessions alive, counts what they cost, and bills for the work.
curl -fsSL https://moshcode.sh/install.sh | sh
Zero-dependency ESM — all it needs is Node.js 18+. Later: … | sh -s -- update to upgrade, … | sh -s -- remove to uninstall.
- 10engines it installs and drives
- 54commands, generated from the dispatch table
- 22games in the arcade
- 0dependencies — Node 18+ and nothing else
installs and drives
opencodeclaudecodexgeminikimiqwendeepseekaiderprivacycodeopenagents
one CLI, every agent
It does not reinvent the agent.
moshcode installs the coding agents that already exist and gives them one set of verbs. start is the raw path — it injects nothing, so the engine keeps its own permission model. agents opens the engine's native agent view when it has one, and otherwise starts an autonomous session using that engine's own bypass flag.
Learn the verb once and it works on all ten.
$ moshcode install opencode
✓ opencode 0.14.2 → ~/.local/bin/opencode
$ moshcode agents claude
→ claude agents --dangerously-skip-permissions (agent view)
$ moshcode start codex --sandbox workspace-write
→ codex --sandbox workspace-write (raw, nothing injected)
the herd
Sessions that outlive your terminal.
A normal launch hands the engine your whole terminal and waits — which is why closing the lid kills the work. Add -d and the session runs in a runtime that outlives the shell, so you get your prompt back immediately.
Every session carries a state. blocked means a human decision is the only thing missing, and it can come find you over email, SMS, Slack, Telegram or push.
$ moshcode agents claude -d --name api
$ moshcode ps
api claude blocked ~/src/coinpay 3m screen
logs shell idle ~/src/coinpay 3m screen
work shell idle ~/src/coinpay 3m screen
⚠ 1 waiting on you — moshcode attach api
the workspace
Every agent on one screen.
moshcode herd ui puts the roster down the left and the selected session's real terminal on the right — not a picture of it, the actual pane, moved in, with its process and its scrollback intact.
The row along the bottom is a mosh prompt that takes any herd verb. F12 reaches it from anywhere, including from inside an agent that has taken the keyboard — which makes it the way out of a session you otherwise cannot leave.
┌ herd ──────┬─ api ─────────────────────────────┐
│ herd │ │
│ │ claude │
│ MAIN │ Do you want to proceed? │
│ ▸ ! api │ ❯ 1. Yes │
│ · work │ 2. No │
│ SCRATCH │ │
│ · logs │ │
│ │ │
│ ACTIONS │ │
│ + shell │ │
│ + agent │ │
│ ✕ stop │ │
│ ⊞ tile │ │
│ ← detach │ │
│ │ │
├────────────┴───────────────────────────────────┤
│ mosh ▸ ps · start claude · show <n> · detach │
└────────────────────────────────────────────────┘
swarm + fleet
One task, a herd of agents, one answer.
One headless call splits a task into pieces that do not touch the same files. Each piece runs in its own herd session, four at a time by default, and one more call folds the outputs into the answer you read. --verify adds a skeptic per piece whose verdict the synthesis sees.
Every swarm is recorded as OpenFleet: who started what, under whose approval, what the synthesis said, and what was refused. A bypass flag the ceiling forbids is refused before anything starts, and the refusal is a ledger line a human reads.
$ moshcode swarm "port the auth routes and the dashboard to the new API"
· plan — claude is splitting the task into up to 4 pieces
1 auth routes owns src/auth/
2 dashboard owns src/dashboard/
3 shared API client owns src/api/client.js
· swarm port-the-auth-routes-an-1412: 3 sessions, 3 at a time
✓ port-the-auth-routes-an-1412-1 idle · t-01
✓ port-the-auth-routes-an-1412-2 idle · t-02
✓ port-the-auth-routes-an-1412-3 idle · t-03
· synthesis — claude is folding 3 pieces into one answer
what it costs
Nothing to instrument. Nothing to proxy.
Every engine already writes down what it used, so moshcode cost reads the CLIs' own session logs and lines them up against the herd. Estimated figures are marked ~; unmarked ones are the engine's own.
Under the table, burn is the slope. cost says what the day cost. burn says whether the next hour will cost the same — which is the number that decides whether to kill something.
session engine model in out cache cost age pr
api claude claude-opus-5 1.2k 27k 10.5M $9.91~ 42m view #128
audit codex gpt-5.6-sol 400 200 600 — 12m —
burn cost rate runs
last 1 min $1.32~ $79.16/h 2
last 15 min $38.34~ $153.35/h 8
last 1 hour $222.03~ $222.03/h 11
last 4 hours $966.27~ $241.57/h 19
last 8 hours $1786.84~ $223.35/h 45
$3.72 a minute over the window, on average
getting paid
Every other agentic CLI helps you do the work.
This one also bills for it. Six words, each useful on its own — the timer needs no client, the rate needs no gateway.
Tracking time and sending an invoice are not moshcode ideas, so they also ship standalone as @profullstack/timer and @profullstack/billing. Handing over is opt-in, because billing import is what keeps your records in one store instead of two.
$ moshcode timer on --client acme
$ moshcode rate set '$400/hour/agent/upto:4'
$ moshcode timer off
4h 12m tracked · acme
$ moshcode billing invoice acme --send
✓ INV-0042 $1,680.00 → acme · payments: coinpay
moshscript
Secretly, all JS is legal.
The simple surface stays dead-simple, but a .mosh file is real JavaScript with the whole moshcode command vocabulary injected as globals. No new syntax, no build step — it is plain ESM.
--dry-run narrates a script without executing it, and a shebang line makes one self-running.
const engines = ["claude", "codex"];
for (const e of engines) {
install(e); // → moshcode install <e>
}
mcp("install", "https://mcp.sentry.dev/mcp"); // fan out across engines
say(`ready to mosh with ${engines.length} engines`);
agents("claude"); // autonomous session
while (alive) {
code(); mosh(); notify(); repeat();
} // no bugs, only features
the Moshpit
Claim a name. Put something behind it.
Claim foo.whatever in the Pit, then scaffold a stack to serve it: a Bun service with Caddy and SQLite, or just Caddy and a directory of files. Nothing in a template is executed on install.
The fact that catches everyone: the machine serving the name never resolves it, and every machine visiting it must. Serving is a Host header match. Visitors need sudo moshcode dns enable, or the name resolves to nothing.
$ moshcode template list
bun-caddy-sqlite Bun + Caddy + SQLite — local file in dev, Turso in prod
caddy-static Caddy and a directory of files. Nothing to keep alive.
$ moshcode template install caddy-static --into /srv/site
$ sudo moshcode dns enable
✓ chovy.hacker resolves on this machine
the arcade
Twenty-two games. No menus.
There are no options screens and no difficulty prompts. moshcode games tetris is already playing.
Because everything we build has a TUI.
TETRIS score 1200 · lines 12
┌────────────────────────────────┐
│ · · · · ████· · · · NEXT │
│ · · · · ████· · · · │
│ · · · · · · · · · · ████████ │
│ · · · · · · · · · · │
│ · · · ████· · · · · LVL 2 │
│ ████████████· ██████ │
└────────────────────────────────┘
← → move · ↑ rotate · ↓ drop · space slam · q quit
Push code. Start pits.
One line, and every agent on this machine answers to the same verbs.
curl -fsSL https://moshcode.sh/install.sh | sh