Configuration
Configuration and manifests.
Two files. The configuration file on your laptop says which worker to use and where the Claude token comes from; it holds your cloud identifiers and stays out of every repository. The manifest says what session to run.
01 / Configuration file
~/.config/mantle/config.toml
Start from examples/config.toml. Unknown fields are refused. Another file or a named profile can be selected; see profiles.
| Field | Meaning |
|---|---|
provider | "aws" or "kubevirt". The matching table below is required. |
ubuntu_serial | Eight-digit Ubuntu 24.04 cloud-image build serial, such as 20260926. Every provider boots the same build. |
[aws] profile, region, vpc, subnet | Your AWS profile and network placement. Required for provider = "aws". |
[aws] instance_type, root_volume_gib, data_volume_gib | Defaults m7i.4xlarge, 50 and 200. |
[kubevirt] context, namespace, cpu, memory_gib, root_disk_gib, data_disk_gib | The Kubernetes context and namespace, and the VM’s size. All required for provider = "kubevirt". task k3d-up creates the context k3d-mantle. |
[claude] token_command | An argv list that prints the token from claude setup-token, such as a keyring lookup. Preferred. |
[claude] token_file | A file holding the token, for hosts without a keyring. ~/ is expanded. |
Omit the whole [claude] table to provision a worker without a Claude token, for example for Codex only. A worker reported READY has its confinement and toolchain in place; agent authentication is separate.
02 / Manifest
The session manifest.
mantle start reads mantle.yaml unless you name another file. Unknown fields are refused, and fields the design declares but 0.3.1 does not serve are refused by name, so a manifest never asks for something it silently does not get. Examples: Claude Code, Codex, a command.
apiVersion: mantle.beyond10x.dev/v1alpha1
kind: Session
metadata:
name: my-project
runtime:
profile: rust-dev
workspace:
repositories:
- name: mantle
repository: https://github.com/beyond10x/mantle.git
ref: main
mount: mantle
agent:
kind: claude-code
cwd: /workspace/mantle
resources:
cpu: 4
memory: 16GiB
pids: 4096
lifecycle:
detachKeepsRunning: true
retainFor: 8h| Field | Rule |
|---|---|
apiVersion, kind | Exactly mantle.beyond10x.dev/v1alpha1 and Session. |
metadata.name | 1–48 characters of a-z, 0-9 and -, not starting with -. Unique among your sessions until destroyed. |
runtime.profile | Optional; only rust-dev is served. |
workspace.root | Optional; must be /workspace. |
workspace.repositories[] | At least one. repository must be an https:// URL reachable through the gateway. ref is a branch, a tag (lightweight or annotated) or a full commit id. mount is one path component, unique in the manifest. There is no Git credential broker: use public repositories. |
agent | Required. See agent. |
placement | Accepted and ignored: 0.3.1 has one worker. |
03 / Agent
Agent kinds.
agent.kind is required; a manifest without it is refused with missing field `kind`. agent.cwd is /workspace or a path inside a declared mount. agent.auth may be omitted; if given, it must match the kind.
| Kind | Authentication and behaviour |
|---|---|
kind: claude-codeauth: claude-oauth | Claude Code 2.1.287, installed by checksum when the worker is provisioned. The token from [claude] reaches the agent through the claude secret slot; see credentials. Example: examples/substrate.yaml. |
kind: codexauth: chatgpt-device | Codex 0.153.4, installed and verified by SHA-256 on every worker up. Complete ChatGPT device login in the agent terminal when prompted; no Claude token or API key is needed. Auth and conversation files stay in /workspace/.mantle/home/.codex; launcher replay is volatile; Codex’s SQLite and text diagnostics go to a launcher-verified tmpfs. Use start --detached to log in after attaching. Example: examples/codex.yaml. |
kind: commandargv: [...] | New in 0.3.1. The session’s process is agent.argv, a non-empty list whose first element is an absolute path. It is run directly, with no shell. It may have at most 243 elements, each non-empty, at most 4096 bytes and without NUL: Substrate admits at most 256 argv elements, and the launcher takes 13 of them. agent.auth is refused: a command session receives no agent credential, so no claude secret slot, no CLAUDE_CODE_OAUTH_TOKEN, no Codex home and no Claude or Codex variables. agent.cwd, network, resources, retainFor, attach and detach, stop and destroy work as for the other kinds; restart runs the stored argv again. mantle list shows agent command and auth method none; mantle status prints an argv line and status --json carries argv. Example: examples/shell.yaml, ["/bin/bash", "-l"]. |
The manifest parser refuses a command manifest that breaks these rules before anything reaches the worker, with one of:
agent.kind command requires agent.argvagent.argv is served only with agent.kind commandagent.argv must be a non-empty list whose first element is an absolute pathagent.argv must have at most 243 elements, each non-empty, at most 4096 bytes and without NULagent.auth is refused with agent.kind command: a command session receives no agent credential
All three kinds use the same Substrate terminal transport, which may record terminal output. This is not a non-recording mode. Device login, authenticated model and tool turns and token refresh are not verified end to end; see the qualification evidence. The command kind is covered by package tests and native scenarios only; it has not been run on a live worker.
04 / Resources
Requested, then reported as applied.
| Field | Default and bound | Enforcement |
|---|---|---|
cpu | 4; values below 1 become 1 | Sets CARGO_BUILD_JOBS. Not a CPU bandwidth limit: Substrate 0.16.1 bounds cumulative CPU time only. |
memory | 16GiB; at least 512MiB | cgroup memory limit. A worker that does not report the memory and pids limit facts is refused at start with FAILED_CAPABILITY. |
pids | 4096; 1–4096 | cgroup pids limit, same requirement. |
storage | No request | A workspace quota, capped at the worker’s maximum, when the worker serves workspace quotas. Otherwise start prints requested, NOT enforced. |
Sizes take KiB, MiB, GiB or TiB. mantle status prints what was requested and what Substrate applied on separate lines.
05 / Network
A fixed allowlist.
network.default must be deny. network.capabilities may name model.anthropic, git.github and rust.crates; any other name is refused. Naming a subset does not narrow the gateway: every session on a worker reaches the same ten destinations, listed under network. network.profile is accepted and ignored.
06 / Lifecycle
How long the agent runs.
lifecycle.retainFor is the agent execution’s timeout and lease: s, m or h, more than 0 and at most 24h (Substrate’s execution bound), default 8h. The agent ends at the latest when it expires; the workspace stays. detachKeepsRunning: false is refused. idleAfter is accepted and ignored; on AWS the worker’s own idle alarm applies instead (worker).
07 / Session environment
What a process inside sees.
/workspaceis writable; the repositories are mounted under it./opt/mantle(agents, launcher, Rust toolchain) is read-only. Host/usr,/bin,/liband/lib64are bound read-only by Substrate, so the worker’s packages (build-essential,cmake,ninja-build,pkg-config,libssl-dev,git,ripgrepand others) are available.HOME=/workspace/.mantle/home,CARGO_HOME=/workspace/.mantle/cargo,CARGO_BUILD_JOBSfromcpu.- The Rust linker and C compiler are
gcc; the C++ compiler isg++. Ubuntu’sccresolves outside the confined root. - The agent is started with the gateway as its proxy. A command run with
mantle execis not; give networked Cargo builds the proxy explicitly:
mantle exec SESSION -- cargo --config 'http.proxy="http://127.0.0.1:3128"' \
check --locked --manifest-path /workspace/PROJECT/Cargo.toml