Skip to content

Repository files navigation

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
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>                          # record a cluster's host key in known_hosts
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).

[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)

About

Multiagent orchestration — spawns, coordinates, and supervises BYOA agent sessions

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages