Skip to content
ArcavenAEPublic

About

Multiagent orchestration — spawns, coordinates, and supervises BYOH (bring your own harness) agent sessions

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

1,001 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

marvel

OpenSSF Baseline OpenSSF Scorecard CI CodeQL Release License: MIT Go version

marvel keeps a declared team of AI agent sessions running: it starts them, watches them, repairs them and rotates them, for any harness.

marvel get sessions in watch mode, while a session is killed and replaced and the team shifts to a fresh generation

You describe a team in a short manifest: its roles, how many sessions each role runs, the command each one starts, and how marvel knows a session is alive. marvel runs each session in a tmux pane, compares what is running with what you declared every two seconds, and fixes the difference.

A session that dies is replaced. A role can be scaled with one command. A shift swaps every session for a fresh one while the old ones drain, so a long-running team sheds stale context without going dark. It works with Claude Code, Codex, opencode, or any command you name.

New here? The first-run page walks four stages, each optional and each with one proof command, so you can stop at the first one that does what you need.

Try it with an installed marvel. It needs no model login and costs nothing, and tmux is the one prerequisite. marvel example lists the manifests the binary carries:

marvel example
marvel daemon &
marvel example demo > demo.toml
marvel work demo.toml
marvel get sessions
marvel stop --teardown

Then take the tour, which needs a source checkout, or go deep with the four-act demo.

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, with 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.

Host requirements (tmux 3.5 or later, and nats-server only for a managed bus) are in the admin guide.

Quick Start

# See the manifests the binary carries
marvel example

# Start the daemon
marvel daemon &

# Load the demo manifest
marvel example demo > demo.toml
marvel work 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

To run from a source checkout instead, build first with just build; it puts marvel in bin/.

Resource Model

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

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); --columns cpu,rss adds CPU% and RSS
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)

About

Multiagent orchestration — spawns, coordinates, and supervises BYOH (bring your own harness) agent sessions

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages