Skip to content
qybaihePublic

About

mu (μ): most of what a coding agent decides isn't code. mu hands 40 kinds of yes/no calls to a small model: fewer wasted tokens, fewer approvals on autopilot, fewer runs that stop halfway. Built on pi.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

553 stars

Watchers

1 watching

Forks

Latest commit

 

History

7,998 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mu

mu

Most of what a coding agent decides isn't code. It's yes/no calls, and mu hands 40 kinds of them to a small model. Built on pi.

Terminal-Bench 2.1, same model, same tasks: mu passed 68.2% of attempts, pi 58.7% (+9.5 points, 95% interval +3.8 to +15.2). How it was measured

npm i -g mu-agent && mu setup && mu · Node.js 22.19 or newer · or the desktop app for macOS, Windows and Linux

CI Desktop app npm Desktop release License: MIT Discussions

English · 简体中文 · 繁體中文 · 日本語 · 한국어

A real run in the mu desktop app, sped up, in mu’s own repository. The message: mu “- fix the parser” fails with “Unknown option”; a task that starts with “- ” is a message, not an option; the CLI is in packages/coding-agent; find the cause, fix it, add a test, run it, then run npm run check; don’t run mu itself. The judge classifies it as a multi-step task. The model, MiMo-V2.6-Pro in Judge mode, reads the argument parser, finds that any argument starting with a dash was taken for an option and changes it so an argument like “- fix the parser” counts as a message. It adds tests, then runs them and npm run check: the judge lets each command run without asking (tool.approval), and everything passes. The Judge tab on the right lists each verdict with its decision point and latency, ending with Task finished.

Does this output matter? Is this command safe for the task? Is the work really done? A coding agent answers questions like these hundreds of times a session. Handing them to the main model or to fixed rules costs you in three ways:

  • Wasted tokens. A 2,000-line test log goes into the context whole, and every request after it pays for it again. mu's judge reads long output chunk by chunk and lets in only what the task needs; the rest waits behind a pointer. Stale results are dropped without a summary, and when you're likely to be back, the prompt cache is refreshed before it expires. Test-log trimming, off by default, folds exact repeats without losing a byte: it cuts 40% of the characters in Jest failure logs and 19.5% across 71 real failing test logs (see Measured).
  • Commands approved on autopilot. The agent asks before every step, so you click Allow without reading, or turn the prompts off. In Judge mode, the default, the judge lets through what the task clearly needs and asks you about the rest. Rules catch risky commands first, and web pages and MCP output are screened for instructions aimed at the AI before the model sees them.
  • Runs that stop halfway. "Next I'll run the tests," and the turn ends. The judge catches a run that stopped short, or a "done" that nothing verified, and sends the agent back to finish.

Asking the main model each of these costs tokens and its attention, and fixed rules get them wrong too often. mu asks a judge: a small, fast model that answers one bounded question at a time, at 40 decision points in the agent loop. 34 of them act on their verdicts out of the box. Every verdict goes into a local ledger with its probabilities and timing (mu ledger, /status or the desktop app's Judge tab), and any decision point can run in shadow mode, asked and logged but changing nothing, so you can compare judges before you rely on one.

mu comes as a command-line tool, mu, which does everything pi does and adds the judgment kernel, and as a desktop app that bundles mu and its runtime. The default judge model is Jev, hosted by TypeSafe. It answers yes/no, choice and score questions with a probability for each answer. Any judge model can take its place: mude 1.0, mu's own model, on your Mac; another decision model from Hugging Face; your own System One server; or any LLM.

Contents: Quick start · How a turn works · Decision points · Judges · How mu is built · Measured · The hive · The board · Desktop app · Command line · Privacy · Documentation · Contributing

Quick start

Desktop app. Download the installer for macOS, Windows or Linux from Releases, open it and sign in with ChatGPT, or paste an API key for any provider. There's nothing else to install.

Command line.

npm i -g mu-agent   # Node.js 22.19 or newer
mu setup            # connect a model
mu                  # start a session in the current directory

You don't need a judge key to start: until you set one, the free Jev on OpenCode Zen answers. Out of the box, 34 of the 40 decision points act on their verdicts, and every verdict is logged (/status, mu ledger or the app's Judge tab). To record what the judge would do without acting on it, put {"modes": {"default": "shadow"}} in ~/.mu/agent/mu.json. More in Getting started.

How a turn works

How a turn works: four stages, each with the decision points it asks the judge. A message arrives: input.preflight, task.frame, input.interjection, skills.disclosure, memory.recall. Before a tool runs, rules first: tool.risk, tool.constraint, tool.approval. What comes back, before the model sees it: tool.injection, tool.admission, context.forget, context.compact. The turn ends: turn.completion, turn.continue, turn.drift, memory.capture, cache.warming. The model loops over the middle two stages. Every stage asks the same judge, and every verdict goes to the ledger.

Decision points

Each decision point is active (the default), shadow (asked and logged, but changes nothing; useful for comparing judges before you switch one on) or off. Each can also name its own judge: jev, mude (local), classifier:<provider>/<model>, llm:<provider>/<model> or a cascade such as mude,jev.

The 40 points fall into five groups:

  • Input (3): what kind of message this is, whether it changes the task and whether it should interrupt the current step.
  • Context (14): what enters the prompt (skills, packs, lessons, chunks of tool output), what to drop as the context grows, which lessons and skills are worth keeping and when to keep the prompt cache warm.
  • Tools and safety (10): whether a command or action should run, whether fetched content or an MCP tool description carries a prompt injection, and quick calls for file search, bulk yes/no questions, browser steps, review triage and diagnostics.
  • Turn (8): whether the work has drifted, hit a dead end, really finished or stopped short, whether a /goal condition is met and what the board and the model should hear.
  • Teamwork (5): which subagent gets a delegated task, whether its patch stayed in scope and which findings bees share.
Input: 3 decision points
Decision point Question Effect
input.preflight What kind of message is this, and how much thinking does it need? A one-line hint to the model; optionally, the turn's thinking level
task.frame Is this a new task, a hard constraint, a correction, a subgoal or no change? Only a change rewrites the task frame: the goal, your constraints verbatim with their source, and the acceptance criteria
input.interjection You send a message while the agent is working: interrupt now, or after this step? The turn is cut short, or the message waits
Context: 14 decision points
Decision point Question Effect
skills.disclosure Which skills are relevant to this task? Only those enter the prompt; the rest can still be found
capability.disclosure Does this task need an installed pack or MCP server? Only then is it opened and its process started
tool.admission For each chunk of a long tool output: does it matter now? What matters enters the context; the rest is archived behind a pointer
tool.admission.test-log What in this test log is repetition? Exact repeats are folded losslessly; optionally, the judge chooses what to keep from the rest
context.forget Past a context threshold: which tool results are stale? Each stale result becomes a one-line tombstone in outgoing requests
context.compact Keep or prune this passage? Off by default. Compaction by judgment; no summary is written
memory.recall Which lessons apply to this task? They're brought into the turn
memory.capture Does this message correct the agent or set a rule? It becomes a lesson
memory.outcome The agent went in circles and found a way out: does that deserve a lesson? A lesson learned from the run, not from you
memory.worth The model or a subagent proposes a lesson: useful again, a one-off or already known? Kept or dropped
memory.merge Is it the same as an existing lesson, more precise or contradictory? No duplicates; the more precise lesson replaces the older one
memory.applied Were the recalled lessons followed this turn? A lesson that's often recalled and never followed is retired
skill.capture A long run ended well: was it a procedure, the same steps for the next task of its kind? It's drafted as a skill and waits for you; /skills accept installs it
cache.warming Will you be back before the prompt cache expires? The cache is refreshed, or left to expire
Tools and safety: 10 decision points
Decision point Question Effect
tool.risk The rules flagged a command: did you ask for it? If the judge is unsure, mu asks you
tool.approval In Judge mode: does the task clearly need this command, this change outside the project, this external action or this subagent? Only what the judge is sure of runs; mu asks you about the rest
tool.constraint Before a call that changes something: does it cross a constraint you stated? The call is stopped
tool.injection Passage by passage, in a web page, a search result, an MCP server's output or something a command fetched from another machine (curl, gh issue view): is there an instruction aimed at the AI? Those passages never reach the model; a note marks where each one was. A subagent that read such passages hands back its report under a warning
tool.description When an MCP tool's description first appears or changes: does it ask the AI for more than calling the tool (reading secrets, sending data elsewhere, hiding something from you)? The tool is removed from the model's list, calls to it are refused, and you're told
files.locate Which files match your description? Ranked candidates, instead of a string of greps
judge.items The model's own yes/no question, asked about each of many items: files, log lines, findings A probability per item through the judge_items tool, instead of reading them all
browser.step Observe, judge once, act: what's the next action, and on which element? The built-in browser moves one step
review.triage For each /review finding: does it change behavior, and is it about this change? Findings ranked P0 to P3
diagnostics.delivery New language-server diagnostics after an edit: report them now, at the next pause or never? Errors reach the model; style warnings don't
Turn: 8 decision points
Decision point Question Effect
turn.drift Every few steps: does the work still serve the goal? Rules catch the agent going in circles; the judge catches drift
turn.rewind The same failure, again and again: is this approach a dead end? Back to a checkpoint
turn.completion The model says it's done: did anything verify that? One nudge if not
turn.continue The run ends on "Let me run the tests next", or on a request for a go-ahead on work you already asked for: did it stop short? It's sent back to work, at most twice per message, and never toward a step that's hard to undo
output.drift While the model is writing: does the tail of its output cross your constraints? Off by default; corrected mid-stream
goal.met In goal mode, when the main model gives no answer: is the condition met? The fallback for /goal
board.read Where do things stand? Asked as multiple choice Feeds the plain-language board
notify.routing An event such as the context budget running low: tell the model now, later or never? The model hears about it at the right time
Teamwork: 5 decision points
Decision point Question Effect
swarm.routing Which role, model tier and thinking level suit this delegated task? The subagent that fits
swarm.patch Did the subagent's patch stay within its task? Judged from the task, the paths and the line counts
hive.publish Is a bee's finding worth posting to the shared board? Published, or kept to itself
hive.deliver Does a note on the board matter to this bee's work? Delivered only if it does
hive.relate Does a new finding supersede, contradict or support an earlier one? Corrections and disputes reach the bees that hold the old note

Every point, with its feature switch and options: docs/reference/decision-points.md.

Judges

  • Jev, TypeSafe's hosted judge model, answers bounded questions with probabilities. mu reaches it through TypeSafe, OpenRouter, the Vercel AI Gateway, OpenCode Zen, Cloudflare Workers AI or any service that speaks the same protocol, each with its own key (TYPESAFE_API_KEY, MU_JUDGE_OPENROUTER_API_KEY, AI_GATEWAY_API_KEY, OPENCODE_API_KEY, CLOUDFLARE_API_KEY with CLOUDFLARE_ACCOUNT_ID). You can pick one in the desktop app under Settings → Judges; by default mu uses the first one whose key is set.

    With no key set, Jev 1.13 on OpenCode Zen answers, free for a limited time. What it judges goes to OpenCode, which doesn't train on it, and mu reminds you of this once a day. Set a key (mu setup, or Settings → Judges in the app) and mu switches to it starting with the next question.

    Measured in the authors' own sessions: a warm question takes about 0.3 s over HTTP/2, and 16 chunks of tool output are judged in a single request in 0.44 s, with the shared state billed once.

  • mude 1.0 (local, a Mac with Apple silicon) is mu's own decision model, optimized for coding (more below).

  • OpenAI's decision model, gpt-6-luna, answers through OpenAI's Decisions API with an OpenAI API key: MU_JUDGE_OPENAI_KEY, or the OpenAI key mu already has. Pick it with mu setup --judge openai or under Settings → Judges (details).

  • Other decision models from Hugging Face (local, a Mac with Apple silicon): mu judge model add <link> (or Settings → Judges in the app) adds one that is packaged like mude 1.0 and makes it the judge. Laya is no longer included: a mu.json that still names it gets mude 1.0 in its place when mude is set up, otherwise the remaining judges or Jev, and mu says so once.

  • Any classifier model in pi's catalog can serve as a tier: classifier:<provider>/<model>. Examples include Cloudflare's Clef (clef, clef-flash), the System One models on OpenRouter and the Vercel AI Gateway, or a llama.cpp classifier.

  • Any LLM can serve as a tier: llm:<provider>/<model>.

Judges can be chained in tiers, cheapest first:

Judges in tiers, for a cascade such as mude,jev. All questions go to mude 1.0 first, local, about 0.1 seconds. What it is sure of becomes a verdict; a yes/no answer between 0.2 and 0.8 is uncertain and goes on to Jev, hosted, about 0.3 seconds. What is still uncertain, or what no judge answered, gets the fallback: what mu would do without a judge. The ledger records every answer and which judge gave it. A question a judge isn't trusted on skips it and goes on to the next.

mude 1.0, a decision model optimized for coding

mude 1.0 is mu's own decision model, optimized for coding: trained for the decisions a coding agent makes, and on mubench in the same range as Jev 1.14, the hosted default. It has 2B parameters and answers every question in a decision in one forward pass, with a probability for each answer. It runs on your machine, so what it judges never leaves it. Both editions, the full model and the MLX 8-bit edition (1.8 GB), are under the MIT license. For now, the one-step setup supports Macs with Apple silicon (macOS 14 or later, 8 GB of memory or more) and uses the MLX edition:

mu judge mude install               # download it, check every file, start it on 127.0.0.1 and make it the judge
mu judge mude status                # what is installed, running and enabled
mu judge mude enable --local-only   # mude only: nothing goes to a hosted judge
mu judge mude disable               # back to the judges you had before, and stop its server
mu judge mude uninstall             # remove the model and its Python environment

On a Mac that can run it, mude 1.0 is the recommended judge. mu setup offers it first, and in the desktop app the first-run guide's judge step has it preselected: one click installs it. Later, the Judges page in Settings installs, starts, stops and uninstalls mude, and its "Local only" switch is the same as --local-only. An install that stops (Ctrl-C, a lost connection, a power cut, quitting the app) picks up where it left off: run mu judge mude install again, or click "Continue installing".

By default, the judge you had before stays on as mude's fallback. What mude can't answer (its server is stopped, or it's unsure) goes to that judge, and so do two injection checks mude isn't trusted with yet. If that judge is hosted, as the default Jev is, what it reads leaves your machine. While it runs, mude's server uses about 4 GB of memory; mu judge mude stop stops it. On other platforms, you can serve the full model (bf16, PyTorch; a CUDA GPU is recommended) with its own System One server and add it to mu.json as a typesafe judge, as its model card shows.

mubench 1.0: how decision models compare

mubench is mu's benchmark for decision models. On its main board, every item is a request mu sent to a decision model, word for word, in a real coding session on an open-source repository. Each answer is scored by the cost of its consequences, and every model is compared with mu running without a decision model: 0 is no better, and 100 removes all the cost mu pays without one. The full leaderboard, with a sub-board of constructed scenarios, is at usemu.dev/en/mubench.

mubench 1.0, main board: overall score on 3,193 requests from real coding sessions on open-source repositories, with 95% intervals. mude 1.0 64.9 (59.1–72.3); Jev 1.14 63.1 (55.6–70.5); Jev 1.13 61.5 (53.8–69.1); d3-nano (original) 32.0 (21.3–39.0); no decision model: 0.

mubench 1.0, main board: scores per capability for mude 1.0, Jev 1.14, Jev 1.13, d3-nano (original). Permission approval: 52.6, 53.7, 52.7, 5.9; Malicious-instruction detection: not scored yet; Context compression: 64.6, 76.7, 70.7, −19.1; On-demand loading and reminders: −2.7, 16.8, 25.1, −118.4; Classification and routing: 83.6, 87.5, 85.8, 51.7; Progress and completion: 86.6, 61.6, 61.6, 70.1; Memory and lessons: 58.7, 75.1, 72.2, 40.5; Multi-agent collaboration: 19.8, 4.6, −0.8, 26.0.

Decision accuracy is a separate, plainer measure: the share of checks a model gets right, with every check counting the same, whatever a mistake on it would cost.

mubench 1.0: decision accuracy, with 95% intervals. Main board, 3,193 requests from real coding sessions on open-source repositories: No decision model 78.0% (75.9–80.2); mude 1.0 91.5% (89.6–93.3); Jev 1.14 90.1% (88.9–91.3); Jev 1.13 89.4% (87.7–91.1); d3-nano (original) 83.5% (82.1–84.9). Sub-board, 1,655 constructed scenarios: No decision model 44.5% (42.8–46.2); mude 1.0 92.1% (91.1–93.1); Jev 1.14 91.8% (90.8–92.8); Jev 1.13 91.1% (90.0–92.0); d3-nano (original) 80.1% (78.6–81.7).

How mu is built

The pieces. The desktop app (desktop/, which runs pi in a utility process over pi's RPC protocol) and the mu command (kyrn/bin/mu.mjs) both start pi, the coding agent: its agent loop, tools, sessions and providers. Inside pi runs the judgment kernel (packages/kyrn-judge): features hooked into pi's events, a decision engine with modes, judges and fallbacks, and the ledger. pi calls the main model. The engine asks the judges: Jev, mude 1.0, any classifier or any LLM.

Everything mu adds to pi is one extension, the judgment kernel in packages/kyrn-judge. mu's changes to pi itself are kept small and marked, so upstream pi changes merge cleanly; a workflow pulls them in every Monday. The mu command handles mu's own commands (setup, ledger, import…) and starts pi with the kernel. The desktop app runs the same pi and kernel in a utility process, so the app and the command line share their sessions.

Every decision point takes the same path, and a feature acts on a verdict only in active mode:

A decision, end to end, with tool.injection screening a web page. 1: a feature hooks a pi event, web_fetch returning a page. 2: it asks a decision point with a small state and a bounded question. 3: the engine checks the mode and picks a judge from its tiers, with a fallback. 4: the judge answers, for example yes 0.97 in 0.3 seconds. 5: the ledger records the verdict. 6: in active mode the feature acts and the passage is withheld. In shadow mode it stops at step 5. Without a verdict, mu takes the fallback and the ledger says why.

The code map, and where each step lives: docs/architecture.md.

Measured

Does handing the small calls to a judge make an agent finish more of the work, or only spend less? Two measurements so far: whole tasks, end to end, and what reaches the model from a failing test run. Both say what they don't show.

Whole tasks: Terminal-Bench 2.1

Same model, same tasks, same time limits, three attempts per task. mu passed 68.2% of its Terminal-Bench 2.1 attempts; pi, the harness mu is built on, passed 58.7%. mu failed less often in both ways: fewer of its attempts ran out of time with the task unfinished, and fewer finished with a wrong result.

88 tasks × 3 attempts, MiMo v2.6 Pro mu · Jev mu · pre-release mude pi
Attempts passed 180 of 264 (68.2%) 174 of 264 (65.9%) 155 of 264 (58.7%)
Difference from pi, 95% interval +9.5 points (+3.8 to +15.2) +7.2 points (+1.5 to +13.3)
Tasks mu passes more often / less often than pi 25 / 8 25 / 10
Failed attempts: out of time / finished wrong 65 / 19 71 / 19 81 / 28
Agent time per passed attempt 23.6 min 22.2 min 27.4 min
Cost per passed attempt $0.067 $0.063 $0.069

What this run is and isn't:

  • Terminal-Bench 2.1 through Harbor 0.24.0, at each task's own time limit. Harbor runs a task's tests even when the agent runs out of time, so an attempt can hit the limit and still pass. pytorch-model-recovery is left out of the totals, because the harness didn't pass its instruction to pi or mu in the first runs. Every configuration passed it in all three attempts on record, so leaving it out doesn't change the comparison.
  • MiMo v2.6 Pro with reasoning effort high, everywhere. pi 1.4.0 is the control. mu is mu-agent 0.1.12, built on pi 1.3.0, with its defaults; Jev is version 1.14. The mude column is a pre-release build with 24 layers, served on the same Mac. mude 1.0 is the 20-layer model made from it and hasn't been run on Terminal-Bench; neither has mu 0.2.x.
  • Three attempts per task, from 2026-10-22 to 2026-10-24, on one 16 GB Mac with Apple silicon. Attempts were rerun only for infrastructure failures, by rules set beforehand. Rosetta breaks four tasks for every configuration, so absolute pass rates are about 4.5 points lower than on x86_64 and can't be compared with the public leaderboard.

Every attempt's result is in docs/benchmarks/terminal-bench-2.1.csv, and the method is in docs/benchmarks/terminal-bench-2.1.md. The Harbor adapter that ran mu and pi, and a script that recomputes this table from the CSV, are in bench/harbor/.

What reaches the model: failing test logs

The numbers below come from the repository's own scripts. Folding was measured on 2026-10-25 with test-log-repeats.ts; goal-aware selection on 2026-09-21 with test-log-replay.ts, whose offline arms give the same results on today's code. The method and the full tables are in kyrn/docs/09-test-log-admission.en.md.

Exact repeats. A failing run often prints the same diff, DOM dump or stack trace once per failed test. mu keeps the first copy and replaces each later copy with a single line naming the lines it repeats. No model is called. The markers expand back to the original byte for byte, and the full log stays on disk, behind a pointer at the end of the output. How much goes depends on the runner: Jest and pytest print each failure's diff and stack trace in full, while Vitest's default reporter repeats less.

Failing test logs folded without loss: 40% of the characters in Jest logs from 4 open-source projects, 27% in pytest logs from 2, 9% in Vitest logs from 6, 6% in Vitest logs from mu's own CI and 51% in Vitest logs from the authors' sessions on September 21; 19.5% across all 71 logs, 2,453,384 characters.

A failing Vitest run of 338 lines scrolls past with its repeated diff blocks highlighted, then the same run as the model sees it: 135 lines, with one marker line for each folded block. 7,686 characters become 4,262, with no model call.

Goal-aware selection. With a verbose reporter, what's worth keeping depends on what you asked for. Passing tests are noise when you're debugging a failure, and evidence when you ask which tests ran. In a single request, the judge is asked about each block of passing tests and each block of test output: does the goal still need it? The summary and the failures are never put to the judge. A block is left out only when the judge gives "not needed" a probability of 0.9 or higher. In these measurements, the judge is Jev 1.13, the default at the time; they haven't been rerun with Jev 1.14.

On 29 tuned goals, Jev cut 40.2% and lost none of 72 required lines; a perfect judge cut 52.5%; keeping only failures cut 61.9% but lost 9. On 9 held-out goals, Jev cut 46.4% and lost none of 19; a perfect judge cut 46.5%; keeping only failures cut 59.4% but lost 6.

Perfect judge reads the labels, so it shows the most a correct judge could cut. Keep failures only is a judge that always answers "leave it out", which is effectively what a goal-blind filter does. The study's 282 live Jev requests cost about $0.017 in total at list price; with the default wording, the median request took 345 ms.

Both are off by default. To fold repeats, set "features": { "admission": { "testLog": "rules" } } in ~/.mu/agent/mu.json, or turn on Test log trimming in the desktop app's settings. Setting it to "jev" also asks the judge which of the remaining parts the current goal needs; /mu mode tool.admission.test-log shadow records that choice without acting on it.

What these numbers don't show:

  • The selection cases are real Vitest, node:test and pytest output from synthetic projects, plus 13 hand-written edge cases. The goals and labels were written by the authors. The held-out goals were labeled first and run once, and nothing was changed afterward.
  • They measure what reaches the model and what's lost, not whether the model then finishes the task.
  • The folding sample is mostly CI logs: from each of 12 open-source projects, chosen by test runner before measuring, its 6 most recent failed runs, and from mu's own CI its failed test runs since 2026-09-22, one failing log per run, cut to what mu's bash tool hands over (the last 2,000 lines or 50 KB). The 7 logs from the authors' sessions are the earlier sample. In their recent sessions the agent piped most test runs through tail, so few logs reached the 4,000 characters admission starts at.
  • Go and Cargo output isn't recognized as a test log, so it isn't folded.
The charts as tables
Goal-aware selection Tuned goals (29): cut Required lines lost Held-out goals (9): cut Required lines lost
mu · Jev 40.2% 0 of 72 46.4% 0 of 19
Perfect judge 52.5% 0 of 72 46.5% 0 of 19
Keep failures only 61.9% 9 of 72 59.4% 6 of 19
Failing test logs, one per run Logs Characters Folded
Jest, 4 open-source projects 14 584,229 40.1%
pytest, 2 open-source projects 5 255,721 26.7%
Vitest, 6 open-source projects 18 530,853 9.2%
Vitest, mu's own CI 27 942,761 6.0%
Vitest, the authors' sessions (2026-09-21) 7 139,820 51.0%
All 71 2,453,384 19.5%

The hive

A hive is two to six bees, each with its own focus. Bees read code, run commands and browse the web, but never edit; the main model makes the changes. Each time a bee finishes a message, hive.publish asks once: is there a finding, a dead end, a decision or a blocker here worth sharing? If so, it goes on a shared, append-only board. For each new note, hive.deliver asks once per other bee: does this touch its focus? If it does, the note is delivered, marked a finding, not an instruction.

The board is append-only, so an earlier conclusion stays even after a later one overturns it: a bee reports that the tests won't run, then unsets an environment variable and they do. hive.relate decides how two notes relate: supersedes, contradicts or supports. When a conclusion is superseded, a correction goes to every bee that holds the old note. When two notes contradict each other, both stay, marked as a dispute; if nobody settles it within a minute, a bee is sent to verify.

The desktop app's Hive tab after a /hive question: three bees, config, repro and tests, all done; a map of the findings they delivered to each other; and in the conversation, the answer with the line, the numbers and the failing test

You can watch all of this in the desktop app's Hive tab. Each bee gets a row: its role, its model and what it's doing or has just said. The map shows who delivered findings to whom, and the more findings travel along a line, the thicker it gets. Corrections and disputes have their own marks, and a line lights up the moment a finding arrives. The Information flow list shows the text of every delivery, and every verdict is listed too. The hive card in the conversation shows a miniature of the map and opens this tab.

/swarm shows what each bee is doing, /swarm stop asks them to report now and /swarm kill ends them. A bee that runs out of time is asked for its report and ended if none arrives, and a watchdog handles a stuck model or tool. A hive always reports back.

The plain-language board

With the board on (/board, or the switch on the desktop app's Board tab), each step the agent takes becomes one plain line on the board as soon as it finishes: a file changed, a check passed or failed, a command ran. Consecutive file reads are folded into a single line with a running count. Whenever the agent says something mid-run, board.read asks the judge whether it's news. If it is, a model chosen only for plain writing (/board model) rewrites it for a person and keeps the board's status current: what's happening now, how many checklist items are done and what's waiting on you. When a run finishes, a summary becomes the last line, with the full account kept above it, so you see what was done, not just that it's done.

The desktop app's plain-language board after the hive answered: waiting for you to say whether to fix it, the one question that needs you and what happened before, with context use and cache hit rate at the top

The board follows the permission mode, the goal and the subagents, and when the agent changes course, the wording follows. The two numbers at the top are context use and cache hit rate.

The desktop app

A desktop app with mu and its runtime built in: there's no Node.js to install and nothing to download on first launch. It has everything the command line has, plus a work panel beside the conversation:

Board · Judge (the live ledger: every verdict with its question, decision point and latency) · Hive · Lessons · Files · Preview · Source · Browser (the built-in browser the agent drives one step at a time; it shows the goal and lets you pause or stop)

The mu desktop app after a bug fix in relay, a job-queue project: jobs with a 1h30m timeout were killed after an hour because a minute was defined as 1,000 ms. The judge classified the message as a multi-step task (input.preflight), let both test runs through (tool.approval) and found the turn complete (turn.continue). The Judge tab on the right lists each verdict with its decision point and latency, about 60 to 120 ms. The sidebar holds earlier conversations in three projects, and the bar along the bottom shows the judge (Jev, through TypeSafe), 38 of 40 decision points active, 5 verdicts and the context in use.

A bar along the bottom keeps the kernel in view: which judge answers and where it runs, how many decision points are active and, in a conversation, the verdicts so far, the latest judge latency and the context in use. The permission mode and the goal sit in the composer, and ⌘K opens the command palette. You connect models inside the app: sign in with ChatGPT, or add an API key for any provider pi supports. You can import Claude Code, Codex CLI and ZCode conversations and continue them.

GitHub Actions builds the app for macOS (Apple silicon / Intel), Windows (x64 / Arm) and Linux (x64 / Arm) and publishes it under Releases.

Command line

npm i -g mu-agent
mu            # interactive session in the current directory
mu doctor     # check the installation, the judges and the connections

mu's welcome screen in a terminal: the μ mark, "mu v0.1.10, judgment-first coding agent, built on pi 1.3.0", then the judge (Jev, answering in 137 ms, decision points active), the model and the working directory, and the key bindings worth knowing.

Requires Node.js 22.19 or newer. mu -p "prompt" runs a single prompt and prints the answer; mu -c continues the last session. mu import --list finds your Claude Code, Codex and ZCode conversations, and mu import <file> brings one in with its full history; importing it again later brings over what's new. mu ledger [n] prints what the judge decided in the last n sessions. The command line and the desktop app share accounts, settings and lessons.

Command What it does
/status Show the judges, each decision point's mode, what was kept out of the context and the latest verdicts
/mu judge <judges> Set which judges answer, in which order: jev, mude,jev, jev-opencode-free, openai, classifier:<provider>/<model>, llm:<provider>/<model>
/mu route <point> <judge> Give one decision point its own judge
/mu mode <point> <off|shadow|active> Switch one decision point's mode
/frame Show the task frame: the goal, your constraints with their source and the acceptance criteria
/goal <condition> Keep working until the condition holds; /goal clear ends it
/permissions Choose Full access, Judge mode or Ask first
/board Turn the plain-language board on or off
/remember, /lessons, /forget Keep a lesson, list lessons, retire one
/skills Show the skills mu drafted from runs, and accept or reject each
/review, /commit Review the change, with findings ranked P0 to P3; write the commits
/checkpoints, /rewind List checkpoints; go back to one
/agents, /swarm List subagent roles; watch running subagents
/browse, /jobs Open the built-in browser; list background jobs
/capabilities, /ledger Show installed capabilities and which are turned on; show the latest verdicts
/import-chat Import a Claude Code, Codex or ZCode conversation
/doctor Check the setup and the connections

pi's own commands (/model, /thinking, /login, /resume, /tree, /fork, /compact, /export and the rest) work as they do in pi, except that /login offers no Claude subscription sign-in: Anthropic doesn't allow other apps to offer one, so use an Anthropic API key. MU_JUDGE=mude,jev mu overrides the judges for a single run.

Privacy

Your keys stay on your machine. mu never downloads a model or a runtime on its own; anything that needs a download asks first. The judge sees only the fields a question needs. With no key set, those fields go to the free Jev on OpenCode Zen. To keep everything on your machine, use mude 1.0 with --local-only, MU_JUDGE=off or mu setup --judge off (no judge is asked, and mu's features fall back to their own rules). Every verdict is logged locally, and you can read all of them. The desktop app sends no telemetry or crash reports. Details are in SECURITY.md.

Documentation

Contributing

Bug reports, fixes, new decision points, judge measurements and translations are welcome, in English or Chinese. Start with CONTRIBUTING.md; issues labeled good first issue are a good way in.

npm install --ignore-scripts   # install dependencies without lifecycle scripts
npm run hydrate:model-catalog  # write the model list from the pinned catalog (offline)
node kyrn/bin/mu.mjs           # run mu from this checkout
npm run check                  # formatting, lint, types
./test.sh                      # tests (those that need a model are skipped without a key)

The desktop app lives in desktop/. Run npm install at the root first, then bun install and KYRN_ROOT="$(cd .. && pwd)" bun run start in desktop/ to run the development build against the mu in this repository.

Everyone taking part follows the Code of Conduct. Report security problems privately, as described in SECURITY.md.

Community and support

Citation

If you use mude in your work, please cite it:

@misc{mude2026,
  title        = {mude 1.0: a decision model optimized for coding},
  author       = {qybaihe},
  year         = {2026},
  howpublished = {Hugging Face},
  url          = {https://huggingface.co/qybaihe/mude-1.0},
  note         = {MIT License. MLX 8-bit edition for Apple silicon: https://huggingface.co/qybaihe/mude-1.0-mlx-8bit}
}

Credits and license

mu is under the MIT license (LICENSE; the desktop app's is desktop/LICENSE). It is built on pi (the coding agent, MIT), and we're grateful to its authors. Some decision points build on ideas from other projects: the wording of the prompt-injection screen comes from hermes-jev-skills, and the continuation check (turn.continue) and the bulk judging tool (judge_items) are based on oh-my-pi. Third-party code in the judgment kernel is listed in THIRD_PARTY_NOTICES.md. mude 1.0 is a fine-tune of d3-nano (Decision 3.0, vLLM Semantic Router Team), built on Qwen3.5-2B; both are Apache-2.0, and the model's repository keeps their notices.

The desktop app began as a fork of AionUi; the files it took from AionUi, listed in desktop/APACHE-FILES.txt, stay under the Apache License 2.0 (see desktop/NOTICE).

About

mu (μ): most of what a coding agent decides isn't code. mu hands 40 kinds of yes/no calls to a small model: fewer wasted tokens, fewer approvals on autopilot, fewer runs that stop halfway. Built on pi.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

553 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages