Help us shape the future of Go! Take the 2026 Go Developer Survey

marvel

module
v0.0.0-...-9672ca5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2026 License: MIT

README

Marvel — Agent Orchestration Control Plane

A kubernetes-like control plane for AI agent workloads. Manages the full lifecycle of BYOA (Bring Your Own Agent) sessions: scheduling, configuration, process management, health monitoring, and rolling shifts.

Where kubernetes orchestrates containers across nodes, marvel orchestrates agent sessions across tmux panes.

Install

Option 1: Homebrew
brew tap arcavenae/tap                # one-time (Homebrew >= 6.0 needs the tap trusted first)
brew install arcavenae/tap/marvel

The tap's marvel formula currently tracks the latest alpha release. A dedicated stable formula will be added when the first v* release ships.

Option 2: Install with mise

mise is a polyglot version manager. It reads a per-project mise.toml, pulls the binary directly from GitHub Releases, and verifies GitHub Artifact Attestations natively — no Homebrew tap required.

Alpha channel (prereleases from main) — the first stable release is pending, so opt into prereleases per-tool:

# mise.toml
[tools]
"github:ArcavenAE/marvel" = { version = "latest", prerelease = true }
mise install
marvel version

Stable (when a v* release ships) — drop the prerelease = true flag:

mise use github:ArcavenAE/marvel@latest

Marvel's alpha assets are not -a-suffixed, so stable and alpha share the same marvel shim — mise pins one version at a time per mise.toml, and switching channels swaps the underlying binary.

macOS troubleshooting — if a quarantine-aware host copies the mise install and Gatekeeper blocks launch, clear the xattr once:

xattr -d com.apple.quarantine "$(mise which marvel)"
Option 3: Download a pre-built binary

Download the latest release from GitHub Releases. Binaries are available for macOS (arm64, amd64) and Linux (amd64, arm64 — Raspberry Pi 3/4/5 64-bit, AWS Graviton, etc.). macOS binaries are code-signed and Apple-notarized.

Quick Start

# Build
just build

# Start the daemon
marvel daemon &

# Load a manifest
marvel work examples/demo.toml

# Watch sessions
marvel get sessions -w

# Trigger a rolling shift (replace all sessions with fresh ones)
marvel shift demo/squad

# Clean up
marvel stop --teardown

Resource Model

Workspace     isolation boundary (k8s namespace)
  └─ Team     cohesive unit of agents (k8s deployment)
       └─ Role     one kind of agent: name, replicas, runtime, healthcheck
            └─ Session    one agent process in a tmux pane (k8s pod)

A team contains heterogeneous roles. A review team might have 1 supervisor, 3 reviewers, and 1 architect — each with its own runtime, replica count, restart policy, and healthcheck config.

Manifests

Resources are declared in TOML manifests:

[workspace]
name = "my-project"

[[team]]
name = "review-squad"

  [[team.role]]
  name = "reviewer"
  replicas = 3

    [team.role.runtime]
    image = "claude"
    command = "claude"

    [team.role.healthcheck]
    type = "heartbeat"
    timeout = "30s"
    failure_threshold = 3

  [[team.role]]
  name = "supervisor"
  replicas = 1
  restart_policy = "always"

    [team.role.runtime]
    image = "claude"
    command = "claude"

image names the harness and is what selects the runtime adapter; marvel falls back to command when it is unset, and a name matching no adapter resolves to the generic one. Every adapter puts the session's identity in the environment (MARVEL_SESSION, MARVEL_ROLE, MARVEL_TEAM, MARVEL_WORKSPACE), so no role passes its own identity flags. The claude adapter additionally names the session in the system prompt, unless the role already passes its own --append-system-prompt or its command is a wrapper around the harness (anything other than claude by name or path), which then owns the prompt. Runnable manifests live in examples/.

CLI

# Daemon and manifests
marvel daemon                                        # start the daemon
marvel work <manifest.toml|.yaml>                    # load manifest, reconcile desired state
marvel stop                                          # stop daemon, detach (agents keep running, adopted on restart)
marvel stop --teardown                               # stop daemon and end every agent

# Inspect
marvel get sessions                                  # list sessions (-w for watch mode); shows CPU% and RSS per session
marvel get teams                                     # list teams and roles
marvel get workspaces                                # list workspaces
marvel get endpoints                                 # list endpoints
marvel describe session <key>                        # session details
marvel events                                        # recent session/team state-transition events (incl. agent.* for observed runtimes)

