CLI-first arena workflow

Use this guide to prepare reusable images, create a named arena, connect over SSH and run a bounded agent task. It then covers refresh, add, and remove/recreate. These are the current implemented CLI operations. For architecture, trust roles and accepted policy, read AI-assisted work; proposed deployment work does not add options to this recipe.

Trust, execution contexts and prerequisites

The human operator runs management commands in the trusted host shell. Preparation needs a connected Linux provisioning host with working rootless Podman/Buildah, subordinate IDs and access to public registries/package repositories. Host tools include Python 3.11+, Bash, jq, Git and Skopeo; arena startup needs usable user-systemd and Quadlet. See Arena administration reference for prerequisites and deployment-specific checks.

The agent demonstration runs in an SSH session as ci, inside an untrusted execution member. Its commands and mutable workspace remain untrusted. The default runtime has no general external access; brokered inference is the permitted data-export path. Local SSH uses prepared images and needs neither an active host network-online.target nor a reachable upstream provider.

Keep trusted management tools and their host state outside execution mounts. This example uses the existing tooling checkout at $HOME/src/shyft-tools and a separate task workspace at $HOME/projects/shyft-work. Place the checkout there first and review the material exposed under the policy in AI-assisted work.

Warning

Read Known issues and assurance limits before choosing an agent or containment boundary: Codex file tools retain their sandbox failure, and strict bridge-gateway host-service isolation remains incomplete. Local-mock OpenCode success is neither real-provider acceptance nor full-containment verification.

At a glance: images and deployment are separate

Images can serve several arenas. Create generates configuration and starts the named arena; saved work and private runtime state persist separately from its replaceable images. Dashed branches below are optional, human-operated actions. Image preparation refresh does not update a running service automatically.

        ---
config:
  flowchart:
    nodeSpacing: 18
    rankSpacing: 22

---
flowchart TD
    I["Trusted host<br/>prepare images"] --> C["Human-operated create<br/>prepared local selections"]
    C --> W["Named arena<br/>untrusted SSH / agent work"]
    W -->|"human stops writers"| R["Human review<br/>outside the arena"]
    R --> T["Governed acceptance"]
    W -.->|"optional"| F["Trusted host<br/>image preparation refresh"]
    F -.->|"explicit deployment"| D["Controlled member /<br/>gateway refresh"]
    D -.->|"affected services recreated"| W
    I -.->|"prepared selection"| A["Human-operated add"]
    A -.->|"new member"| W
    R -.->|"optional"| X["Remove<br/>deployment only"]
    X -.->|"retained recreate"| C
    classDef untrusted fill:#fbe1dc,stroke:#a74432,color:#54251e
    classDef guard fill:#e4effb,stroke:#35669a,color:#193d62
    classDef context fill:#eeeeee,stroke:#666666,color:#333333
    classDef accepted fill:#e4f0e6,stroke:#477650,color:#25472b
    class W untrusted
    class I,C,R,F,D,A guard
    class X context
    class T accepted
    

Human-operated lifecycle; optional branches retain work/state, not running processes.

A. Prepare, create and use an agent

1. Trusted host shell: prepare, create and connect

Choose the public-source sequence below, or the local-source substitution in step 2, before starting. Stop if any command fails. --images identifies a named preparation selection, not an arbitrary image tag or JSON filename.

Important

First create needs a provider secret: after checking non-secret prerequisites, it prompts without echo and creates an arena-specific Podman secret. To use an existing secret, add --secret YOUR_PODMAN_SECRET_NAME; noninteractive first create requires that mechanism. Pass only the name. Never put secret values in arguments, JSON, logs or examples. Create itself makes no inference call.

cd "$HOME/src/shyft-tools"
mkdir -p "$HOME/projects/shyft-work"
bash tools/ai/build.sh prepare archlinux-dev \
  --source registry.gitlab.com/shyft-os/shyft/archlinux-dev:latest
bash tools/ai/build.sh gateways
bash tools/ai/build.sh status
python3 -B tools/ai/arena.py create shyft \
  --images archlinux-dev --workspace "$HOME/projects/shyft-work" --member dev
python3 -B tools/ai/arena.py status --arena shyft
python3 -B tools/ai/arena.py ssh --arena shyft --member dev

Expected: preparation reports selections archlinux-dev, archlinux-squid and caddy. Gateways builds Arch Squid and acquires registry.access.redhat.com/hi/caddy:latest unmodified. Create validates the recorded immutable local images, allocates networking/loopback SSH, installs managed source Quadlets and starts services. It never pulls or builds.

Status distinguishes saved configuration from running services and reports local gateway health. The last command opens a pinned SSH session as ci; continue with step 3 there. Local gateway health does not prove upstream authentication or model readiness. An identical create rerun retains keys/work and reconciles state; identity/configuration conflicts are refused, not overwritten. Mutating arena commands support --dry-run without mutation or secret input.

2. Alternative: prepare a local source on the trusted host

This is a substitution before first create, not an extra step inside SSH. Replace the Arch preparation line above with this trusted host shell command:

bash tools/ai/build.sh prepare archlinux-dev \
  --source localhost/archlinux-dev:next --name local-dev

Then use --images local-dev in create. Local input is inspected and used directly without registry access or invented registry provenance. Package installation can still need distribution repositories unless prepared explicitly offline. See Image preparation for offline preparation and the Fedora preparation branch.

3. SSH session as ci: create files with an agent and test them

This is an explicit real-provider action: it sends task data to the configured inference provider and can incur charges. Use only permitted task material. The demonstration creates a disposable subdirectory in the mounted workspace:

cd /home/ci/workspace
DEMO=$(mktemp -d ./agent-demo.XXXXXX)
cd "$DEMO"
/opt/ai-agents/runtime.sh opencode --format json \
  'Create add.py with add(a, b).
 Create test_add.py using unittest: add(2, 3) == 5 and add(-2, 2) == 0.
 Run python3 -m unittest -v. Report the test result and files changed.'
ls add.py test_add.py
python3 -m unittest -v

Expected: add.py and test_add.py exist and the user-run unittest passes. A text response alone is not file-tool success. The launcher selects the installed supported OpenCode profile; do not replace its broker configuration. Local-mock file/exec evidence is separate from real-provider acceptance. No inference runs automatically during create or status. An upstream failure does not broaden egress; stop and consult Arena troubleshooting and known issues.

B. Refresh images in an arena

Return to the trusted host shell in the tooling checkout. Build refresh prepares a new image and retains the previous one. Arena refresh deliberately deploys the prepared immutable identity; it does not build or pull.

bash tools/ai/build.sh refresh archlinux-dev
python3 -B tools/ai/arena.py refresh --arena shyft \
  --member dev --images archlinux-dev --dry-run
python3 -B tools/ai/arena.py refresh --arena shyft \
  --member dev --images archlinux-dev --stop-running

Expected: the dry-run identifies affected services and old/new identities. An unchanged identity is a no-op. A changed image with running affected services requires --stop-running; the example explicitly permits that interruption. Member SSH sessions and processes stop. Saved mounts, keys, addresses and initialized runtime/cache state persist; processes and unsaved buffers do not. Stop independent host writers separately and preserve valuable work independently.

Image rollback — trusted host shell: restore the previous local identity:

python3 -B tools/ai/arena.py refresh --arena shyft --member dev \
  --rollback --stop-running

Image rollback does not roll back persistent data or state migrations. Retained local images must remain available; see Arena administration reference for compatibility and recovery limits.

Gateway refresh — trusted host shell: prepare, then deploy explicitly:

bash tools/ai/build.sh gateways --refresh
python3 -B tools/ai/arena.py refresh --arena shyft --gateways --stop-running

Expected: policy and secret references remain unchanged. Gateway refresh temporarily interrupts inference for every member; local member SSH remains independent of upstream readiness. For the local-source example, prepare with refresh archlinux-dev --name local-dev and deploy with --images local-dev.

C. Add another member

First prepare fedora44-scripting with its verified local agent bundles. Then run in the trusted host shell:

mkdir -p "$HOME/projects/analysis"
python3 -B tools/ai/arena.py add --arena shyft --member analysis \
  --images fedora44-scripting --workspace "$HOME/projects/analysis"
python3 -B tools/ai/arena.py ssh --arena shyft --member analysis

Expected: add allocates a separate address/loopback port, SSH identity and private state; scripting disables the development compiler cache. Existing members and gateways are not restarted. The last command enters the new member’s SSH session as ci. Identical input preserves state; conflicting input fails. Use --dry-run to inspect the addition before deployment.

Members in the same arena are mutually reachable and share a trust domain; add is not tenant isolation. Use another arena for a different trust domain, while remembering that arenas on the same host still share its kernel.

D. Remove and recreate an arena

Return to the trusted host shell. Review the removal plan before continuing:

python3 -B tools/ai/arena.py remove --arena shyft --dry-run
python3 -B tools/ai/arena.py remove --arena shyft
python3 -B tools/ai/arena.py status --arena shyft
python3 -B tools/ai/arena.py create shyft --retained
python3 -B tools/ai/arena.py ssh --arena shyft --member dev

Expected: remove stops/removes only the owned deployment and status records it as removed. Work/data, runtime/cache, SSH keys, images, selections, secrets and operation records remain. Repeated removal is safe. --retained recreates every saved member using saved configuration, immutable images and existing keys/state where available; it does not select newer images or recopy initialized seeds.

Missing retained inputs or ownership conflicts require deliberate recovery, not replacement or forced deletion. See Arena administration reference for optional owned-secret removal and partial-failure recovery. The last command reconnects to SSH as ci; removal/recreation does not restore stopped processes.

What to check and when to stop

  • Stop at a failed prerequisite, identity mismatch, configuration conflict or unavailable inspection. Do not overwrite state, bypass validation or widen network/mount access. Failed operations can be partial; inspect diagnostics and follow Arena administration reference before retrying identical input.

  • Check status and actual files/test results. Local SSH and default-deny gateway health are separate from real-provider readiness. Consult Known issues and assurance limits for agent and bridge-service blockers; bounded checks in Bounded security verification are not certification.

  • Before acceptance, stop the execution member and independent writers. Review returned files as untrusted input outside the arena, following AI-assisted work. Persistence is not a backup. Human acceptance, signing, publication and production integration remain outside agent authority.

References and known issues

Use these references for details rather than expanding the CLI recipe:

Image inputs/provenance, administration, bounded verification and troubleshooting remain separate topics. Optional IDE provisioning and named members is an optional provisioning extension, not a CLI prerequisite; ordinary arena.py add does not expose IDE backend/seed options. Lifecycle regressions and manual checks do not establish independent security review or full containment.