muster
Launches and manages instructed coding agents (Codex, Claude, OpenCode) over MCP.
run: Start a session or one-shot task with a required prompt and runtime; configure cwd, kind (session/task), host (auto/tmux/pty/macos-terminal), permissions (deny/auto/bypass), sandbox (read-only/workspace-write/full-access), MCP servers, open in a terminal viewer (Terminal.app/iTerm2/Ghostty), and pass runtime args after
--.list: List Muster-owned sessions and tasks, optionally filtered by kind, including host capabilities.
stop: Stop a run by durable ID, unambiguous peer name, or canonical address.
output: Read captured output (stdout/stderr and exit status) from a task run.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@musterRun a Codex session to review the authentication flow"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Muster
Muster launches instructed Codex, Claude Code, or OpenCode agents on this machine. A
session returns an address only after its runtime is reachable. A task
runs once, captures output, and never advertises a peer address.
Live launch verification: Codex and Claude both launched and answered their initial prompts without terminal interaction. OpenCode 1.18.31 passed the loopback API and local-provider protocol checks. Claude requires a directory already trusted by the operator. The automated suite uses fake runtimes, not real models.
Install
npm install -g @brutalsystems/muster
muster --versionPublishing a release does not touch an installed copy: muster --version keeps
reporting the old version until you update it.
npm update -g @brutalsystems/musterIf which muster resolves to a version-manager shim (for example
~/.asdf/shims/muster), run that update under the Node the shim resolves to and
reshim afterwards — asdf reshim nodejs — or the shim keeps pointing at the old
binary.
An MCP server starts once at session startup, so an agent session that already has Muster loaded keeps running the old binary until that session restarts. Updating on disk is not enough; restart the session too.
Related MCP server: pokeclaw
Build and run locally
npm run check is the local gate: it builds, runs the suite, then packs and
verifies the tarball — the same scripts/check-tarball.mjs the CI packing job
runs, so the two cannot disagree about what "verified" means. npm test alone
does not pack anything, so tarball drift is green locally and red on push.
It is not everything CI does: CI additionally runs the suite across the Node
version matrix, and the contract suite runs only on release. Passing check is
necessary rather than sufficient.
Requires Node 22.12+ (tested with 24.16), TypeScript 5, Codex 0.155.1, Claude
Code 2.1.267, and OpenCode 1.18.31 or newer. Newer OpenCode releases must retain
the CLI and loopback HTTP API used by Muster. Terminal drivers use tmux or
node-pty. Process discovery currently requires a POSIX host with ps and
lsof; the terminal interface itself is platform-neutral. The macOS Terminal
driver is an unavailable v1 stub.
Before launching a Claude session, open Claude normally in the target directory and complete its workspace-trust review yourself, then exit that setup session. This is a one-time prerequisite for each directory Claude requires you to trust. Muster never accepts trust prompts or changes trust settings. An untrusted directory can block startup; Muster times out and cleans up that launch.
npm ci
npm run build
node dist/muster.js run codex --prompt 'Review the authentication flow'
node dist/muster.js run claude --prompt 'Summarize the project' --host tmux
node dist/muster.js run opencode --prompt 'Review this project'
node dist/muster.js run opencode --prompt 'Build a plan' -- --model coldfire-local/qwen3-30b-a3b
node dist/muster.js run codex --kind task --prompt 'Explain the test layout'
node dist/muster.js run opencode --kind task --prompt 'Summarize the tests'
node dist/muster.js list
node dist/muster.js list --format human
node dist/muster.js list --kind task
node dist/muster.js output RUN_ID
node dist/muster.js stop THREAD_OR_SESSION_OR_RUN_ID--prompt is required and cannot be blank. --cwd defaults to the current
working directory. --kind defaults to session. All commands except output
emit JSON; output prints the captured task output. stop also accepts an
unambiguous peer name or canonical address, refusing ambiguity with candidates.
Use the durable ID to stop a session whose runtime has renamed it.
For readable terminal output, add --format human to run, list, stop, or
doctor:
muster run codex --prompt 'Review this project' --format human
muster list --format human
muster stop THREAD_OR_SESSION_OR_RUN_ID --format humanHuman output keeps full IDs and shows directory, host, state, and relevant
attach/output/stop commands with actual IDs. pty sessions are labeled as not
watchable or attachable. --format json is explicit JSON; omitting the flag
still returns JSON. Put Muster options before any -- RUNTIME_OPTIONS.
output always prints captured task text and does not accept --format.
MCP tools retain their existing JSON responses.
Human output uses subtle colors in interactive terminals: green for idle or
running, yellow for busy or starting, gray for ended states and field labels,
red for failures or nonzero exit codes, and cyan for follow-up commands. IDs
and paths retain the normal text color. Set NO_COLOR=1 to disable colors;
piped output and TERM=dumb are always uncolored. JSON never includes colors.
run accepts an optional -- followed by runtime arguments. The normal
allowlist is --model / -m, plus Claude's --effort and OpenCode's --agent
and --variant. Unknown options, bundled short options, config injection and
raw permission overrides are refused, even with allow_dangerous_flags
enabled. Use Muster's normalized permission flags. Prompt strings are always
passed as one literal argument. Codex and Claude launches and OpenCode tasks put
that value after --; OpenCode sessions use the dedicated --prompt value.
OpenCode inherits the provider and model definitions from its normal user and
project configuration, so configured local OpenAI-compatible providers such as
coldfire-local/qwen3-30b-a3b remain available. Muster never rewrites those
files. Put runtime options after --, as in the local-model example above.
muster run opencode --prompt 'Review this project'
muster run opencode --prompt 'Build a plan' -- --model coldfire-local/qwen3-30b-a3b
muster run opencode --kind task --prompt 'Summarize the tests'
muster run opencode --mcp tincan --permissions auto --sandbox workspace-write --prompt 'Coordinate'Terminal lifetime
Add --open to display the launched session in a new Terminal.app window on macOS:
muster run codex --open --prompt "Review this project" --format human
muster run claude --open --terminal ghostty --prompt "Review this project" --format human
muster run opencode --open --terminal iterm2 --prompt "Review this project" --format human
muster run codex --open --terminal iterm2 --prompt "Review this project" --format humanMCP run accepts open: true. This requires tmux and selects it when the host
is auto; explicit pty hosts and tasks are rejected. Detached launch remains the
default. --terminal auto|terminal|iterm2|ghostty requires --open; omitted or
auto uses Terminal.app. MCP accepts the same terminal values. Explicit
choices never silently fall back. iTerm2 and Ghostty must be installed as
iTerm.app or Ghostty.app in /Applications or ~/Applications.
The host remains tmux. Successful results include terminal_opened: true and
the resolved terminal (a launch event, not a live window-status check).
Closing the Terminal window leaves the session running; use muster stop <id>
to stop it. Terminal.app and iTerm2 may require macOS Automation permission.
Ghostty opens a separate app instance that exits when its last window closes;
that instance disables saved-window restoration so previous tabs and windows
are not duplicated. It uses the Ghostty macOS launch interface.
Terminal.app creates the requested window before activation
to avoid also opening a default shell window on startup.
iTerm2 uses its documented scripting interface.
If the launch request to the viewer fails,
Muster stops the launched session and returns an error.
Auto-selection tries tmux, then pty. Every peer includes host, capabilities
and attach_hint. Watchability is separate from the runtime's idle/busy state.
tmux: each agent has its own session on the dedicated
mustertmux server. Opening or exiting one agent does not switch another agent's viewer. Watchable and attachable; survives the CLI or MCP server exiting. Use the returned attach hint to reconnect to that agent.pty: not watchable or attachable. The CLI prints the peer record and stays running to own the terminal. Ctrl-C stops it. MCP-owned pty sessions stop when the MCP server disconnects. There is no persistent pty daemon.
task: a per-run worker captures stdout/stderr and exit status after the launching CLI exits. It supervises one task, with no retry or restart behavior.
list refreshes live session metadata and shows ended runs distinctly. A timeout
or startup failure cleans the process tree and host window, logs failure, and
returns an error instead of a peer record.
Each OpenCode session owns a separate HTTP server bound to 127.0.0.1 on a
Muster-selected port. Muster verifies that the listener belongs to the launched
process tree, stores its server_url and durable session_id, and never attaches
to an existing personal OpenCode server. list refreshes the session through
that endpoint; stop aborts it best-effort and still performs authoritative
process-tree cleanup. The URL is local control metadata, not a public address.
OpenCode sessions otherwise use the same tmux/pty, viewer, list, stop, and human
output behavior described above; OpenCode tasks use the same detached output
and exit-status lifecycle as other tasks.
Configuration and permissions
Muster reads ~/.muster/config.toml once at startup and never writes it.
Missing configuration uses these defaults:
host = "auto"
launch_timeout_sec = 30
max_concurrent = 4
permissions = "deny"
sandbox = "read-only"
allow_dangerous_flags = false
default_mcp = []Choose sandbox = "workspace-write" yourself when agents should edit files.
full-access and permissions = "bypass" require allow_dangerous_flags = true.
The old config spelling danger-full-access remains accepted as an alias.
Per-launch --permissions and --sandbox override these config defaults. The
same named fields are accepted by MCP run. Both session and task launches
support them:
muster run codex --permissions auto --sandbox workspace-write \
--prompt 'Implement the change' --format human
muster run claude --permissions auto --sandbox workspace-write \
--prompt 'Implement the change' --format humanMuster permissions | Codex translation | Claude Code translation | OpenCode translation |
| Approval policy | Permission mode | Deny write, shell, task, external-directory, web, and unselected MCP operations |
|
| Permission mode |
|
| Bypass approvals and sandbox | Permission mode | Allow supported operations |
deny refuses actions that would require approval; it does not prohibit tools
already allowed by the sandbox or permission rules. auto delegates permission
review to the runtime and may still reject an action; it is not blanket approval.
Auto mode requires workspace-write in Muster because the Codex preset selects
that sandbox. Explicitly select it; Muster never widens a read-only request.
Bypass requires full-access; combinations claiming a sandbox while bypassing
it are refused. deny can be combined with any authorized sandbox setting.
full-access disables the runtime command sandbox and requires operator-owned
config authorization even without bypass. Muster never writes that config.
Config defaults apply to subsequent launches; overrides apply to one launch.
Resolved permissions and sandbox are returned in records, shown in human
output, persisted for listing, and written in the pre-launch log. Old records
without those fields remain readable; their settings are not guessed.
The runtimes' enforcement differs: Codex reviews sandbox escalation requests; Claude's classifier reviews tool permission requests while its Bash sandbox is separate. Auto-mode availability and decisions remain subject to runtime, model, account, and managed policy. These fields describe Muster's resolved launch settings, not a continuous attestation of remote policy or user changes. See Codex auto-review and Claude permission modes.
OpenCode permissions are tool policy, not an OS-level filesystem sandbox.
Muster's read-only OpenCode policy denies editing, shell, subagent,
external-directory, web, and MCP operations except explicitly selected MCP
tools; it does not claim kernel-enforced isolation. Auto still requires
workspace-write, and bypass still requires authorized full-access.
The concurrency cap is shared by separate CLI/MCP processes, including pending launches. Settings apply to both kinds; tasks are read-only by default.
Codex defaults to an explicit sandbox and never-ask approval policy. Muster enumerates and explicitly disables inherited MCP servers, enables only the selected operator definitions, then verifies the effective server selection. Hooks, plugins, app connectors, automatic skill-MCP installation and external notifications are disabled for the child. Unknown MCP names that cannot be addressed safely are refused.
Claude's built-in tools default to enabled. Unless full access is selected, its command sandbox is enabled,
requires availability, and forbids unsandboxed retries. File-writing tools and
sandbox writes are denied in read-only mode; default permissions use dontAsk so an
unattended child does not auto-grant escalations. User/project settings and MCP
servers are not inherited. Detected managed policy is refused because the CLI
cannot prove that inline settings override it. Enterprise remote policy can
arrive after startup; this v1 is not an enterprise policy-enforcement layer.
Claude permissions and its command sandbox are different mechanisms; neither
claim implies that every external tool is OS-sandboxed.
OpenCode keeps normal provider/model configuration and launches with --pure
unless plugins are selected, which disables inherited external plugins.
Providers declared under [opencode.provider] and a model named by
[opencode] model or --model are supplied in the same verified overlay, so a
launch does not depend on the operator's own OpenCode configuration; provider
definitions merge with any the child resolves for itself rather than replacing
them. Secrets belong in api_key_env_var, read from the launching environment,
not in config.toml. Before launch, Muster inspects the
effective OpenCode configuration, disables every inherited MCP server and tool
family, enables only the selected Muster definitions, and fails closed if a
higher-precedence managed policy prevents that isolation from being proven.
These child restrictions prevent automatically propagating spawn authority.
External tools are enabled only through the operator configuration and launch
selection described below. Codex and Claude runtime inboxes remain reachable
from an external Tin Can even when they have no MCP tools of their own. An
OpenCode session is reachable as a Tin Can peer only when the Tin Can plugin is
selected with --plugin; the plugin, not the MCP server, is what advertises the
session to other runtimes.
No user-level runtime configuration is rewritten, and workspace-trust dialogs
are never accepted automatically.
Launch intent is fsynced to ~/.muster/launches.jsonl before a runtime starts;
ready/failure outcomes follow. The log contains the full prompt, cwd,
requester, runtime, kind and host. Registry and task outputs also live under
~/.muster, with private file permissions. An abandoned registry.lock fails
closed: verify no Muster operation is running before removing that directory.
There is no automatic time-based lock theft.
Optional tools for launched agents
MCP servers are optional. Muster does not require or install Tin Can (or any
other MCP server). Register only servers you want launched agents to use in
~/.muster/config.toml. For example, to use an already-installed Tin Can:
# Optional personal defaults for sessions. Omit to keep launches MCP-free.
default_mcp = ["tincan"]
[mcp_servers.tincan]
command = "tincan"
tools = ["peers", "send_peer", "message_log"]
required = falseThen any runtime can use it:
muster run codex --mcp tincan --prompt 'Coordinate with the other agent'
muster run claude --mcp tincan --prompt 'Coordinate with the other agent'
muster run opencode --mcp tincan --permissions auto --sandbox workspace-write \
--prompt 'Coordinate'
muster run codex --no-mcp --prompt 'Work without external tools'A plugin is named either by path or by an npm specifier, never both. A path
becomes a file URL; a specifier is passed through untouched for OpenCode to
resolve and install:
[plugins.tincan]
npm = "@brutalsystems/tincan-opencode"
[plugins.local-thing]
path = "~/.config/opencode/plugin/local-thing.ts"Prefer npm where the plugin is published — but not because it avoids a stale
copy. Both routes keep one. A copied file goes stale in silence: the package
updates, the copy does not, and the old code keeps running against whatever it
was built for. A specifier keeps its copy somewhere less obvious. OpenCode
resolves the specifier once, writes a generated package.json pinning the
resolved version alongside a lockfile, and caches that under the range it was
asked for:
~/.cache/opencode/packages/@brutalsystems/tincan-opencode@latestPublishing a new version does not change that directory and nothing warns, so the stale plugin keeps running and keeps reporting. Deleting it forces re-resolution on the next launch:
rm -rf ~/.cache/opencode/packages/@brutalsystems/tincan-opencode@latestMuster passes the specifier through untouched, so pin a version where the
staleness should be deliberate and visible in config rather than implicit in a
cache. OpenCode keys a pinned specifier to its own directory, leaving the
@latest copy alone:
[plugins.tincan]
npm = "@brutalsystems/tincan-opencode@0.7.1"A specifier needs the package to declare an entry point OpenCode's loader
actually reads. It looks for exports["./server"] and falls back to main; it
does not read exports["."]. A package declaring only the latter is fetched,
its package.json is read, the session runs — and the plugin never executes,
with nothing logged. If a specifier-named plugin appears to do nothing, check
the package's entry points before looking anywhere else.
Either way, confirm what is actually loaded. muster doctor checks every
path-configured plugin against the package it came from:
muster doctor --format humantincan @brutalsystems/tincan-opencode
Status: stale — copy predates 0.7.2, published 2026-09-21
Path: /Users/you/.config/opencode/plugin/tincan.ts
1 stale plugin. Replace path with npm = "@brutalsystems/tincan-opencode" in [plugins.tincan], or re-copy the file.The copied file carries no version of its own, so the check compares its mtime against the registry's publish time for the current release. That means a file re-copied recently reads as current even when its contents are old: doctor under-reports and never cries wolf. It exits 1 when anything is stale, and an unreachable registry is reported as such rather than failing the command.
Muster knows the packages for the plugins it ships with. Name anything else,
or override the default, with published:
[plugins.mine]
path = "~/src/mine.ts"
published = "@acme/mine-opencode"Plugins named by npm are not checked: they keep no copy of their own, and
clearing OpenCode's cache above is that remedy instead. For what a running
session loaded rather than what is on disk, the records still carry the version:
grep plugin_version ~/.tincan/peers/opencode/ses_*.json
tincan --versionRegistering Muster itself is the one case to think twice about. A definition
whose command runs muster mcp gives every session that selects it run,
list, stop and output — launch authority, held by an agent rather than by
you. Put it in default_mcp and every session muster launches can launch more,
which is the propagation the child restrictions above exist to prevent;
max_concurrent caps simultaneous launches but does not stop a tree forming.
Nothing in Muster refuses this, so the restraint has to be yours. If you want
an orchestrating agent, give exactly that one session an explicit
--mcp muster and leave default_mcp alone. See "MCP installation" below for
the same stance applied to a runtime's own shared configuration.
--mcp NAME is repeatable and replaces personal defaults. --no-mcp clears
them and cannot be combined with --mcp. MCP run takes mcp: ["tincan"];
mcp: [] disables all servers. Omitted selection uses default_mcp for sessions.
Tasks have no defaults, but accept an explicit selection.
Definitions support either command plus optional args, env, and env_vars
for stdio, or url plus optional bearer_token_env_var for Streamable HTTP.
tools is a required nonempty list of exact tool names. Use env_vars and
bearer_token_env_var to reference credentials in the launch environment;
credentials are not written to launch logs. HTTP OAuth setup shared across
runtimes, plugin/app tools, MCP resources and prompts are outside this interface.
Server and tool names must contain only letters, digits, underscores or hyphens.
Relative stdio commands run from the requested working directory; prefer an
absolute executable path or a command on PATH.
Before agent launch, Muster initializes each selected server and checks its tool
catalog. No tool is called during preflight. An explicit --mcp selection is
required: a missing server, missing credential, or missing configured tool fails
that launch. Defaults are optional unless their definition sets required = true;
an unavailable optional default is skipped with mcp_warnings. Each preflight is
bounded by startup_timeout_sec (default 10, maximum 60) and the launch deadline.
JSON results and list report selected logical names in mcp; human output shows
MCP: and any warnings. These describe launch configuration, not continuous
server health.
Codex receives isolated definitions, using a fresh runtime name when an inherited
server has the same name, and its native tool allowlist. Claude receives a private
Muster stdio connection that filters both tool discovery and calls; newly added
upstream tools cannot bypass the selection. Only selected tools are preapproved.
OpenCode disables inherited definitions and tool families in its verified
per-launch overlay, then enables only selected definitions. A launch that
selects MCP servers omits the wildcard * permission entry and names the
built-in tools it denies instead: in OpenCode a * entry suppresses MCP tools
outright, and an explicit allow for the tool does not restore them. The
built-in list is fixed, so a tool added by a future OpenCode release would not
be denied by it; launches that select no MCP server keep the wildcard. With no plugins
selected it also uses --pure and pins an empty plugin list, so inherited
plugins do not enter the child process. Selecting a plugin with --plugin
necessarily relaxes that: OpenCode merges project-local plugin discovery into
any non-empty plugin list, so the child also loads whatever plugins the target
repository ships. It globs both spellings — .opencode/plugin and
.opencode/plugins — so auditing only one of them misses half of what a
repository can load. Select plugins only for repositories trusted with that.
Claude connection specifications are stored with owner-only permissions under
~/.muster/mcp, removed on stop, task completion, or when list observes an ended
session. MCP server access is separate from filesystem sandbox permissions: a
selected external tool may have its own write or network capabilities.
MCP installation
Installed deliberately, in the one session that should hold spawn authority — never at user scope.
Muster exposes run, list, stop, and output over stdio. No arguments or
mcp starts the server. Diagnostics go to stderr, never protocol stdout.
Schemas match the CLI (args is the array of optional runtime arguments).
For a single Codex session, use per-invocation configuration:
codex -c 'mcp_servers.muster.command="node"' \
-c 'mcp_servers.muster.args=["/absolute/path/to/muster/dist/muster.js","mcp"]'For a single Claude session:
claude --mcp-config '{"mcpServers":{"muster":{"command":"node","args":["/absolute/path/to/muster/dist/muster.js","mcp"]}}}'Do not add Muster to ~/.codex/config.toml, Claude's user-scope MCP registry,
or another shared configuration that grants launch authority to every agent.
The same applies to Muster's own [mcp_servers]: a definition that runs
muster mcp, selected by default_mcp, grants that authority to every session
Muster launches.
Tin Can compatibility
Muster has no Tin Can build or runtime dependency. Each tool implements the
written address contract independently. Vendored mechanics carry source-commit
headers and the original MIT license in TINCAN_LICENSE.
Addresses belong to running sessions and can expire or collide. Store
thread_id / session_id, and re-resolve through Tin Can's peers before
sending instead of caching a launch address. Canonical IDs are not unique keys.
One OpenCode behaviour is worth knowing if you deliver to a session yourself
rather than through Tin Can. A message posted to the v2
/api/session/{id}/prompt of a TUI-hosted session is admitted with a 200
and an admittedSeq, schedules a turn, and then dies with
ModelUnavailableError naming the session's own model — while the TUI resolves
that same model in the same process. A session hosted by opencode serve does
not do this, and the v1 /session/{id}/prompt_async route does not either.
Tin Can 0.6.0 delivers over v1, so nothing here depends on the v2 path.
The failure is silent from the caller's side: a success response, nothing written into the session, and the only trace a line in OpenCode's own log. The investigation, what it did and did not establish, and why it was not filed upstream are recorded in CONTRACT_PROVENANCE.md. The frozen cases intentionally preserve Tin Can's known naming defects.
Codex idle means reachable and not known to be busy, not guaranteed free.
The querying app-server can report notLoaded for a live thread; Muster maps
that to idle. Claude state comes from its session registry.
OpenCode peers expose a durable session_id and loopback-only server_url so a
future Tin Can adapter has a stable integration seam. Tin Can does not yet send
to OpenCode through Muster: choosing native OpenCode messaging versus A2A, and
updating Tin Can for that transport, are explicitly deferred follow-up work.
Verification
npm test
npm run build
npm run test:contractThe ordinary suite requires tmux, node-pty, POSIX ps/lsof, and Python 3 for
real file locks in the fake Codex executable. It uses isolated runtime homes and
no model APIs. It skips the four explicitly invoked compatibility cases.
The verified contract baseline is Tin Can 0.6.4. The suite spawns an installed binary as an MCP subprocess, compares durable IDs, and verifies delivery to fake runtimes through both terminal hosts. A missing binary or missing durable field fails the test. For reproducible verification, install that exact release outside Muster:
contract_dir=$(mktemp -d)
npm install --prefix "$contract_dir" --no-save @brutalsystems/tincan@0.6.4
MUSTER_TINCAN_BIN="$contract_dir/node_modules/.bin/tincan" npm run test:contractVerification uses the published 0.6.4 release installed in an isolated
temporary directory. No Tin Can source edits are made.
Fixture version metadata alone does not indicate address-format drift: compare
the case arrays. Those arrays cover naming only, not peer-list membership or
state semantics. Upgrades require separate compatibility verification; passing
fixture hashes alone does not establish compatibility. The tests locate the
launched peer by canonical ID and compare its durable ID; they do not assert a
total peer count, exclude same-runtime peers, or assert Tin Can's busy state.
CONTRACT_PROVENANCE.md records both types of integrity checks.
One-time live probes are separate from the automated suite. Both runtimes
launched and answered an initial prompt with the versions listed above; Claude
used a directory already trusted by its operator. npm test does not run
real models.
License and releases
MIT © 2026 Mike Williams. See LICENSE. Vendored Tin Can code retains source attribution and its MIT notice.
Publishing is tag-driven and runs in GitHub Actions over OIDC trusted
publishing, with no stored npm token. A bare git push publishes nothing; a
version tag is what triggers publish.yml. That workflow validates a RELEASE_NOTES.md section for
the version being published, so write the notes under ## Unreleased as you do
the work and commit them normally. Cutting the release is then one command:
git commit -am "<the change, including its notes under ## Unreleased>"
npm version patch -m "%s — <what changed>"npm version runs the version hook, which stamps ## Unreleased into
## <version> — <date> and stages it, then bumps, commits and tags; the
postversion hook pushes the commit and tag together. If there is no
## Unreleased section, or it is empty, the stamp refuses — before a tag
exists, rather than in CI after one has been pushed.
RELEASING.md covers versioning, package inspection, publication, and release notes in full. Changes to the shared address format require an explicit contract update; Muster never independently fixes the frozen naming behavior.
Available Tools
4 toolslistA
List Muster-owned sessions and tasks, including host capabilities.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must disclose behavioral traits. It describes the action as non-mutating ('List'), which implies a read-only operation, but it does not explicitly state there are no side effects, nor does it mention authentication requirements, pagination, or output format. 'Including host capabilities' hints at extra data, but no details are given. This is adequate for a simple list tool but not richly transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence that front-loads the primary purpose ('List Muster-owned sessions and tasks') before adding the secondary detail about host capabilities. It contains no filler or repetition, and its brevity is appropriate for a tool with only one optional parameter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (one optional enum parameter, no output schema, no annotations), the description covers the main purpose but leaves gaps: it does not explain the 'kind' parameter's effect, nor does it describe the return structure. The phrase 'including host capabilities' suggests extra output but is undefined. For a simple list tool, this is moderately complete but not fully self-sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description does not explain the 'kind' parameter at all. The schema provides an optional enum of 'session' or 'task', but with 0% schema description coverage, the description should clarify how this parameter filters results. The overview says 'sessions and tasks' but not that 'kind' selects between them. This is a meaningful gap, as the parameter's role is left entirely to inference from the schema's enum values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the operation: 'List Muster-owned sessions and tasks'. It uses a specific verb ('List') and names the resource, which distinguishes it from siblings like 'run', 'stop', and 'output'. The additional 'including host capabilities' makes the scope more specific without confusing the core purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage: the agent should call this when it needs to enumerate existing sessions/tasks. However, it does not explicitly state when to use it over alternatives (e.g., before running or stopping), nor does it describe when not to use it. There is no mention of prerequisites or routing to siblings, leaving the agent to infer the use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
outputC
Read captured output from a task run.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It only says 'Read', implying a non-mutating operation, but does not state whether the task must be finished, whether it blocks, what happens if the id is invalid, or what the output format is. The description is too sparse to convey essential behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single short sentence, which is concise, but it is under-specified. It lacks essential context that should be present given the absence of annotations and parameter descriptions. The brevity works against the agent rather than aiding it, so it is not appropriately sized for the tool's needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with one parameter, no annotations, and no output schema, the description is severely incomplete. It does not explain what the 'id' is, what 'captured output' means, how to obtain the output, or what the response will look like. An agent cannot reliably invoke this tool correctly based on the provided definition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has a single required parameter 'id' with no description, and schema coverage is 0%. The description does not explain what 'id' refers to (presumably a task run ID) or how to obtain it. The agent has no information about the parameter's meaning, format, or constraints beyond a minLength of 1.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Read' and the resource 'captured output from a task run', which distinguishes it from sibling tools like run, list, and stop. However, it is slightly vague about what 'captured output' includes (e.g., stdout, stderr, logs), so it does not fully specify the resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives such as list or run. It does not mention prerequisites like the task needing to be completed, nor does it contrast with siblings. The agent is left to infer usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
runB
Launch an instructed agent. Sessions return only when reachable; tasks return a non-messageable run handle.
| Name | Required | Description | Default |
|---|---|---|---|
| cwd | No | ||
| mcp | No | Configured MCP server names. Omit for session defaults; [] disables all. Tasks have no defaults. | |
| args | No | ||
| host | No | ||
| kind | No | session | |
| open | No | Open the tmux session in a terminal viewer (macOS only). | |
| prompt | Yes | ||
| runtime | Yes | ||
| sandbox | No | Defaults to config (read-only). Full access requires config authorization. | |
| terminal | No | Viewer app; requires open. Auto uses Terminal.app. | |
| permissions | No | Defaults to config (deny). Auto requires workspace-write; bypass requires authorized full-access. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden for behavioral disclosure. It does disclose return behavior (sessions return only when reachable, tasks return a non-messageable run handle), but it says nothing about side effects, permissions, asynchronous execution, resource consumption, or failure modes – significant gaps for a launch tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two efficient sentences: the first states the core purpose, the second adds the key behavioral distinction. No redundant words, and the most important scoping information is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 11 parameters, no annotations, and no output schema, the description is far too sparse. It covers the launch intent and one behavioral nuance, but leaves parameter semantics, usage scenarios, safety profile, and return formats nearly completely undocumented, forcing the agent to infer too much from the schema alone.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is low at 45%, and the description adds no parameter-level meaning beyond the session/task kind distinction. Required parameters like runtime and prompt are left entirely to the schema, and optional fields like cwd, args, host, and sandbox are not explained in the description, failing to compensate for the schema's incomplete coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Launch an instructed agent' – a specific verb and resource. It also distinguishes session versus task variants by their return semantics, clearly setting it apart from sibling tools list, output, and stop without needing their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use run (to launch an agent) and distinguishes when to choose session vs task, but it does not explicitly mention alternatives such as list for viewing existing runs or stop for terminating them, nor does it state any prerequisites or when not to use the tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
stopA
Stop a Muster-owned run by durable id or unambiguous peer name.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full responsibility for behavioral disclosure. It only says 'Stop,' implying a mutating action, but does not disclose whether stopping is irreversible, what happens to the run's output, permission requirements, or idempotency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. Every part contributes: the action, the resource scope, and the accepted identifier forms.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple and the description covers the action and parameter semantics, so an agent can likely invoke it correctly. However, with no annotations and no output schema, it omits behavioral consequences and does not mention how to obtain the id or name, despite the sibling list tool existing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has one required string id with no description (0% coverage). The description adds crucial meaning by explaining that id can be a durable id or an unambiguous peer name, which is not derivable from the schema. It does not define the formats, but it compensates well for the schema gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description uses a specific verb ('Stop') and names the exact resource ('Muster-owned run'), plus the identifier forms accepted. It is clearly distinct from siblings run, list, and output.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies this tool is for stopping an existing Muster-owned run and even states how to identify it, but it does not explicitly mention when not to use it or direct the agent to list for finding ids. Usage context is clear but alternatives are left implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.7.8- Changed
run4 fields changed- added
Input schema / properties / mcpAdded value: +{ + "description": "Configured MCP server names. Omit for session defaults; [] disables all. Tasks have no defaults.", + "items": { + "pattern": "^[a-zA-Z0-9_-]+$", + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / openAdded value: +{ + "description": "Open the tmux session in a terminal viewer (macOS only).", + "type": "boolean" +} - changed
Input schema / properties / runtime / enumPrevious value: -[ - "codex", - "claude" -]New value: +[ + "codex", + "claude", + "opencode" +] - added
Input schema / properties / terminalAdded value: +{ + "description": "Viewer app; requires open. Auto uses Terminal.app.", + "enum": [ + "auto", + "terminal", + "iterm2", + "ghostty" + ], + "type": "string" +}
4 tool updates
v0.3.0- First observed
list - First observed
output - First observed
run - First observed
stop
TDQS
Scored across 4 tools
Each tool maps to a distinct lifecycle action: run creates, list inspects, output retrieves results, and stop terminates. There is no meaningful overlap between any pair of tools.
All tool names are single-word lowercase commands that read as direct actions: list, output, stop, run. The style is uniform and predictable, with no mixed conventions.
Four tools is a well-scoped set for launching, inspecting, reading output from, and stopping runs. Each tool earns its place without redundancy or bloat.
The run/list/output/stop lifecycle covers tasks well, but sessions appear to be a distinct messageable concept while no send/message or session-specific interaction tool exists. This is a notable gap in the tool surface.
Maintenance
Related MCP Connectors
A paid remote MCP for OpenAI Codex agent coordination MCP, built to return verdicts, receipts, usage
Hosted MCP memory and agent control plane for durable conversations, jobs, and operations.
Scoped agent execution. Server-side credentials, policy, budgets and verifiable receipts.
MCP server for Superserve sandboxes: create, exec, and manage Firecracker microVMs
Related MCP Servers
- AlicenseAqualityDmaintenanceWraps Claude Code as tools for MCP clients, enabling autonomous coding tasks via a 4-tool lifecycle with session management, async polling, and permission controls.443 npm20MIT
- AlicenseNot gradedqualityDmaintenanceEnables MCP clients to spawn and control Codex CLI and Claude Code sessions on the host machine, with session management and filesystem access.4MIT
- FlicenseNot gradedqualityCmaintenanceEnables ISLI agents and MCP clients to dispatch natural-language coding and terminal tasks to a locally-installed Claude Code CLI, supporting both one-shot execution and persistent sessions with workspace and security controls.-
- FlicenseNot gradedqualityAmaintenanceAgent orchestration system that runs coding-agent sessions (Claude Code, Codex) with policy mediation and exposes tools via MCP.-