# Lifecycle
marvel scale <ws/team> --role <r> --replicas N       # scale a role
marvel shift <ws/team> [--role <r>]                  # rolling shift
marvel run <cmd> [args...] --role <r>                # one-off session
marvel kill <session-key>                            # kill a session (alias: delete session)
marvel delete <resource> <key>                       # delete a session, team, or workspace

# Session interaction
marvel capture <session-key>                         # capture a session's pane content
# a plain capture drops dim text and says so on stderr; it reads the pane twice, so a pane that changes between the reads can give a stray notice or miss one
marvel capture -e <session-key>                      # keep escape sequences, so dim text (a composer suggestion) can be told from a typed draft
marvel capture --composer <session-key>              # report on stderr whether the composer is empty, holds text or is mid-turn; types nothing
marvel inject <session-key> [text] [--key <key>]     # send keystrokes to a pane (executive privilege)

# Remote daemons (named clusters)
marvel config add-cluster <name> ...                 # add or update a cluster
marvel config list                                   # list configured clusters
marvel config current                                # show the current cluster
marvel config use-cluster <name>                     # switch the current cluster
marvel config remove-cluster <name>                  # remove a cluster

# SSH keys (client auth to a daemon)
marvel keys generate                                 # generate a client keypair
marvel keys show                                     # print a client public key to share with a daemon admin
marvel keys list                                     # list local client keypairs
marvel keys trust <cluster>                          # show a cluster's host key fingerprint, ask, then record it (--yes skips the question)
marvel keys authorize <pubkey>                       # authorize a client's key on this daemon
marvel keys authorized                               # list clients authorized on this daemon
marvel keys revoke <fingerprint>                     # revoke a client
marvel keys doctor                                   # audit (and optionally fix) permissions under ~/.marvel/

# Version and self-upgrade
marvel version                                       # print version and channel
marvel upgrade                                        # upgrade to the latest release

stop defaults to detach: the daemon checkpoints state and exits while agents keep running; the next marvel daemon adopts the live panes. Use --teardown to end every agent and leave the machine clean.

marvel events includes agent.* events (session start/end with cost and timing, tool calls, permission prompts) for runtimes marvel can observe, today a headless stream-json launch (see examples/claude-headless.toml).

Shifts

Shifts are rolling replacements of agent sessions. Agent sessions accumulate context, drift, and stale mental models. A shift starts fresh sessions, verifies they're running, then drains the old ones — preserving team identity.

# Shift all roles (workers first, supervisor last)
marvel shift my-project/review-squad

# Shift only one role
marvel shift my-project/review-squad --role reviewer

Sessions track their generation (visible in marvel get sessions as the GEN column). During a shift, old-generation sessions drain one per reconciliation tick while new-generation sessions are already running.

Healthchecks

Roles can configure healthchecks. Currently supported: heartbeat (agent must send periodic heartbeats to the daemon) and process-alive (tmux pane exists). A passed heartbeat reads healthy in marvel get sessions; a process-alive role reads alive, because nothing beyond the pane was checked.

[team.role.healthcheck]
type = "heartbeat"       # "heartbeat" or "process-alive"
timeout = "30s"          # heartbeat staleness threshold
failure_threshold = 3    # consecutive failures before action

Restart policies control what happens when a session is unhealthy:

  • always (default): delete and recreate
  • on-failure: delete and recreate only if failed
  • never: mark failed, don't restart

Sessions without a configured healthcheck stay in unknown health state and are never restarted by health evaluation.

Examples

examples/ holds a manifest per scenario, each shipped in both TOML and YAML. examples/README.md indexes every one of them: what it demonstrates, grouped by topic, and which to open first.

Three entry points:

Manifest What it shows
examples/generic-agent.toml The smallest thing that works: marvel managing an arbitrary command through the generic adapter. No model auth needed.
examples/claude.toml Real Claude Code agents beside a simulator supervisor: adapter selection, permission injection, identity injection. Requires the claude CLI.
examples/review-team.toml A heterogeneous team: reviewer, architect and supervisor roles, each with its own replica count.

Just Recipes

just build          # build marvel + simulator
just test           # run all tests
just demo           # load demo manifest, show state
just demo-shift     # demonstrate shift lifecycle
just watch          # watch sessions (interactive)
just shift <team>   # trigger a shift
just scale <t> <r> <n>  # scale a role
just start          # start daemon (foreground)
just stop           # stop daemon
just clean          # kill tmux sessions, remove binaries

Architecture

Written in Go. The daemon manages agent sessions through a tmux substrate:

  • Reconciliation loop (2s interval): compares desired state (manifests) with actual state (running sessions), creates/deletes to match
  • Health evaluation: checks heartbeat staleness, applies restart policies
  • Shift state machine: launching → draining → complete, driven by the reconciliation loop
  • Usage accountant: derives context-window occupancy from each harness's own usage reporting, feeding the CTX% column (see user-guide)
  • Simulator: context pressure simulation for testing without real agents

BYOA

Marvel works with any BYOA console it can launch as a process in a tmux pane: claude, codex, opencode, or a custom agent. The runtime is just a command path plus args, and marvel does not care what the agent is: it manages the process lifecycle.

The prompt is not delivered on stdin. The claude adapter passes it as a positional argument under --print; the codex and opencode adapters close stdin outright, because codex exec otherwise appends piped stdin to its prompt and hangs on the pane tty.

A forestage adapter also ships, frozen as the reference implementation of the deep-integration contract rather than as a live target (forestage was retired 2026-07-31).

Requirements

  • Go 1.25+
  • tmux
  • just (command runner)

Directories

Path Synopsis
cmd
applycheck command
Command applycheck applies a manifest to an in-memory store and prints what the store would hold, so an upgrade's post-check can compare it with a reference without touching a daemon.
Command applycheck applies a manifest to an in-memory store and prints what the store would hold, so an upgrade's post-check can compare it with a reference without touching a daemon.
marvel command
rolescheck command
Command rolescheck applies a manifest to an in-memory store and prints the roles the store would hold.
Command rolescheck applies a manifest to an in-memory store and prints the roles the store would hold.
simulator command
Command simulator is a Claude Code simulator for testing marvel orchestration.
Command simulator is a Claude Code simulator for testing marvel orchestration.
watcherprobe command
Command watcherprobe is the logger and checker half of the watcher's claude probe kit (scripts/probes/watcher-claude).
Command watcherprobe is the logger and checker half of the watcher's claude probe kit (scripts/probes/watcher-claude).
contracts
go/envelope
Package envelope holds the generated Go types and the validator for the director envelope contract (bd aae-orc-b69n).
Package envelope holds the generated Go types and the validator for the director envelope contract (bd aae-orc-b69n).
go/envelopeschema
Package envelopeschema holds the director envelope JSON Schema as bytes and nothing else.
Package envelopeschema holds the director envelope JSON Schema as bytes and nothing else.
go/event
Package event holds the validator for the marvel adapter event vocabulary wire twin (bd aae-orc-b69n).
Package event holds the validator for the marvel adapter event vocabulary wire twin (bd aae-orc-b69n).
internal
admission
Package admission is the arithmetic that refuses a spawn which would exceed a team-declared budget.
Package admission is the arithmetic that refuses a spawn which would exceed a team-declared budget.
api
Package api defines marvel's resource types — the k8s-like primitives for agent orchestration.
Package api defines marvel's resource types — the k8s-like primitives for agent orchestration.
asof
Package asof is the one cell shape that `marvel get sessions` uses for every derived or status reading: a value, when it was observed, until when it holds, and where it came from.
Package asof is the one cell shape that `marvel get sessions` uses for every derived or status reading: a value, when it was observed, until when it holds, and where it came from.
backoff
Package backoff is the restart schedule two crash loops share.
Package backoff is the restart schedule two crash loops share.
broker
Package broker is the skeleton of marvel's credential broker: a seat asks for a short-lived token, the broker checks the seat is who its heartbeat token says, and a driver issues the token.
Package broker is the skeleton of marvel's credential broker: a seat asks for a short-lived token, the broker checks the seat is who its heartbeat token says, and a driver issues the token.
bus
Package bus renders and maintains the configuration of a cluster's local NATS broker: nats-server.conf and the 0600 authorization.conf beside it (brief 10 sections 3 and 5, aae-orc-e9g8i).
Package bus renders and maintains the configuration of a cluster's local NATS broker: nats-server.conf and the 0600 authorization.conf beside it (brief 10 sections 3 and 5, aae-orc-e9g8i).
childproof
Package childproof holds the one way to signal a managed child: through a Child whose identity was read from the kernel and matched.
Package childproof holds the one way to signal a managed child: through a Child whose identity was read from the kernel and matched.
composer
Package composer reads what state a harness's input composer is in from a pane capture, so an inject can be checked by its effect and a clear is only ever sent where it is safe (aae-orc-dgb35, aae-orc-g88i1).
Package composer reads what state a harness's input composer is in from a pane capture, so an inject can be checked by its effect and a clear is only ever sent where it is safe (aae-orc-dgb35, aae-orc-g88i1).
config
Package config manages marvel's client configuration, modeled after kubeconfig.
Package config manages marvel's client configuration, modeled after kubeconfig.
daemon
Package daemon provides the marvel daemon — a long-running process that manages sessions via tmux and serves CLI requests over Unix sockets, SSH tunnels, or (for advanced use) bare TCP sockets.
Package daemon provides the marvel daemon — a long-running process that manages sessions via tmux and serves CLI requests over Unix sockets, SSH tunnels, or (for advanced use) bare TCP sockets.
daemonrpc
Package daemonrpc is the marvel daemon's wire format and its client: the request and response envelopes, the method names, and the functions that dial a daemon over a Unix socket, mrvl://, ssh:// or bare TCP and carry one request or one events.watch stream.
Package daemonrpc is the marvel daemon's wire format and its client: the request and response envelopes, the method names, and the functions that dial a daemon over a Unix socket, mrvl://, ssh:// or bare TCP and carry one request or one events.watch stream.
events
Package events provides a bounded in-memory ring of structured state-transition events — marvel's equivalent of `kubectl get events`.
Package events provides a bounded in-memory ring of structured state-transition events — marvel's equivalent of `kubectl get events`.
gittest
Package gittest builds throwaway git repositories for tests.
Package gittest builds throwaway git repositories for tests.
homeguard
Package homeguard keeps a package's tests out of the operator's real home.
Package homeguard keeps a package's tests out of the operator's real home.
keys
Package keys handles marvel's client and host SSH keypairs.
Package keys handles marvel's client and host SSH keypairs.
knownhosts
Package knownhosts manages marvel's ~/.marvel/known_hosts file — trust-on-first-use host-key verification for mrvl:// connections.
Package knownhosts manages marvel's ~/.marvel/known_hosts file — trust-on-first-use host-key verification for mrvl:// connections.
limitact
Package limitact is the limit action of design 9.4 and 9.9 (UL-7): what marvel does when the pane-menu source finds a seat on the usage-limit menu.
Package limitact is the limit action of design 9.4 and 9.9 (UL-7): what marvel does when the pane-menu source finds a seat on the usage-limit menu.
limitmenu
Package limitmenu recognises the usage-limit menu a harness shows when an account runs out, and reads the reset time that menu names.
Package limitmenu recognises the usage-limit menu a harness shows when an account runs out, and reads the reset time that menu names.
logbuf
Package logbuf implements a bounded in-memory line ring for the marvel daemon.
Package logbuf implements a bounded in-memory line ring for the marvel daemon.
otel
Package otel provides OpenTelemetry metric helpers for marvel.
Package otel provides OpenTelemetry metric helpers for marvel.
panemenu
Package panemenu is the pane-menu source of the "limited" condition (design 9.3, ruled UL-R2).
Package panemenu is the pane-menu source of the "limited" condition (design 9.3, ruled UL-R2).
panestate
Package panestate classifies what a harness's pane is showing, from the visible screen alone (docs/design/harness-state-watchdog-p1.md section 4).
Package panestate classifies what a harness's pane is showing, from the visible screen alone (docs/design/harness-state-watchdog-p1.md section 4).
paths
Package paths centralizes marvel's on-disk layout and permission rules.
Package paths centralizes marvel's on-disk layout and permission rules.
pidfile
Package pidfile reads the pid a daemon writes to its pidfile.
Package pidfile reads the pid a daemon writes to its pidfile.
procargs
Package procargs reads a process's exact argument list, from the kernel and not from `ps`.
Package procargs reads a process's exact argument list, from the kernel and not from `ps`.
procstat
Package procstat samples CPU and memory for a process subtree.
Package procstat samples CPU and memory for a process subtree.
rlog
Package rlog provides a size-rotating, compressing log writer for the marvel daemon's on-disk log file.
Package rlog provides a size-rotating, compressing log writer for the marvel daemon's on-disk log file.
runtime
Package runtime provides adapter interfaces and implementations for launching BYOA agent sessions.
Package runtime provides adapter interfaces and implementations for launching BYOA agent sessions.
runtime/claudecode
Package claudecode implements the marvel runtime adapter parse layer for Claude Code invoked with
Package claudecode implements the marvel runtime adapter parse layer for Claude Code invoked with
runtime/codex
Package codex implements the marvel runtime adapter parse layer for the Codex CLI invoked with `codex exec --json`.
Package codex implements the marvel runtime adapter parse layer for the Codex CLI invoked with `codex exec --json`.
runtime/crush
Package crush holds marvel's guards for launching the Crush harness.
Package crush holds marvel's guards for launching the Crush harness.
runtime/events
Package events defines the marvel runtime adapter event vocabulary — the normalized shape adapters emit after digesting a harness-specific telemetry stream (Claude Code stream-json, Codex --json, OpenCode SSE, etc.).
Package events defines the marvel runtime adapter event vocabulary — the normalized shape adapters emit after digesting a harness-specific telemetry stream (Claude Code stream-json, Codex --json, OpenCode SSE, etc.).
runtime/opencode
Package opencode implements the marvel runtime adapter parse layer for OpenCode invoked with `opencode run --format json`.
Package opencode implements the marvel runtime adapter parse layer for OpenCode invoked with `opencode run --format json`.
seaturi
Package seaturi is the one place marvel cuts a seat's identity string.
Package seaturi is the one place marvel cuts a seat's identity string.
service
Package service holds the two registries the cluster Services list is validated against: class contracts (what every provider of a class must deliver to a consumer) and provider drivers (what renders, spawns, health-checks, and mints for a class).
Package service holds the two registries the cluster Services list is validated against: class contracts (what every provider of a class must deliver to a consumer) and provider drivers (what renders, spawns, health-checks, and mints for a class).
session
Package session manages session lifecycle — creating and destroying sessions by coordinating the API store, tmux driver, and runtime adapters.
Package session manages session lifecycle — creating and destroying sessions by coordinating the API store, tmux driver, and runtime adapters.
shorttmp
Package shorttmp gives a test a scratch directory short enough to hold a marvel layout root.
Package shorttmp gives a test a scratch directory short enough to hold a marvel layout root.
simulator
Package simulator implements a Claude Code simulator for load testing marvel.
Package simulator implements a Claude Code simulator for load testing marvel.
suspend
Package suspend freezes the processes of a fleet in place and resumes them (docs/design/fleet-suspend-resume.md section 2).
Package suspend freezes the processes of a fleet in place and resumes them (docs/design/fleet-suspend-resume.md section 2).
team
Package team implements the team controller — a reconciliation loop that maintains desired replica count for each role within each team, and orchestrates shift operations (rolling session replacement).
Package team implements the team controller — a reconciliation loop that maintains desired replica count for each role within each team, and orchestrates shift operations (rolling session replacement).
tmux
Package tmux provides a shell-out driver for tmux operations.
Package tmux provides a shell-out driver for tmux operations.
tmux/tmuxtest
Package tmuxtest holds helpers that tests in several packages share about the tmux they run against.
Package tmuxtest holds helpers that tests in several packages share about the tmux they run against.
upgrade
Package upgrade implements self-update for the marvel binary.
Package upgrade implements self-update for the marvel binary.
usage
Package usage is marvel's context-window and token accountant: the single producer of the CTX% column for sessions whose harness marvel can observe.
Package usage is marvel's context-window and token accountant: the single producer of the CTX% column for sessions whose harness marvel can observe.
view
Package view builds and swaps a per-seat read-only view of a repository's default branch (docs/design/readonly-view.md, marvel#609).
Package view builds and swaps a per-seat read-only view of a repository's default branch (docs/design/readonly-view.md, marvel#609).
watcherprobe
Package watcherprobe is the checker and the loggers of the watcher's claude probe kit (docs/design/marvel-watcher.md section 6).
Package watcherprobe is the checker and the loggers of the watcher's claude probe kit (docs/design/marvel-watcher.md section 6).
workload
Package workload spawns the managed children the daemon supervises: a process that is not a Role, has no pane, and must not inherit the daemon's environment (docs/design/services-list.md section 3, aae-orc-oo62t).
Package workload spawns the managed children the daemon supervises: a process that is not a Role, has no pane, and must not inherit the daemon's environment (docs/design/services-list.md section 3, aae-orc-oo62t).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL