mau-agent
v0.0.12
Published
Standalone multi-provider coding-agent broker with native CLI parity, proactive account governance, and provider-neutral sessions.
Maintainers
Readme
MAU Agent
MAU Agent is a local-first, multi-provider foundation for running official Claude Code and Codex CLIs with isolated accounts, provider-neutral routing, usage governance, bounded delegation, and auditable receipts.
This package does not contain AgenticOS data, provider credentials, personal configuration, or a hosted service. It runs on the user's machine and launches official provider binaries that the user installs and authenticates.
Developer preview: provider discovery, account management, usage refresh, the governed direct shell, governed Claude remote control, and bounded public task constructor described below are supported CLI surfaces in
0.0.1. The authenticated local broker also exposesdaemon start|status|stop, and the policy-governed MCP gateway has explicit configuration and invocation commands. Bounded, payload-free ledger queries are also public.
Requirements
- Node.js 22 or newer.
- The official
claudeand/orcodexCLIs. MAU installs missing ones automatically at shell start (and keeps npm-managed ones current);mau install [claude|codex|all]does the same on demand. SetMAU_AUTO_PROVIDERS=offto disable all automatic provider management. - A provider subscription or API arrangement accepted by that official CLI.
MAU installs and updates provider CLIs through ordinary npm install --global
of the official packages and does not bypass their terms, usage limits,
authentication, permissions, or sandbox.
Install from a colleague's checkout
Until a release is published, install from a trusted local checkout or tarball:
cd "path\to\MAU Agent"
npm.cmd ci
npm.cmd run check
npm.cmd test
npm.cmd pack
npm.cmd install --global .\mau-agent-0.0.1.tgz
mau doctorOn macOS or Linux, use npm instead of npm.cmd. Review the archive contents
printed by npm pack before installing it. Re-run npm install --global after
installing a newer archive.
For development without a tarball:
npm.cmd ci
npm.cmd run build
npm.cmd link
mau --helpQuick start
Inspect installed providers without authenticating or making a model call:
mau doctor
mau discover
mau parity
mauProvider CLIs are managed automatically: starting the shell (mau /
mau shell) installs any missing official CLI and updates npm-managed ones
when the registry has a newer release (checked at most every 6 hours, cached
under the MAU data root, fail-open when offline). Native installs such as the
claude.exe installer update themselves and are never touched. To check or
update immediately, or after disabling automation with
MAU_AUTO_PROVIDERS=off:
mau install # install anything missing, update anything behind
mau install codex # or one provider by nameInstallation is an ordinary npm install --global of the official package and
makes no model call. Authentication still happens afterwards in the provider's
own login flow (mau account login).
Already logged in to claude or codex on this machine? Then plain mau is
enough: at shell start MAU probes the providers' default homes
(CLAUDE_CONFIG_DIR / %USERPROFILE%\.claude, CODEX_HOME /
%USERPROFILE%\.codex) with a bounded local read — no network, token values
never logged — and registers a detected login as claude-default /
codex-default (a legacy home: never moved, modified, or auto-deleted). This
only happens while a provider has zero registered accounts; once you add or
import any account for a provider, MAU never touches its detection again.
MAU_AUTO_PROVIDERS=off disables it, and mau doctor shows what would be
registered. For multi-account setups, use the isolated-accounts flow below.
The model list is discovered, not hardcoded: on the same 6-hour cadence MAU
lists Claude models with an enabled account's own OAuth token (metadata only,
the same bounded read as the usage probe — no prompt or completion) and merges
them into /model and constructor routing. Newly discovered families start
with conservative capabilities (unknown families are plain executors). Codex
has no documented session-free model-list surface, so Codex entries come from
the bundled catalog. <data root>/models.json is an explicit override file
(replace-by-id or append) that always wins.
mau discover writes machine-specific capability manifests beneath .mau/ in
the current working directory. mau parity reads those manifests. They are
local evidence, not portable proof that another machine supports the same
surface.
Create an isolated account home and complete the provider's own login:
mau account add claude claude-work "Claude work"
mau account login claude-work
mau account add codex codex-personal "Codex personal" worker,review
mau account login codex-personal
mau account list
mau account usage
mau status
mau discover
mau shell
# Launch Claude's official remote-control surface after usage admission:
mau remote-control project-session
# Pin one configured Claude account (it must still pass the governor):
mau remote-control project-session --account claude-work
# Native Claude arguments must follow the separator:
mau remote-control project-session -- --permission-mode plan
# Add a bounded constructor task. Every scope and deterministic gate is explicit:
mau task add feature-nav "Build the feature navigation" --scope src/navigation --accept "navigation tests pass" --verify "npm.cmd test"
mau task list
mau task status feature-nav
mau task run --max-parallel 2Account IDs are local stable names. The optional surface list is a
comma-separated subset of interactive,master,worker,review; all four are used
when omitted.
Edit only display/routing policy fields without changing an account's provider, stable ID, or isolated home:
mau account edit claude-work --label "Claude primary" --surfaces worker,review --reserve 10 --soft 90 --hard 98Thresholds must satisfy 0 <= reserve <= 100, 0 <= soft < hard <= 100, and
leave a positive effective usable ceiling (min(soft, 100 - reserve)). The
registry update is locked and atomic.
mau status is an aggregate local snapshot: broker state, stored provider
manifests, enabled account surfaces, fresh cached usage, and quota-park state.
It does not discover providers, refresh quota metadata, call a model, or print
account config/credential paths.
Inspect the canonical local ledger without launching a provider:
mau ledger status
mau ledger events --limit 20
mau ledger session session-id --limit 20
mau ledger memory "review rejection" --limit 10
mau ledger context "constructor landing" --budget 4000
mau ledger compact session-id --budget 4000Ledger output is bounded and payload-free by default. Memory/context views use allowlisted summaries, and compact handoffs fingerprint the requested session instead of echoing its native identifier. These commands do not read blobs, print account/session metadata, refresh usage, or make model/provider calls.
Bare mau starts the hidden local broker when needed and opens the interactive
shell (mau shell is the explicit equivalent). The broker keeps durable state
and background work alive after the terminal closes; normal use does not
require mau daemon commands.
Typing / immediately opens a filtered command list. Continue typing to
filter, use Up/Down to select, Tab to complete, and Enter to run. /add opens a
provider picker, creates an isolated account, then launches the official login.
Account IDs are normalized to lowercase machine-safe slugs while display labels
preserve their casing. /account-list and /account-usage are direct aliases. Ordinary text sends a
governed turn. /model and /effort
open keyboard pickers; they also accept an explicit argument. /status,
/governor, and /usage show local state without a model call. /help lists
the exact available command registry and /exit returns to the terminal.
The interactive shell uses a Codex/Claude-style terminal composer. Up/Down
recalls prompt history, including restoration of an unfinished draft. While a
provider turn is running, keep typing and press Tab to queue a bounded follow-up;
Enter prioritizes the message as the next turn, while Tab appends it to the
bounded FIFO tray. Alt+Up pulls the last queued message back into the composer.
Esc or Ctrl+C
interrupts the active turn without advancing a failed or cancelled native
session. Shift+Tab cycles manual, auto, and plan modes: Claude receives its
documented permission mode and Codex receives a safe read-only or
workspace-write sandbox policy; MAU never maps this control to a dangerous
sandbox bypass. The selected mode is stored atomically under MAU's global
state, survives restarts, and follows every later model and account switch.
Alt+, and Alt+. step effort for the next turn. ? opens the
shortcut panel, Ctrl+O opens the transcript view, and Ctrl+T opens the task
panel. /model, /effort, /status, /usage, /governor, /permissions,
/sessions, and /help remain live while a provider is working; they bypass
the message queue without interrupting the active turn. The live footer shows the active model and effort, routed provider
account, working directory, Git branch, explicit context availability, queued
count, named project/branch session, mode, active file, current provider phase,
and elapsed time. A 100 ms spinner turns amber for long work and reports a
provider stall after 20 seconds without an event. Provider-emitted token totals
are shown as real telemetry; missing totals remain unknown. Tool/progress/error
events and bounded numbered red/green file diffs are rendered as terminal-safe
transcript rows when the turn completes.
The direct shell also reuses the public local handlers for /account,
/mcp, /tools, /plan, /agents, and /doctor. /agents is a direct view
of the real constructor task graph rather than a placeholder. /sessions lists locally stored
opaque native-session references, while /permissions displays MAU's active
MCP policy baseline; neither contacts a provider. Examples:
/account list
/mcp list
/tools
/plan list
/sessions
/permissions
/memory task
/context task --budget 4000
/compact session-id --budget 4000
/doctorCommands without a safe direct-shell implementation are marked unavailable and
omitted from /help, rather than being advertised as working placeholders.
Before every ordinary turn, the shell refreshes exact usage, projects the turn against all provider windows, selects an eligible account for the active model's provider, and preserves affinity when capacity is similar. If no account is safely admissible, the turn is parked and no provider prompt is sent. A completed bridged turn retains its native session identifier for the next turn on that provider/account.
mau task add, list, status, and run use the authenticated local daemon;
start it first with mau daemon start. list and status read bounded local
task state only: they do not refresh usage, call a provider, or trigger work.
mau task run acknowledges a background trigger immediately, and the daemon
dispatches only dependency-ready, non-overlapping scopes. It
refreshes exact usage, selects a quota-admissible author in an isolated Git
worktree, sends finished work once to a reviewer from the other provider
family, permits at most one targeted author correction, runs the declared
verification commands without a shell, and fast-forward lands only verified
work. Quota and provider-capacity exhaustion park the stored phase and preserve
partial work. Rebase conflicts remain awaiting-integration with the worktree
untouched. A durable runner lock plus the daemon trigger guard prevents two
runners from claiming the same queue. A second trigger reports that a runner is
already active. Graceful mau daemon stop refuses while a task run is active;
forced termination is recovered as preserved work on restart.
Use MAU constructor tools from Claude Code
MAU includes its own bounded stdio MCP server. Start the daemon, then register the server from the repository that Claude should work on:
cd "C:\path\to\project"
mau daemon start
claude mcp add mau -- mau serve-mcp
claude mcp get mauThe server exposes only mau_status, mau_task_submit, mau_task_list,
mau_task_status, and mau_task_run. It authenticates internally to the local
daemon and never returns its handshake secret, account paths, provider
credentials, raw ledger payloads, or session identifiers. Status/list tools are
local reads and make no model or provider call. The run tool cannot accept a
repository path: it is permanently bound to the mau serve-mcp process working
directory, and the normal governor remains authoritative before any constructor
provider work. Model-submitted verification gates are direct argv only; shell
executables and shell syntax are rejected.
mau remote-control [session-name] refreshes exact Claude usage and applies the
same fail-closed account governor before it starts Claude's official
--remote-control surface. Named sessions retain account affinity only while
that account remains safely admissible; capacity and reserve win over affinity.
--account id restricts selection but never bypasses usage, enabled-state,
surface, cooldown, or quota checks. MAU passes terminal streams and arguments
after -- directly to Claude and does not inspect or emulate the remote-control
protocol.
Temporarily exclude an account or remove its registry entry:
mau account disable claude-work
mau account enable claude-work
mau account remove claude-workRemoving an account does not delete its home by default. To delete a MAU-created managed home as well:
mau account remove claude-work --delete-homeThe deletion guard only permits a managed directory beneath MAU's canonical accounts root. Imported/legacy homes, the user profile, filesystem roots, Git repositories, and paths escaping through a link or junction are not eligible for automatic deletion.
Existing official-client homes can be registered without moving them:
mau account import claude existing-claude "C:\Users\me\.claude" "Existing Claude"
mau account rename existing-claude "Primary Claude"Imported homes are marked legacy: MAU can remove the registry entry but will
never recursively delete that directory.
Account isolation and local state
Each managed account receives its own official-client configuration directory:
| Platform | Default MAU data root |
| --- | --- |
| Windows | %APPDATA%\mau-agent |
| macOS | ~/Library/Application Support/mau-agent |
| Linux | ${XDG_CONFIG_HOME:-~/.config}/mau-agent |
Set MAU_AGENT_HOME to an absolute alternative before using MAU if needed.
Changing it selects a different registry; it does not migrate existing data.
Claude is launched with an isolated CLAUDE_CONFIG_DIR; Codex is launched with
an isolated CODEX_HOME. Authentication happens in the real provider terminal.
MAU strips credential-shaped environment variables from that login process so
one account or provider is not silently authenticated by another provider's
environment.
An account home controls provider configuration and login identity. It does not grant an agent access to the whole computer. File and command access still comes from the working directory, the official provider's permission and sandbox settings, operating-system permissions, and any narrower MAU policy.
The registry and usage cache use bounded files, atomic replacement, backups, and ownership-aware locks. Treat the MAU data root as private user data and do not sync or commit it.
Usage and governor behavior
mau account usage refreshes metadata for every enabled account and prints
five-hour and weekly windows where the provider exposes them:
- Claude reads the selected account's OAuth token only long enough to call Anthropic's usage-metadata endpoint. The token is not returned, logged, copied to another account, or persisted by the probe.
- Codex asks the official
codex app-serverprocess for rate limits while selecting that account'sCODEX_HOME; MAU does not read the Codex token. - Governed remote control currently exposes Claude's documented native surface only. Codex is not presented as an equivalent remote-control protocol. Admission happens before launch; an active native Claude remote-control process remains bound to its selected account and is not migrated mid-session.
These probes do not send a prompt or make a model/completion call. Missing,
malformed, stale, or unavailable metadata remains unknown; it is not guessed
as 0%. Governor admission validates all relevant windows, projects
post-task utilization, preserves configured reserve, and parks quota-blocked
work for a reset/reprobe rather than classifying quota exhaustion as a code
failure.
Default account thresholds are a 10% reserve, 90% soft ceiling, and 98% hard
ceiling. Use mau account edit to tune them per account.
Native, bridged, and unified behavior
- Native launches or attaches to the real provider CLI. The provider owns its TUI, slash commands, model picker, approvals, MCP lifecycle, native sessions, and remote-control behavior. MAU does not emulate those surfaces.
- Bridged uses a documented machine interface for bounded work: Claude structured headless output or Codex JSON/App Server. A bridge validates its first real turn live and records integrated conformance evidence keyed to the exact executable, version, and discovered capability hash. This avoids a separate setup/model call. Fixture evidence cannot enable production bridging, and version drift demotes the capability to native.
- Unified is MAU-owned behavior: account eligibility, governor decisions, routing contracts, canonical handoffs, scheduling, worktree reservations, bounded review, landing receipts, approvals, and MCP policy.
A bridged run is not successful merely because its process exits with code zero. Malformed output, a missing or duplicate terminal result, unexpected session identity, truncation, timeout, cancellation, and provider error events produce explicit failed receipts.
Claude supports a documented non-mutating session fork when discovered and
conformance-tested. Codex exec resume is not presented as a fork because no
equivalent documented non-mutating surface was found.
MCP and security model
The MCP gateway supports scoped server definitions and environment references, bounded payloads, explicit policy decisions, and human approval callbacks. A delegated task receives only its named tools/actions/resources. Unmatched writes and consequential operations fail closed. The included Salesforce baseline hard-blocks consequential production actions and requires approval for production writes.
This is application policy, not an operating-system sandbox. Native provider security controls and OS permissions remain authoritative. Do not put secrets in prompts, labels, task text, logs, capability manifests, or handoff summaries.
Configure a local stdio server using environment variable names, never literal credential values:
mau mcp add salesforce sf-mcp --env SF_TARGET_ORG --scope global
mau mcp list
mau mcp tools
mau mcp call salesforce query '{"soql":"SELECT Id FROM Account LIMIT 1"}' --action read --environment productionmau mcp call requires the caller to classify the action. Policy-required
approval is a one-call terminal prompt and defaults to denial. Hard-denied
actions are rejected without prompting. Server definitions are stored
atomically under the MAU data root and contain environment names only.
MAU launches children without a shell, validates executable shims, bounds machine-interface output and runtime, hides noninteractive Windows subprocess windows, and terminates bounded worker process trees on timeout or cancellation. Interactive native sessions intentionally inherit the user's terminal.
Current limitations
- The direct shell currently wires ordinary governed turns,
/model,/effort,/add,/account,/account-list,/account-usage,/usage,/governor,/permissions,/sessions,/mcp,/tools,/memory,/context,/compact,/plan,/agents,/status,/doctor, discovered native provider commands, help, and exit. - Provider-neutral
/resumeand/fork, provider-native subagent steering, normalized/skillsand standalone/reviewremain unavailable. Ordinary shell turns automatically resume the current provider/account session; constructor review is available only as the bounded phase inside/plan run. - The authenticated daemon accepts bounded task submission, inspection, and background run triggers. Ledger queries are read-only and payload-free; raw blob retrieval is not public.
- Automated task author/review requires version-matched integrated bridge evidence. If a provider is available only through its native interactive surface, the task parks rather than pretending it can automate that session.
- Verification commands are direct executable-plus-argv gates; shell operators,
pipelines, and ambient shell expansion are intentionally unsupported.
Integration conflicts preserve the worktree for human resolution and require
another
mau task runafter the rebase is clean. - Fable 5 routing policy exists in the model/routing modules but does not turn this package into a bundled Fable model or include provider access.
- The direct shell switches eligible accounts within the active model's
provider. It does not silently change model families; use
/modelto do so. - Usage metadata is provider-dependent and may become unavailable when an upstream interface changes. Unknown usage fails closed in governor admission.
- Native provider session files are not portable across model families. During one live MAU shell, switching families sends only the unseen bounded canonical conversation delta; MAU never copies provider credential/session stores.
- Upstream CLI changes require rediscovery and fresh integrated conformance evidence before affected bridged behavior can resume.
- The project currently has no declared open-source license. Possession of a package does not grant redistribution or modification rights; obtain the owner's permission.
Development and verification
npm.cmd ci
npm.cmd run check
npm.cmd test
npm.cmd run doctor
npm.cmd run discover
npm.cmd run parity
npm.cmd pack --dry-runThe detailed provider inventory, architecture notes, parity matrix, and bridge
conformance contracts are included in docs/.
