First run
Part of getting started. Steps keep their original numbering.
2. Look at the instance
examples/hello-worker is a complete, minimal instance. The root holds the config and boot
prompt (host-only); only the workspace/ subdir is bind-mounted into the jail:
hello-worker/ # instance root, run `lever` here; NOT mounted
├── lever.yaml # the config
├── manager.md # the manager's boot prompt (host-only)
└── workspace/ # tree: the bind-mounted subdir (agents edit this)
└── workers/
└── worker/ # the worker's workspace
# examples/hello-worker/lever.yaml
name: hello-worker
backend: orbstack
tree: workspace # a confined SUBDIR; the root itself is never mounted
scion:
version: 65531d7f # pin a scion commit; a lever release ships this one prebuilt
# api-key is the secure default (the real key never enters the container) but
# needs a Console API key. This demo opts into subscription (your Claude OAuth
# token), so egress stays open and the token is projected to the agents.
broker:
llm_auth: subscription
manager:
image: lever.local/lever-claude
prompt_file: manager.md # resolved at the root (host-only), not inside the mount
credential_file: ~/.scion/oauth-token # YOU supply this: your Claude OAuth token (0600)
allow_ports: []
workers:
- name: worker
dir: workers/worker # relative to tree, i.e. workspace/workers/worker
The credential_file is the one thing you add: point it at a least-privilege
Claude OAuth token (mint with claude setup-token). In subscription mode its
contents are projected into the agent containers, so keep it 0600.
The config and prompt live at the root, outside the mount, so a compromised agent can’t rewrite them. See config-reference.md for every key.
There’s nothing more to stage: the image you built in
step 1a already
has lever-manager baked in at /usr/local/bin, so it’s on PATH the moment the manager container
boots.
3. Preview the bring-up plan (no side effects)
Run lever from the instance root (where lever.yaml lives, there’s no walk-up discovery):
cd examples/hello-worker
lever apply --dry-run
You’ll see a backend: <profile summary> line, then the ordered plan:
broker-up
load-image lever.local/lever-claude:arm64
init-machine
config-registry
scion-server
hub-identity /…/hello-worker/workspace
credential ~/.scion/oauth-token
register-project /…/hello-worker/workspace
agent-template /…/hello-worker/workspace
mint-manager-bootstrap /…/hello-worker/workspace
start-manager hello-worker
(With manager.image_tar set, the load-image line also names the archive it streams in:
load-image lever.local/lever-claude:arm64 (from /…/hello-worker/images/lever-claude.tar).)
scion-server starts the jail’s hub with --dev-auth=false, in scion’s proxy auth mode: it trusts
only assertions lever signs with a key held on the host. hub-identity then signs in as lever’s
hub admin and controller, registers the instance’s project, and has the controller mint the
controller PAT that drives every later scion verb (see
security model §4.2). credential
(present because this example sets credential_file) stages the manager’s Claude OAuth token.
register-project is the one scion init/hub link for the whole instance; the manager and every
worker are agents inside it, and the step also strips scion’s default shared scratchpad and writes
the project’s agent-role ceiling (see security model §4.4). Workers are not started here; the manager dispatches them on demand
(step 6).
4. Scaffold the operator skills (lever init)
Lever ships SKILL.md files that teach your agents how to operate inside the
jail — the capability flow (mint via lever-capability, attach the token as
_capability on every gated call), messaging, and worker dispatch. Scaffold
them into your instance tree:
lever init
This writes .claude/skills/lever-operator/ at the tree root, .claude/skills/lever-agent/
inside each declared worker directory, and a marked reference block in your tree-root CLAUDE.md.
The files are plain markdown in your tree, stamped with the lever version they came from.
Re-run lever init after upgrading lever or adding a worker. Edited files are left alone with a
warning; --force, --check and --adopt are described in the
CLI reference.
5. Bring it up
lever up
lever up runs the plan from step 3 (creating the jail if needed), starts the manager, and hands
you its terminal. First boot takes ~10-15 minutes (runtimes + a multi-GB image load); after
that a lever up after lever stop typically takes 1-2 minutes, and one with the manager already
running only seconds. System requirements & sizing has the
numbers per backend and what the first boot downloads.
up is idempotent: re-running it resumes a suspended manager and re-attaches. Detach with
Ctrl-b d; the manager keeps running in the jail, and lever attach or the next lever up
re-attaches to the same conversation.
--fresh starts a new manager thread; --no-attach brings up without attaching.
To reattach without re-provisioning, run lever attach from the instance root in a separate
terminal. It is strictly passive: if the jail is not up it fails with “run lever up first”.
If something looks wrong, run lever doctor; each failing check prints a fix hint (the full check
list is in the CLI reference).
6. Dispatch a worker (inside the manager session)
You’re now talking to the manager agent. It drives workers with the in-jail lever-manager binary
(baked into the image, already on PATH). A dispatch looks like:
lever-manager agent start worker --task "Write a haiku to haiku.md"
Notes:
workeris the worker’s configured name, not a path or a bare scion slug. The command is a thin client of the capability broker: the broker authenticates the manager, validates the name against the config, and starts the worker host-side (with operator identity) — as an agent in the same single instance project as the manager, mounted at its ownworkers/worker/subdir rather than the manager’s whole tree.- There is no
--imageflag: the broker resolves the worker’s image from the config (workers[].image, else the manager image).
agent start is for a fresh worker only; a worker’s task is fixed at creation, so agent start
against an existing record returns HTTP 409. Use lever-manager agent resume|suspend|stop NAME for
lifecycle, and lever worker purge NAME --force (host) to discard the record before starting it again with
a new task.
Watch progress and relay events:
lever-manager watch --events-file events.jsonl & # appends scion events to a file you can tail
lever-manager agent list # phases of running agents
lever-manager msg list # typed inbox (input-needed, completion, …)
lever-manager msg send "answer" --to worker
msg and watch are mTLS clients of the broker (/msg/send, /msg/list), not of scion
directly; no agent holds a hub credential (architecture §4). --to takes
agent:<name>, a bare <name>, or user:manager for the manager. Routing is identity-derived and
default-deny; the policy is under broker.messaging in the config reference.
To see a worker’s session directly, run lever attach worker from your host (another terminal,
instance root). To message an agent from the host without attaching, use lever msg send "…" --to
worker (or --to hello-worker for the manager); the note lands as the agent’s next user turn.
When worker finishes, the file it wrote (workers/worker/haiku.md) is there on your host; it was
mounted in place.
8. Detach, stop, or destroy
Three levels, from lightest to heaviest:
| detach | lever stop |
lever destroy |
|
|---|---|---|---|
| What happens | leave your TTY (Ctrl-b d) |
power the jail machine off | delete the jail machine |
| Manager state | still running | suspended, then the VM halts | gone |
| Disk (image, containers) | untouched | untouched | deleted |
| Host broker (and remote proxy) | still running | stopped | stopped, staged state cleared |
| Resume with | lever up / lever attach |
lever up (powers back on, same conversation) |
lever up (full re-provision) |
stop stops the host broker (and the remote proxy), suspends the manager and every running worker
(best-effort), then powers the jail off; the
next lever up resumes the same manager conversation. destroy removes the jail machine
lever-<name>; your tree on disk is untouched, and the next lever up re-provisions from scratch.
See the CLI reference.
lever stop --keep-vm does everything stop does except power the VM off: the agents are
suspended and the hub and the broker stopped, so the next lever up skips the VM boot. The VM
keeps its memory on the host until you power it off; see
stopping without powering off.