This page is the comprehensive reference for configuring and operating Murmur entirely from the CLI. It is designed primarily for AI agents acting on a user’s behalf — the structure, hard rules, and decision tree below let an agent provision and operate a tenant end-to-end without consulting other docs. Humans can read it too; skip the first section.Documentation Index
Fetch the complete documentation index at: https://docs.murmur.dev/llms.txt
Use this file to discover all available pages before exploring further.
For AI agents reading this page
You are likely reading this because a user asked you to set up, modify, or operate Murmur from the CLI. This page is self-contained — every command, every required field, every enum literal, and every common error is in here. Do not invent values; everything you need is documented.Operating rules
These rules supersede any pattern you may have seen elsewhere. Follow them in order.- Verify before you act. Before any state change, run
murmur version(confirms server reachability) andgh auth status(confirms GitHub identity). Read.murmur/murmur.yamlto see the active tenant + workspace. If.murmur/murmur.yamldoes not exist in the user’s repo, they have not runmurmur setup— start at Step 1 of the walkthrough. - Discover, do not guess. Before referencing a platform builtin (machine-type, disk-type, image, placement), run
murmur get <kind>to see what actually exists in this tenant. Builtin names are stable across tenants but new substrates and regions are added over time. - Names follow strict patterns.
[a-z][a-z0-9-]{0,62}for all kinds exceptsecretanduser-secret, which use[A-Z][A-Z0-9_]*. If you guess and it’s wrong, the API rejects. Lowercase with hyphens for most things; SCREAMING_SNAKE_CASE for secrets. - Enums use the full prefix form.
SUBSTRATE_GCP,SUBSTRATE_AWS,ARCHITECTURE_AMD64,ARCHITECTURE_ARM64. Never writegcporamd64alone — the API rejects. murmur setbody must includename: <same-as-positional-arg>. The body and positional argument are validated against each other.- Required-field validation is one-at-a-time. If you send a body missing required fields, the API returns the first missing one. Each retry surfaces the next. The minimum YAMLs in this doc are pre-validated to pass — start from them rather than iterating from empty.
murmur setupis interactive and opens a browser. There is no flag to pre-select tenant or workspace. If you must script it, either pipe answers on stdin (Y for token confirm, the numeric tenant index, then defaults) or use--non-interactivewhich requiresANTHROPIC_API_KEYin env (won’t work for users on Claude subscription OAuth).- Cost-aware actions need user confirmation. See the table below.
- Stop and report on terminal failures. If an action fails with
PermissionDenied,FailedPrecondition, orUnauthenticated, report the exact error to the user and ask before retrying. Do not loop.
Action risk reference
| You may run without confirming | Confirm with user first | Never do without explicit ask |
|---|---|---|
murmur version, murmur get *, murmur describe *, murmur status, murmur ls, murmur pool status, murmur check-permissions, murmur watch, murmur session watch, murmur task ls/get, murmur subscriptions ls | murmur spawn (each agent is 25), murmur set workspace with min_idle > 0 (warm VMs are billable), murmur bake (5–30 min VM build), murmur secret set (write-only, you cannot read it back to verify), murmur each (fans out, multiplies cost), batch operations | murmur rm (irreversible; cascades blocked by ref integrity), murmur kill -A style mass kills, murmur pool flush (drops warm VMs), murmur secret rm, murmur queue clear, anything with --force-new |
Decision tree — which section do you need?
| The user asked you to… | Read |
|---|---|
| ”Set up Murmur in this repo” | A well-set-up workspace, top to bottom |
| ”Spawn an agent that does X” | murmur spawn |
| ”Why is my agent stuck / failing?” | murmur status, then Common errors |
| ”Create / modify a workspace, environment, recipe, persona, flight” | Catalog resource reference |
| ”Add a secret” / “give workspace X access to secret Y” | secret, workspace.secret_refs, Secret hygiene |
| ”Make agent startup faster” | Pool sizing |
| ”Why does the CLI reject my YAML?” | Common errors |
| ”What model should I use?” | Model selection |
| ”Bake a custom image with Go / Python / Node / etc.” | Step 4 of the walkthrough, recipe |
| ”Set up CI / scheduled / event-driven agents” | flight, then Flights guide |
| ”Give Bob workspace-admin access” | role + group + tenant-binding |
| ”Audit who can do what” | murmur check-permissions |
Vocabulary you must use precisely
- Tenant — a GitHub org or personal account registered in Murmur. Identified as
github_app/<org>orgithub_oauth/<user>. - Workspace — a launchable preset composing image + environment + placement + repos + secrets. Every
murmur spawntargets one. - Environment — pure compute shape (machine type + disk + disk size). Placement-agnostic.
- Placement — where VMs physically run (cloud + region + project + network).
- Recipe — a shell script that builds a custom image via
murmur bake. - Image — a runnable VM/container artifact, either a platform builtin or a bake output.
- Agent — a spawned task. Has a slug, a VM, a phase, a session, a cost, and (usually) opens a PR.
- Persona — a reusable bundle of system prompt + model + tool policy + default tasks.
- Flight — a Markdown-defined orchestration plan with optional event triggers.
- Pool — the set of warm VMs awaiting spawn requests. Sized tenant-wide by
pool-config.max_vmsand per-workspace byworkspace.min_idle.
When the user says “just set it up for me”
- Identify the GitHub org of the repo (
gh api repos/:owner/:repo --jq .owner.login). - Run
murmur setupfrom inside the repo. - Pick the most appropriate tenant from the setup prompt (matches the repo org).
- Confirm the workspace name choice with the user once (default to the repo name).
- Run the walkthrough steps 2–7. Use platform builtins for image/environment/placement unless the user has stated a specific toolchain need.
- Verify by spawning a small hello-world agent and reporting the resulting PR URL.
What this page does not cover
- The gRPC wire protocol — see API Reference.
- Detailed dashboard usage — see Dashboard.
- Customer placements (running VMs in your own cloud account) — see Customer Placements.
- Flight DSL semantics (event matchers, scheduling syntax) — see Flights.
For humans: how to use this page
- Setting up a new tenant from zero: read Mental model, then follow A well-set-up workspace top to bottom.
- Looking up a specific command or flag: jump to CLI command reference.
- Looking up a specific resource shape: jump to Catalog resource reference.
- Diagnosing an error: jump to Common errors and validation.
- Making a workspace better, not just functional: jump to Best practices.
Mental model
Murmur is a control plane for autonomous coding agents. To use it, you provision a small set of catalog resources, then ask the CLI to spawn agents against them. The layers, from top to bottom:- A
workspaceis the unit of “what an agent runs on.” Everymurmur spawntargets a workspace. A workspace composes an image, environment, placement, and one or morerepos. - The catalog enforces referential integrity. You cannot delete an
environmentreferenced by a workspace, animagereferenced by an environment, etc. - Every resource has a name matching
[a-z][a-z0-9-]{0,62}(lowercase, starts with a letter, hyphens allowed, max 63 chars). Secrets are the exception — secret names match[A-Z][A-Z0-9_]*because they become env var names on VMs. - Enums use the full prefix form in YAML:
SUBSTRATE_GCP,SUBSTRATE_AWS,ARCHITECTURE_AMD64,ARCHITECTURE_ARM64.
A well-set-up workspace
This walkthrough produces a workspace that is not just valid — it is configured the way Murmur teams configure them in practice. Annotated choices explain why each field has the value it does, so you can adapt rather than copy. The example provisions a small Go service. Adapt machine sizes, regions, and language runtimes to your stack.1. Configure the developer profile
From inside any repo:.murmur/murmur.yaml (commit) and .murmur/murmur.local.yaml (gitignored, KMS-encrypted).
Verify connectivity:
2. Set the pool ceiling
max_vms: 50 is a sensible early ceiling — high enough that you almost never queue, low enough that a runaway flight cannot bankrupt you. reap_stranded_agents: enabled auto-cleans orphaned agents whose VMs vanished (vs the default dry_run which only logs). Move to enabled once you have observed dry_run for a few days and trust the reaper.
3. Load tenant secrets
Anything you do not want hard-coded in repos goes here. Secrets surface asMURMUR_SECRET_{NAME} env vars on every agent VM.
SCREAMING_SNAKE_CASE. The MURMUR_SECRET_ prefix is added by the platform — if you need a runtime env var named DATABASE_URL, create the secret as DATABASE_URL and reference it as $MURMUR_SECRET_DATABASE_URL (or symlink with an .envrc).
Rotation: Secrets are write-only. To rotate, murmur secret set again with the new value. The previous value becomes unreadable.
4. (Optional) Bake a custom image with your toolchain
Skip this if your repo’s bootstrap script can install everything you need at agent boot. Bake when the install is expensive enough to be worth pre-doing once. The platform shipsmurmur-debian12-gce and murmur-debian12-aws with git, jq, curl, GitHub CLI, Claude Code, Codex CLI, yq, and a hardened murmur user. Language runtimes (Go, Python, Node, Ruby, Rust) are not included on purpose — they go in your recipe.
murmur bake creates an image resource named like go-stack@<hash>. Reference it from a workspace via image_ref: go-stack@<hash> or pin to the latest via image_ref: go-stack (the platform resolves to the most recent successful bake).
Provisioning script rules of thumb: pin every version explicitly, set -euo pipefail always, use apt-get non-interactively, gate slow steps behind if, and end with wait to flush background processes. unset GH_TOKEN at the end if you used it.
5. Define a compute environment
Theenvironment resource is pure compute shape — placement-agnostic.
murmur-n2-standard-4 (4 vCPU / 16 GB). If your build is dominated by linking large binaries, c3-standard-44 is the right escape valve. If your tests are I/O-bound and not parallel, smaller is fine. The disk is fast (pd-balanced is 240 IOPS/GB up to 80k); 100 GB is enough headroom for a Go monorepo with a Docker layer cache.
6. Create the workspace
The workspace is whatmurmur spawn targets. It composes everything above plus the repo list.
min_idle: 2 keeps two warm VMs ready so the first spawn of the day is ~5 seconds, not ~90. Increase to 5–10 when active developer count > 5; keep at 0–1 for solo or low-volume workspaces.
secret_refs decides what the workspace sees. The full secret list lives at tenant scope; only the names you list here become env vars on VMs spawned in this workspace. Principle of least privilege: a marketing-site workspace should not have access to DATABASE_URL.
ports declares which TCP ports the dashboard and murmur url should know about. The platform tunnels these through the port-proxy with subdomain routing. Without an entry here, the port is reachable via murmur port-forward but not via a stable URL.
7. Pin the workspace in your repo’s config
model field becomes the default for every murmur spawn from this repo. Override per-spawn with --model.
8. (Optional) Author reusable personas and flights
Personas factor out system-prompt + model + tool-policy bundles you want to reuse:9. Spawn
CLI command reference
Every command Murmur exposes. Flags are listed in the order they appear in--help. Examples are deliberately small and copy-pasteable.
Setup & authentication
murmur setup
Gathers your credentials (GitHub token, Claude OAuth or API key, SSH signing key), encrypts them, and writes the per-developer profile to .murmur/murmur.local.yaml. Run once per repo.
| Flag | Type | Description |
|---|---|---|
--out | string | Output path. Default .murmur/murmur.local.yaml. Use - for stdout. |
--non-interactive | bool | Skip OAuth flow and prompts; reads GH_TOKEN, ANTHROPIC_API_KEY, OPENAI_API_KEY from env. |
--skip-ssh-keys | bool | Skip SSH signing key generation. Useful in CI. |
--commit-signing | bool | Upload the SSH signing key to GitHub so VM commits show as Verified. |
--upload | bool | Upload the encrypted profile to the platform (required when --non-interactive). |
gh token → prompts for tenant → prompts for workspace (if tenant has any) → Claude OAuth or API key → SSH key generation → writes both YAMLs.
Programmatic gotcha: there is currently no flag to pre-answer the tenant or workspace prompts. To script setup, either expect-feed numeric answers on stdin or run --non-interactive with ANTHROPIC_API_KEY set.
murmur auth
Run the Claude OAuth flow standalone. Useful when only the Claude token needs refreshing.
murmur version
murmur check-permissions
Evaluate permissions against the caller’s effective grants. Useful when debugging “permission denied” errors.
allowed or denied with the matching grant (if any).
Spawn
murmur spawn
Create an agent task, claim a VM from the pool, and start a session.
<slug> is the agent’s identifier within the workspace. Must match [a-z][a-z0-9-]{0,62}. The Git branch is murmur/w/<workspace>/u/<account>/<slug> (or .../s/... for service agents).
Core flags
| Flag | Type | Description |
|---|---|---|
--workspace -w | string | Workspace override. Defaults to .murmur/murmur.yaml. |
--purpose | string | Human-readable goal (max 240 chars). Shown in the dashboard sidebar. |
--agent | string | Persona name (loads agent-persona from catalog). |
--model | string | Model override (e.g. claude-opus-4-6, claude-sonnet-4-6, gpt-5-4). Implies backend. |
--backend | string | Backend override: claude or codex. Auto-detected from model. |
--out | string | Expected output: pr, push, respond, or freeform text. |
--append-system-prompt | string | Appended to the agent’s system prompt. |
Session mode flags
| Flag | Description |
|---|---|
-i | Interactive — Claude runs in tmux. Attach with murmur ssh --attach <slug>. |
--stream | Streaming backend — long-lived bidirectional channel. |
Lifecycle flags
| Flag | Type | Description |
|---|---|---|
--on-idle | enum | sleep (default), terminate, terminate-when-prs-resolved, keep-alive. |
--pilot | bool | Mark as a pilot task — runs a completion assessor loop before allowing idle. |
--wait | bool | Block until the task reaches a terminal phase before returning. |
--dequeue-strategy | enum | all (default), one, five — how queued follow-ups are delivered. |
Repo & task flags
| Flag | Description |
|---|---|
--repo | Repo to clone. Repeatable. Format: URL, URL=base, or URL=base:working. |
--task | Pre-populate the agent’s task checklist. Repeatable. |
--input key=value | Flight input variable (only with --flight). Repeatable. |
-e VAR / -e VAR=val | Forward an env var. Repeatable. |
Resurrection & forking
| Flag | Description |
|---|---|
--resurrect | Resume a completed/failed/killed agent with full conversation history. |
--force-new | Start fresh even if a prior session exists for this slug. |
--fork-from <slug> | Branch off another agent’s session into a new independent agent. |
--flight <path> | Execute the flight at .murmur/flights/<path> via a pilot agent. |
Examples
murmur each
Fan out: spawn one agent per line of stdin. Both the slug and description are templates with {} replacement.
| Flag | Description |
|---|---|
-d | Input delimiter. Default \n. Use \0 for null-delimited (paired with find -print0). |
--dry-run | Print the planned slug/description pairs without spawning. |
--agent, --model, --backend, --repo, --workspace | Same as spawn. |
Agent lifecycle
murmur status
Query an agent’s state — phase, VM, progress, cost, opened PRs, and (optionally) timeline events.
| Flag | Description |
|---|---|
--children | Include child-agent statuses recursively. |
--timeline | Include the full lifecycle event timeline. |
--service | Query a service (flight) workflow instead of a developer workflow. |
--workspace -w | Workspace override. |
PHASE_STARTING, PHASE_RUNNING, PHASE_CHECKS_PENDING, PHASE_SLEEPING, PHASE_TASK_COMPLETE, PHASE_FAILED, PHASE_KILLED.
murmur ls
List agents in the current workspace.
| Flag | Description |
|---|---|
-a | Include completed and failed agents (default hides them). |
-A | Include all developers’ agents (default scoped to caller). |
--developer <name> | Scope to a specific developer. |
--json | JSON array output. |
-q | Quiet — slugs only, one per line. Composable with xargs. |
--workspace -w | Workspace override. |
murmur kill
Cancel a running agent.
| Flag | Description |
|---|---|
--service | Kill a service (flight) workflow instead of a developer workflow. |
--workspace -w | Workspace override. |
murmur watch
Stream the local event log for an agent. Each event is one line.
| Flag | Description |
|---|---|
--from <stream-id> | Resume from a Redis stream ID. Default 0 (from start). |
--json | Raw JSON, one event per line. Useful for jq pipelines. |
--workspace -w | Workspace override. |
murmur notify
Publish an event to the agent’s Pub/Sub topic. Useful for nudging an agent or simulating external events in tests.
| Flag | Description |
|---|---|
--workspace -w | Workspace override. |
Session interaction
murmur session watch
Stream live session events from a running agent. On the VM you can omit [slug] to attach to self.
murmur session send
Send a follow-up message to an active agent. The message is delivered to Claude’s input stream.
murmur session interrupt
Interrupt the agent’s current turn (graceful — Claude finishes its current tool call, then stops).
murmur session stop
Request a graceful session shutdown. Persists session state for later --resurrect.
Queue (follow-ups)
murmur queue add
Append a follow-up message to the agent’s queue. Delivered according to the dequeue strategy.
| Flag | Description |
|---|---|
--agent | Persona override (e.g. programmer, architect). |
--task | Add a checklist item alongside the message. Repeatable. |
--workspace -w | Workspace override. |
murmur queue clear
Discard all queued follow-ups without delivering them.
murmur queue strategy
Change the dequeue strategy for an agent.
all(default) — drain all queued follow-ups into one batch.one— drain one follow-up per turn.five— drain up to five per turn.
murmur queue conflict-resolution
Set how the agent handles git merge conflicts during rebase. Per-repo — the second positional arg is the repo display name.
murmur queue conflict-resolution fix-bug acme/api rebase.
Task checklists
Every agent has a task checklist that survives across turns. Tasks support dependencies and activation conditions.murmur task create
| Flag | Description |
|---|---|
-d | Longer description body. |
--activate-when | Activation condition (e.g. files_modified). |
--pattern | Glob pattern for activation (e.g. *.go, **/*_test.go). |
--workspace -w | Workspace override. |
murmur task update
| Flag | Description |
|---|---|
--subject | New subject. |
-d | New description. |
-s | New status: pending, in_progress, completed, deleted. |
--blocked-by | Comma-separated task IDs that must complete first (appended). |
--blocks | Comma-separated task IDs this task blocks (appended). |
--workspace -w | Workspace override. |
murmur task ls
| Flag | Description |
|---|---|
--active | Only show tasks whose activation conditions are currently met (those that block exit). |
--json | JSON array output. |
--workspace -w | Workspace override. |
murmur task get
Catalog operations
The catalog is the typed, versioned registry that backs every Murmur resource. All resources are managed through the same five verbs.murmur describe
murmur get
murmur set
Full replace. Reads YAML (or Markdown for agent-persona/flight) from stdin. All required fields must be present in the body — fields not included are reset to defaults.
murmur patch
Partial update. Other fields are preserved.
murmur rm
Delete a resource. Blocked by referential integrity — the error message lists what holds the reference.
murmur bake and murmur bakes ls
Bake produces a new image from a recipe by running the recipe’s provisioning script on a VM derived from the base image, then snapshotting.
bake flag | Description |
|---|---|
-e VAR / -e VAR=val | Forward an env var to the bake VM. Repeatable. |
--service-profile <name> | Run the bake under a named service profile (github_app tenants only). |
Secrets (shortcut commands)
murmur secret is a convenience wrapper over murmur set secret. The catalog-level commands work too.
murmur secret set
murmur secret ls
murmur secret rm
murmur set user-secret ..., murmur get user-secret, murmur rm user-secret ....
Pool management
The platform maintains a warm VM pool for fast agent startup.murmur pool status
pool-config default plus per-workspace min_idle).
murmur pool up
murmur pool flush
murmur pool reconcile-visibility
Connectivity
murmur ssh
SSH into an agent’s VM through an IAP tunnel. No public IPs are exposed.
murmur port-forward
Tunnel a local port to the agent’s VM through the port-proxy.
| Flag | Description |
|---|---|
--insecure | Allow connecting to the port-proxy without TLS. |
--workspace -w | Workspace override. |
murmur url
Print URLs for VM ports or the agent dashboard.
Subscriptions
Subscribe an agent to GitHub branch/file events so it gets notified when relevant changes land.murmur subscriptions add
--branch or --file is required.
murmur subscriptions remove
murmur subscriptions flush
murmur subscriptions ls
Other
murmur mcp
Run as a stdio MCP server exposing agent tools over JSON-RPC 2.0. Used by Claude Code when it talks to Murmur.
| Flag | Description |
|---|---|
--debug | Log all JSON-RPC traffic to ~/.murmur/mcp.log. |
--workspace -w | Workspace override. |
claude mcp add murmur murmur mcp registers it once and Claude Code launches it on demand.
murmur upload
Upload one or more files to GCS and print public URLs. Useful for handing artifacts to agents or sharing dashboard screenshots.
Global flags
These flags work on every command:| Flag | Description |
|---|---|
--workspace -w | Override workspace from murmur.yaml. |
--config | Path to a specific config file (skips walk-up discovery). |
--context | Named context (equivalent to MURMUR_CONTEXT env var). |
--verbose -v | Verbose output for debugging. |
MURMUR_CONTEXT=staging resolves murmur.staging.yaml + murmur.staging.local.yaml. Use for separating prod and non-prod credentials in the same repo.
Catalog resource reference
All 20 catalog kinds. Each entry lists: purpose, permissions required, minimum YAML that passes validation, full field reference, and the CLI commands you would actually use.Universal validation rules
| Rule | Detail |
|---|---|
| Names | [a-z][a-z0-9-]{0,62} for everything except secret/user-secret, which use [A-Z][A-Z0-9_]*. |
substrate enum | SUBSTRATE_GCP or SUBSTRATE_AWS. Full prefix required. |
architecture enum | ARCHITECTURE_AMD64 or ARCHITECTURE_ARM64. |
| Required-field validation | Errors are returned one at a time — fields are checked left-to-right. Iterate until the body passes. |
| Referential integrity | A resource cannot be deleted while another references it. The error names the holder. |
| Generation numbers | murmur describe shows the current generation, author, and updated_at. |
| Platform builtins | Resources with platform: true are immutable from your tenant. |
pool-config
Purpose: Tenant-wide VM pool limits. Singleton — exactly one record per tenant, always nameddefault.
Permissions: pool-config.read, pool-config.edit
Minimum YAML
Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes (must be default) | — | Singleton name. |
max_vms | integer | No | platform-dependent | Maximum total VMs across the tenant. |
reap_stranded_agents | enum | No | dry_run | enabled, dry_run, disabled. |
CLI
Per-workspace warm-pool sizing is on workspace.min_idle, not here.
user
Purpose: User identity record. Created automatically bymurmur setup.
Permissions: user.read, user.edit
Minimum YAML
Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Username (GitHub login). |
git_name | string | No | Git commit author name. |
git_email | string | No | Git commit author email. |
ssh_public_keys | array | No | SSH public keys for VM access. |
CLI
group
Purpose: Named principal set for authorization grants. Bound to roles viatenant-binding.
Permissions: group.read, group.list, group.create, group.edit, group.delete
Minimum YAML
The source kind is a proto oneof at the top level — set exactly one ofstatic, github_admin, or all_tenant_members.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Group identifier. |
static | object | One of these three | {members: [<username>, ...]}. |
github_admin | object | One of these three | {} — membership equals GitHub org admins. |
all_tenant_members | object | One of these three | {} — every user in the tenant. |
description | string | No | Human-readable description. |
CLI
role
Purpose: Named permission bundle. Granted to principals viatenant-binding.
Permissions: role.read, role.list, role.create, role.edit, role.delete
Minimum YAML
Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Role identifier. |
permissions | array of strings | Yes (non-empty) | {kind}.{verb} strings. Verbs: read, list, create, edit, delete. |
description | string | No | Human-readable description. |
CLI
tenant-binding
Purpose: Tenant-wide authorization grant. Binds a principal to a role. Permissions:tenant-binding.read, tenant-binding.create, tenant-binding.delete
Minimum YAML
grant.users and grant.groups are arrays; grant.role is the role to grant. At least one of users or groups must be non-empty, and the referenced role must already exist.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Binding identifier. |
grant.users | array of strings | One of these two | Usernames to grant the role to. |
grant.groups | array of strings | One of these two | Group names to grant the role to. |
grant.role | string | Yes | Role to grant. Must already exist as a role resource. |
CLI
service-profile
Purpose: Identity for non-human agents (CI bots, scheduled flights). Has its own credentials and grants. Permissions:service-profile.read, service-profile.list, service-profile.create, service-profile.edit, service-profile.delete
Minimum YAML
Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Profile identifier. |
description | string | No | What the profile is used for. |
grants | array | No | Inline permission grants. Prefer tenant-binding. |
CLI
secret
Purpose: Tenant-wide secret. KMS-encrypted. Injected asMURMUR_SECRET_{NAME} on agent VMs.
Permissions: secret.read (metadata only), secret.create, secret.delete
Minimum YAML
Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Matches [A-Z][A-Z0-9_]*. |
plaintext_value | string | Yes (on create/replace) | Write-only — never returned by get. |
CLI
secret_refs: [NPM_TOKEN].
user-secret
Purpose: Per-developer secret. Same shape assecret, but encrypted with the owning user’s identity in the AAD.
Permissions: user-secret.read, user-secret.create, user-secret.delete
Minimum YAML
CLI
machine-type
Purpose: Sanctioned VM shape: vCPUs, memory, architecture, per-region pricing.Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Machine-type identifier. |
vcpus | number | Yes (positive) | Virtual CPU count. |
memory_gb | number | Yes | Memory in gigabytes. |
architecture | enum | No | ARCHITECTURE_AMD64 or ARCHITECTURE_ARM64. |
gce | object | No | {machine_type, regions: {<region>: {cost_per_hour}}}. |
aws | object | No | {instance_type, regions: {<region>: {cost_per_hour}}}. |
platform | boolean | No | true if platform builtin. |
description | string | No | Human-readable description. |
Platform builtins (typical)
murmur-n2-standard-2, -4, -8, -16, -32; murmur-c3-standard-44; murmur-m5-large, -xlarge, -2xlarge, -4xlarge, -8xlarge; murmur-c5-9xlarge.
CLI
disk-type
Purpose: Sanctioned persistent disk type with per-region storage pricing.Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Disk-type identifier. |
substrate | enum | Yes | SUBSTRATE_GCP or SUBSTRATE_AWS. |
gcp | object | When GCP | {disk_type, regions: {<region>: {cost_per_gib_month}}}. |
aws | object | When AWS | {volume_type, regions: {<region>: {cost_per_gib_month}}}. |
platform | boolean | No | true if platform builtin. |
description | string | No | Human-readable description. |
Platform builtins (typical)
GCP:murmur-pd-balanced, murmur-pd-ssd, murmur-pd-standard. AWS: murmur-gp3, murmur-io2.
CLI
image
Purpose: Substrate-bound runnable artifact — AWS AMI, GCE image, or Docker container. Produced bymurmur bake.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Image identifier. |
architecture | enum | Yes | ARCHITECTURE_AMD64 or ARCHITECTURE_ARM64. |
source | object | Yes (one of) | {gce: {self_link}}, {aws: {ami_id, region}}, or {docker: {repository, tag}}. |
preinstalled | string | No | Multi-line description of pre-installed tooling. |
description | string | No | Human-readable description. |
Platform builtins
murmur-debian12-gce, murmur-debian12-aws. Both ship with git, jq, curl, GitHub CLI, Claude Code, Codex CLI, yq, and a hardened murmur user. Language runtimes (Go, Python, Node, Ruby, Rust) are intentionally not included — add them via a recipe.
CLI
placement
Purpose: Where VMs run — cloud provider, project, region/zone, network, and credentials.Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Placement identifier. |
substrate | enum | Yes | SUBSTRATE_GCP or SUBSTRATE_AWS. |
platform | boolean | No | true if platform-managed. Customer placements set this false. |
gcp | object | When GCP | {project, network_project, subnet, zones[], wif_provider_resource_name, wif_service_account, wif_readonly_service_account}. |
aws | object | When AWS | {account_id, region, subnet, security_groups[], instance_profile}. |
service_account | string | No | Service account VMs run as. |
description | string | No | Human-readable description. |
Platform builtins
GCP:murmur-gcp-us-central1, murmur-gcp-us-east1, murmur-gcp-us-west1. AWS: murmur-aws-us-east-1, murmur-aws-us-west-2.
For running agents in your own cloud account, see Customer Placements.
CLI
recipe
Purpose: Image build script. References a base image per substrate, runs a shell script duringmurmur bake to install your toolchain, produces an image.
Permissions: recipe.read, recipe.create, recipe.edit, recipe.delete
Minimum YAML
At least one ofbase_image_gce_ref or base_image_aws_ref is required. provisioning_timeout is required.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Recipe identifier. |
base_image_gce_ref | string | One of these two | GCE base image. |
base_image_aws_ref | string | One of these two | AWS base AMI. |
provisioning_timeout | duration | Yes | Max build duration (Go duration: 30m, 1h, 90m). |
provisioning_script | string | No | Shell script run during bake. Has GH_TOKEN and secret_allowlist secrets in env. |
secret_allowlist | array | No | Names of secret resources the script may read. |
CLI
environment
Purpose: Pure compute shape — substrate + machine type + disk type + disk size. Placement-agnostic. Permissions:environment.read, environment.create, environment.edit, environment.delete
Minimum YAML
Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Environment identifier. |
substrate | enum | Yes | SUBSTRATE_GCP or SUBSTRATE_AWS. |
machine_type_ref | string | Yes | Reference to a machine-type. |
disk_type_ref | string | Yes | Reference to a disk-type. |
disk_size_gb | integer | Yes | Boot disk size in GB. |
description | string | No | Human-readable description. |
CLI
repo-config
Purpose: Per-repository overrides for merge behavior. Applied to repos whoseclone_url matches.
Permissions: Admin-only.
Minimum YAML
The resource name is the clone URL — the positional argument tomurmur set is the URL, and the body has the same URL in clone_url.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
clone_url | string | Yes | Git clone URL. Also used as the resource name. |
conflict_resolution | enum | No (default rebase) | rebase or merge. |
base_branch | string | No | Default base branch. Overrides the repo’s default. |
CLI
workspace
Purpose: Launchable preset — composes image, environment, placement, secrets, and repos. Everymurmur spawn targets a workspace.
Permissions: workspace.read, workspace.list, workspace.create, workspace.edit, workspace.delete
Minimum YAML
set returns {field} is required until each is present.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Workspace identifier. |
image_ref | string | Yes | Reference to an image. |
environment_ref | string | Yes | Reference to an environment. |
placement | string | Yes | Reference to a placement. |
repos[] | array | Yes (at least one) | Repositories to clone. |
repos[].clone_url | string | Yes | Git clone URL. |
repos[].base_branch | string | Yes | Default branch. |
min_idle | integer | No (default 0) | Minimum warm VMs to keep for this workspace. |
secret_refs | array | No | Names of secret resources to inject as env vars. |
ports[] | array of {label, port} | No | TCP ports for port-proxy routing. |
description | string | No | Human-readable description. |
CLI
alias
Purpose: Port-proxy alias binding a friendly name to an agent’s port for subdomain routing. Permissions:alias.read, alias.create, alias.delete
Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Alias identifier (used as subdomain prefix). |
agent_id | object | Yes | Identifies the target agent. Encoded as a proto message — see note below. |
port | integer | Yes | Port the alias forwards to. |
agent_id is a structured proto message with required account and agent fields. The exact YAML/JSON encoding accepted by murmur set alias depends on the proto-to-YAML codec; if your {account, agent} block returns proto: syntax error, copy the shape from an existing alias via murmur get alias <name> and adapt.
CLI
agent
Purpose: Runtime record created when an agent is spawned. Read-only — managed by the orchestrator. Listed here for completeness.Fields (read via murmur get)
| Field | Type | Description |
|---|---|---|
name | string | Slug. |
agent_id | string | Unique agent identifier. |
grants | array | Effective permission grants. |
created_at | timestamp | Spawn time. |
terminated_at | timestamp | Termination time, if terminated. |
session_url | string | Live session view URL. |
purpose | string | Human-readable goal. |
service_profile | string | If a service agent, its profile. |
CLI
agent-persona
Purpose: Reusable agent configuration — system prompt, model, tool policy, default tasks. Referenced frommurmur spawn --agent or from flight.persona.
Input format: Markdown with YAML front-matter.
Permissions: agent-persona.read, agent-persona.create, agent-persona.edit, agent-persona.delete
Minimum input
Front-matter fields
| Field | Type | Required | Description |
|---|---|---|---|
description | string | No | Catalog summary. |
model | string | No | Model override (opus, sonnet, haiku, or full claude-* ID). |
tools | array | No | Allowlist of tool names. Empty = all tools. |
disallowed_tools | array | No | Denylist (overrides tools). |
max_turns | integer | No | Maximum turns before the agent stops. |
tasks | array | No | Default task checklist (string items). |
CLI
flight
Purpose: Multi-agent orchestration plan with triggers (events, schedules) and a default workspace. Stored as Markdown with YAML front-matter. Input format: Markdown with YAML front-matter. Permissions:flight.read, flight.create, flight.edit, flight.delete
Minimum input
Front-matter fields
| Field | Type | Required | Description |
|---|---|---|---|
workspace | string | Yes | Default workspace for spawned agents. |
daemon | boolean | No (default false) | If true, runs continuously, consuming events. |
paused | boolean | No (default false) | If true, triggers are disabled. |
on | object | No | Event triggers. Keys are event types (pr_opened, pr_labeled, pr_synchronize, push, schedule); values are filter blocks. |
persona | string | No | Reference to an agent-persona. |
model | string | No | Model override for the pilot. |
service_profile | string | No | Identity the flight runs as. |
max_concurrent | integer | No | Maximum simultaneous runs. |
dequeue_strategy | enum | No | For daemons: all, one, five. |
expected_output | enum | No | pr, push, respond. |
CLI
spawn:
Best practices
Workspace design
| Pattern | Use when |
|---|---|
| One workspace per repo | Most common. Keeps secret scopes narrow and lets each repo pick its own image. |
| One workspace per service | Monorepo with services that need different toolchains. Use --repo overrides on spawn to swap subsets. |
| One workspace per substrate × region | Multi-region resilience. Pair with placement-aware flight routing. |
- A single “shared” workspace that owns every repo. Secrets leak across teams, and image bakes get bloated trying to satisfy everyone.
- A separate workspace per developer. Personas + user secrets give per-developer isolation without the catalog overhead.
- Naming workspaces after people or dates (
alice-staging-2024). Workspaces outlive their original purposes; pick a name describing what runs there.
Model selection
| Model | Use case |
|---|---|
claude-opus-4-7[1m] (latest) | Architecture decisions, deep refactors, gnarly debugging, design-doc generation. Slowest, most expensive, most capable. |
claude-sonnet-4-6 | Default for most coding tasks. Fast, accurate, cheap enough for parallel fanout. |
claude-haiku-4-5-20251001 | Tight loops where latency matters more than reasoning depth (e.g. PR triage labelers). |
gpt-5-4 (via Codex backend) | When the codebase is dominated by Python ML or you want Codex’s tool-call style. |
.murmur/murmur.yaml’s model: field. Per-spawn override with --model. Per-persona override in the persona’s front-matter.
Pool sizing
| Setting | Effect |
|---|---|
pool-config.max_vms | Tenant ceiling. Keep loose enough that you almost never queue. Tight enough that a runaway flight cannot run away. |
workspace.min_idle | Per-workspace warm count. Sets the floor of how fast first-of-the-day spawns are. |
pool-config.reap_stranded_agents: enabled | Auto-clean orphans whose VMs vanished. Start in dry_run, promote to enabled once stable. |
workspace.min_idle should be roughly the count of simultaneous spawns you do during a normal work hour. If you spawn 4 agents at once at 9am, min_idle: 4 makes that batch start instantly. The pool refills behind you.
Secret hygiene
- Tenant-scope by default, user-scope when truly personal.
secretis the common case. Useuser-secretonly when a value must never be shared with the rest of the team. - Reference, do not inline.
workspace.secret_refschooses what each workspace can see. Defaulting to “every workspace sees every secret” is a footgun. - Allowlist for bakes separately. Recipes get their own
secret_allowlist. A secret needed by the build script does not automatically reach runtime agents. - Rotate by setting again. Secrets are write-only; rotation is a
secret setwith the new value. Old values become unreadable. - Audit access via
check-permissions. Before sharing a workspace with someone new,murmur check-permissions secret.read --resource secret/PRODUCTION_DBfrom their context.
Naming conventions
| Resource | Recommended pattern | Why |
|---|---|---|
workspace | <repo-name> or <service-name> | One workspace per repo or service. Matches what an agent thinks “where am I” means. |
environment | <workload>-<size> (e.g. go-medium, frontend-small) | Workload + size = obvious sizing intent. |
recipe | <workload>-stack (e.g. go-stack, python-ml-stack) | Stack-flavored toolchains. |
agent-persona | role/expertise (e.g. reviewer, architect, security-auditor) | Reads as a job title. |
flight | verb-noun (e.g. pr-review, nightly-tests, bug-triage) | Reads as what happens when it fires. |
secret | SCREAMING_SNAKE_CASE | Matches the env-var convention. |
tenant-binding | <group>-<role> (e.g. backend-team-workspace-admin) | Self-documenting binding. |
Permission model
The shape of every permission is{kind}.{verb} where verbs are read, list, create, edit, delete. Plus a few kind-specific verbs (agent.kill, secret.access, etc.).
Recommended starter roles for a small team:
tenant-binding.
Observability
| Signal | Where | ||
|---|---|---|---|
| Per-agent cost, phase, PRs | murmur status <slug> or the dashboard. | ||
| Pool utilization | murmur pool status. | ||
| Tenant-wide spend trend | `murmur ls -A -a —json | jq ’.[] | .cost’` aggregated. |
| Audit log of catalog changes | murmur describe <kind> <name> shows generation, author, updated_at for each resource. | ||
| Live event stream | murmur watch <slug> for one agent; pair with --json and jq for filtering. |
Common errors and validation
| Error | Cause | Fix |
|---|---|---|
rpc error: code = InvalidArgument desc = name is required | Body missing name: field. | Add name: <same-as-positional-arg> to the YAML body. |
rpc error: code = InvalidArgument desc = name must match [a-z][a-z0-9-]{0,62} | Name violates the lowercase-letter-start rule. | Rename. Underscores and uppercase letters are not allowed (except for secrets). |
rpc error: code = InvalidArgument desc = secret name "" must match [A-Z][A-Z0-9_]* | Secret name not in screaming snake case. | Rename to SCREAMING_SNAKE_CASE. |
rpc error: code = InvalidArgument desc = ref name "X" does not match payload name "Y" | Positional arg and body name: disagree. | Make them match. |
rpc error: code = InvalidArgument desc = substrate is required | substrate: field missing or unrecognized value. | Use SUBSTRATE_GCP or SUBSTRATE_AWS exactly. |
rpc error: code = InvalidArgument desc = at least one repo is required | Workspace body has repos: empty or absent. | Add at least one {clone_url, base_branch} entry. |
rpc error: code = InvalidArgument desc = repo base_branch is required | A repo entry omitted base_branch. | Add base_branch: main (or whatever default applies). |
rpc error: code = InvalidArgument desc = at least one of base_image_aws_ref or base_image_gce_ref is required | Recipe body has neither base image. | Add base_image_gce_ref: or base_image_aws_ref: (or both). |
rpc error: code = InvalidArgument desc = provisioning_timeout is required | Recipe body missing provisioning_timeout. | Add provisioning_timeout: 30m (or another Go duration). |
rpc error: code = InvalidArgument desc = group source is required (static, github_admin, or all_tenant_members) | Group body uses source: static instead of the proto oneof. | Put the source as a top-level key: static: {members: [...]}, github_admin: {}, or all_tenant_members: {}. |
rpc error: code = InvalidArgument desc = grant must specify at least one group or user | Tenant-binding grant block has no users or groups array. | Add grant.users: [...] or grant.groups: [...]. |
rpc error: code = InvalidArgument desc = role "X" does not exist | Tenant-binding references a role that has not been created yet. | Create the role first with murmur set role X. |
rpc error: code = InvalidArgument desc = ref name "X" does not match payload name "Y" (on repo-config) | The positional name is the clone_url itself, not an arbitrary identifier. | murmur set repo-config "https://github.com/org/repo" with body clone_url: https://github.com/org/repo. |
Could not list workspaces: rpc error: code = PermissionDenied desc = s2s identity required — skipping | Workspace lookup during murmur setup for a tenant without workspaces yet. | Cosmetic; safe to ignore. Setup proceeds. |
unknown command "connect" / unknown command "install" | Documented commands that the CLI does not implement. | Use the catalog-level equivalent or skip; documented in PR review notes. |
Required-field cascade pattern
The API validates one missing required field at a time. To create a resource from scratch, you usually send an initial body, parse the error to learn the next required field, append it, and resend until it succeeds. The minimum YAMLs in this doc are the fully-passing bodies — they save you the round trips. When designing new kinds, the same pattern lets an LLM bootstrap valid configs from a single starting field:name. Iterate until the body is accepted.
Reference: dependency order for a brand-new tenant
For an admin onboarding a tenant from zero:murmur setup— install the CLI, authenticate, and write your encrypted developer profile.pool-config default— setmax_vmsto your budget ceiling.role+group+tenant-binding— bind humans and service profiles to roles.secret— tenant secrets (npm tokens, database URLs, package-registry credentials).recipe+murmur bake— only if you need a toolchain beyond the platform debian12 base.environment— composemachine_type_ref+disk_type_ref+disk_size_gbfor the agent VM size.workspace— wire image + environment + placement + repos + secrets.agent-persona+flight— reusable agent behaviors and event-triggered orchestrations.murmur spawn— confirm the loop works end-to-end with a hello-world agent.
murmur rm <kind> <name>, blocked only by referential integrity (e.g. you cannot delete an environment referenced by a workspace — delete the workspace first or repoint it).