swarmy-iris-cli
v0.3.0
Published
CLI for IRIS — manage tokens, profiles, containers, run agent tasks from the shell, and tunnel local services into the container for FE+BE preview testing.
Maintainers
Readme
swarmy-iris-cli
Command-line client for IRIS — a self-hosted browser runtime for AI agents. Provision real Chrome containers, snapshot profiles, and run agent tasks from your shell.
This is the third wrapper around the IRIS manager API, alongside the SSE endpoint and the swarmy-iris-mcp server. Use this CLI when you want to drive IRIS interactively or from a shell script (humans + AI agents both welcome).
Install
npm install -g swarmy-iris-cliThe install puts a swarmy-iris-cli binary on your PATH.
Sign in
The recommended way to authenticate swarmy-iris-cli for a human user is swarmy-iris-cli login. It pairs your machine with the manager via a one-time browser approval.
swarmy-iris-cli login --url https://swarmy.firsttofly.comWhat happens:
> Registered device 'khoa-mbp.local' on khoa-mbp.local.
> Open this URL to approve in your browser:
https://swarmy.firsttofly.com/settings/devices?pending=dev_…
> Waiting for approval (15 min)...
> Waiting for approval (14:32 remaining)...swarmy-iris-cli login opens the URL in your default browser; if that fails (headless env, no xdg-open), copy-paste the printed URL into any signed-in browser, then approve. Once you click Approve, the CLI receives a dev_… token and writes ~/.config/swarmy-iris-cli/credentials (mode 0600).
swarmy-iris-cli login --name "my-laptop" # override the device label
swarmy-iris-cli login # re-uses the URL from $IRIS_URL
# or the credentials filePress Ctrl-C to cancel; the pending device expires server-side after 15 minutes anyway.
Sign out
swarmy-iris-cli logout # revokes the device on the server
# AND deletes the local credentials
swarmy-iris-cli logout --keep-server-side # local-only (when the server is offline)Running swarmy-iris-cli logout while already logged out is a no-op (Not logged in., exit 0). For swm_* API tokens, swarmy-iris-cli logout does NOT revoke them server-side — those are managed in the web UI's Settings page; only the local credentials file is cleared.
Configure
swarmy-iris-cli resolves auth in this priority order:
- CLI flags —
swarmy-iris-cli --url https://... --token swm_... <command> - Environment —
export IRIS_URL=...; export IRIS_TOKEN=... - Credentials file —
~/.config/swarmy-iris-cli/credentials, written byswarmy-iris-cli login
For headless agents that don't have a human to approve a device, mint a long-lived API token at <IRIS_URL>/settings → API Tokens and use it via IRIS_TOKEN or --token.
Quick examples
# Verify your token works
swarmy-iris-cli whoami
# List visible profiles (private + shared)
swarmy-iris-cli profile list
# Run a task — final answer prints to stdout, progress to stderr
swarmy-iris-cli run "Use swarmy-chrome-agent to navigate to https://example.com and print the page heading as the last line." \
--profile claude-default-latest
# JSON-only output, suitable for `jq`
swarmy-iris-cli run "..." --profile claude-default-latest --json | jq -r .result
# Capture a final screenshot + MP4 of the run
swarmy-iris-cli run "..." --profile claude-default-latest \
--final-screenshot --final-video --json | jq '{result, captures}'
# Pull the captured artifacts (the URL paths are returned in .captures)
RUN=$(swarmy-iris-cli run "..." --profile claude-default-latest \
--final-screenshot --final-video --json | jq -r .run_id)
curl -o final.mp4 -H "Authorization: Bearer $IRIS_TOKEN" \
"$IRIS_URL/api/captures/$RUN/final.mp4"
# Snapshot a running container's Chrome state into a new profile
swarmy-iris-cli profile snapshot --container 8e91d2a4-... --name "my-saved-state"
# Force-stop a container (bypasses the warm pool)
swarmy-iris-cli container delete 8e91d2a4-... --force --yesTest your local app
swarmy-iris-cli test exposes one or more local TCP ports through the manager
to a remote worker container, then runs an agent task that can reach them at
http://localhost:<port> natively. The agent's Chrome inside the container
sees http://localhost:3000 and dials back to your laptop's localhost:3000
through a manager-mediated WebSocket relay — your existing CORS allowlist
keeps working unchanged.
# FE + BE common case — agent drives Chrome against your local stack
swarmy-iris-cli test \
--expose 3000 \
--expose 8000 \
--profile my-test-user \
--then "Open http://localhost:3000, log in, verify the dashboard loads"
# Remap if the worker host already binds 3000
swarmy-iris-cli test --expose 13000:3000 --profile p --then "..."--expose 3000— same port both sides--expose 13000:3000— worker listens on 13000, agent seeslocalhost:3000- Up to 8
--exposeflags per session; one tunnel per container - HTTP works out of the box. For HTTPS dev servers, generate a cert with
mkcert and trust your local CA
inside your environment —
--trust-certis not in v1 - The CLI enforces a port allowlist on every dial — only the userPorts you
explicitly named here can be reached on your loopback. A buggy or
compromised worker can't probe your
localhost:22/:6379/:5432 - Dial target hardcoded to
127.0.0.1(with::1fallback for IPv6-only dev servers). Loopback resolution does NOT consult DNS, so a hostile resolver can't redirect the rendezvous off-host
Exit codes match run (0 ok, 1 error, 2 blocked, 3 transport).
Exit codes for swarmy-iris-cli run
swarmy-iris-cli run is the killer feature for shell scripts. Its exit code tells you what happened:
| Exit | Meaning |
| ---- | ---------------------------------------------------------- |
| 0 | Success — the agent returned a result event then done. |
| 1 | Error — agent emitted an error event for any reason. |
| 2 | Blocked — human intervention needed (captcha / login). The container stays alive; resume with --container-id. |
| 3 | Transport / config error — bad URL, missing token, network failure, etc. The agent never ran. |
Use this to branch in shell:
swarmy-iris-cli run "$task" --profile claude-default-latest --json > out.json
case $? in
0) jq -r .result out.json ;;
2) echo "Open $(jq -r .blocked.vnc_url out.json) and resolve the block, then re-run with --container-id $(jq -r .container_id out.json)." ;;
*) echo "Failed: $(jq -r .error.message out.json)"; exit 1 ;;
esacAI-agent friendliness
Humans use swarmy-iris-cli login; headless agents typically use a long-lived API token. The minimum an agent needs:
- Set
IRIS_TOKEN(aswm_…API token from Settings) andIRIS_URLin env. - Run
swarmy-iris-cli run "<task>" --profile <name> --json. - Parse stdout as JSON:
{ container_id, result?, blocked?, error? }. - Check the exit code:
0→ useresultas the answer.2→ ask a human to openblocked.vnc_url, then retry with--container-id <container_id>.1→ useerror.messageanderror.codeto decide retry vs surface.3→ check your token / URL, this isn't a task failure.
The --json mode is single-shot: one JSON object printed once the stream ends. Don't try to stream-parse it line by line.
Commands
Run swarmy-iris-cli <command> --help for per-command help.
| Command | What it does |
| ---------------------------------------------- | ------------------------------------------------------------------ |
| swarmy-iris-cli login [--url URL] [--name NAME] | Pair this device with the manager (sign in). |
| swarmy-iris-cli logout [--keep-server-side] | Revoke this device and clear local credentials. |
| swarmy-iris-cli whoami | Validates the token and prints the resolved user. |
| swarmy-iris-cli token list | Lists API tokens (firebase auth only — see note below). |
| swarmy-iris-cli token create --name NAME | Mints a token (one-time reveal). |
| swarmy-iris-cli token revoke <id> | Revokes a token. |
| swarmy-iris-cli profile list | Lists visible profiles (private + shared). |
| swarmy-iris-cli profile snapshot --container ID --name N | Snapshots a container's Chrome state into a new profile. |
| swarmy-iris-cli profile delete <id> | Deletes a profile (owner only). |
| swarmy-iris-cli container delete <id> | Stops or releases-to-pool a container. |
| swarmy-iris-cli run "<instruction>" | Runs an agent task. See exit-code table above. Add --keyframes, --final-screenshot, --final-video, --final-video-max-seconds N to capture screenshots / MP4 of the run; URLs land in --json output under .captures / .capture_events and on stderr. |
| swarmy-iris-cli test --expose PORT --then "<task>" | Runs an agent task with one or more local ports exposed to the in-container browser through a manager-mediated WS relay. Agent sees http://localhost:<port> natively (CORS works unchanged). See "Test your local app" above. |
Known constraints
swarmy-iris-cli container listnot implemented — the manager has noGET /api/containerslisting endpoint yet. Use the web UI's container page instead.swarmy-iris-cli token list/create/revokerequires a Firebase ID token — the manager scopes/api/api-tokensto Firebase auth (deliberately: agents can't mint tokens for themselves). With aswm_ordev_token you'll get a 401. Manage tokens via the web UI's Settings page.
Links
- Full IRIS docs: https://swarmy.firsttofly.com/help.html
- SSE endpoint reference:
docs/agent-sse-endpoint.md - OpenAPI spec:
manager/docs/agent-openapi.yaml - MCP server (alternative):
mcp/iris-mcp/
