Skip to content

evershell CLI

evershell is a single static binary that wraps the Evershell control plane API for shell-friendly automation. Install it once, run evershell login, and every verb thereafter reads credentials from ~/.config/evershell/credentials (or EVERSHELL_API_KEY + EVERSHELL_SLUG env vars).

Pre-built binaries for macOS, Linux, and Windows live at downloads.evershell.ai. The latest/ path always serves the most recent release — pick the archive that matches your machine, extract, and put evershell on your $PATH:

Terminal window
# macOS (Apple Silicon)
curl -L https://downloads.evershell.ai/evershell/latest/evershell_darwin_arm64.tar.gz | tar -xz
sudo mv evershell /usr/local/bin/
# Linux (amd64)
curl -L https://downloads.evershell.ai/evershell/latest/evershell_linux_amd64.tar.gz | tar -xz
sudo mv evershell /usr/local/bin/
# Windows (amd64) — download the zip from the same URL pattern,
# unzip, and put evershell.exe somewhere on %PATH%.

Available platforms: macOS (darwin_amd64, darwin_arm64), Linux (linux_amd64, linux_arm64), Windows (windows_amd64).

The latest/ mirror always points at the newest release. To pin, swap latest for an exact version (e.g. v0.2.0):

Terminal window
curl -L https://downloads.evershell.ai/evershell/v0.2.0/evershell_0.2.0_darwin_arm64.tar.gz | tar -xz

Every released version is listed in the manifest at https://downloads.evershell.ai/evershell/versions.json:

{
"latest": "0.2.0",
"versions": ["0.2.0", "0.1.0"]
}

A Homebrew tap is on the roadmap — once it ships you’ll be able to brew install evershell. Until then, curl is the install path.

Every release includes a checksums.txt listing SHA-256 hashes:

Terminal window
curl -L https://downloads.evershell.ai/evershell/latest/checksums.txt
sha256sum -c checksums.txt --ignore-missing
Terminal window
evershell login --slug=acme
# Prompts for API key (issued from Settings → API keys in the console)
# Or pass the key directly via flag or stdin:
evershell login --slug=acme --api-key sk_live_...
echo "sk_live_..." | evershell login --slug=acme --api-key -

The CLI verifies the credential against /v1/me/session before persisting. Failed auth surfaces a friendly error instead of writing a broken credentials file.

For CI / unattended environments, skip login entirely:

Terminal window
export EVERSHELL_SLUG=acme
export EVERSHELL_API_KEY=sk_live_...
evershell ps

Env vars take precedence over the credentials file when both are set — handy for one-off overrides during testing.

Run evershell <verb> --help for the full flag list. Each verb below declares the permission scope it needs; see the permissions reference for what each one gates and which scopes every default role holds.

Permissions: workspace:read or workspace:read:own.

Terminal window
evershell ps # active workspaces
evershell ps --include-archived # include archived
evershell ps --role analyst # filter to one agent role by name
evershell ps -o json | jq . # machine-readable

--role <name> resolves the role server-side and 404s with role_not_found if the name doesn’t match — silent empties would hide typos. Each row shows the workspace’s role_id, not the role’s name (workspace rows don’t carry either the name or the display name).

evershell run — create a workspace and submit the first task

Section titled “evershell run — create a workspace and submit the first task”

Permissions: (workspace:write or workspace:write:own) and (tasks:write or tasks:write:own).

Terminal window
evershell run analyst "summarize Q3 revenue"
# Workspace ws_01HZ created, task task_01HZ submitted.
# Follow with: evershell logs ws_01HZ

Optional overrides:

Terminal window
evershell run analyst "..." \
--environment staging \
--thinking-effort high \
--max-continuations 10

Scheduled invocations. evershell run is a regular CLI command — schedule it from your OS’s scheduler (cron, launchd, systemd timers):

# nightly CVE triage at 03:00 local
0 3 * * * /usr/local/bin/evershell run secops "triage today's CVE feed"
# every Monday morning — weekly metrics writeup
0 8 * * 1 /usr/local/bin/evershell run analyst "compile last week's metrics"

evershell logs — tail a workspace’s activity stream

Section titled “evershell logs — tail a workspace’s activity stream”

Permissions: workspace:read or workspace:read:own.

Terminal window
evershell logs ws_01HZ # follow (default — SSE stream)
evershell logs ws_01HZ --no-follow # print history once and exit
evershell logs ws_01HZ -o json # JSON-per-event for piping to jq

History mode supports the same paging flags as evershell audit. Passing any of them auto-implies --no-follow (paging only applies to the history endpoint, not to the live SSE stream):

Terminal window
# Single page, capped at 100 by default
evershell logs ws_01HZ --limit 500
# Auto-paginate the full activity history
evershell logs ws_01HZ --all -o json | jq '.events | length'
# Resume from where a previous page left off
evershell logs ws_01HZ --cursor "2026-05-23T12:34:56.789Z|01HZABCD..."
# Reverse chronology (default is asc — chronological)
evershell logs ws_01HZ --order desc --limit 50

Permissions: workspace:write or workspace:write:own.

Terminal window
evershell stop ws_01HZ
# Workspace ws_01HZ: stopped.

State is snapshotted before pod tear-down — resume later via the console or by submitting a new task. Stopping an already-stopped workspace returns 409 workspace_already_stopped; guard your callers if you want a no-op on repeat invocations.

Permissions: audit:read or audit:read:own. With --workspace, additionally requires workspace:read or workspace:read:own (creator-match) on the target workspace.

Filters compose AND across columns. Each --filter value supports equality (col=val), IN (col=v1,v2), not-equal (col!=val), and “column populated” (col!=).

Terminal window
# Every deny in the last hour
evershell audit --filter event_type=policy_decision --filter decision=deny \
--from "$(date -u -d '1 hour ago' +%FT%TZ)"
# A bounded window
evershell audit --from 2026-05-01T00:00:00Z --to 2026-05-02T00:00:00Z
# Pipe to jq for richer querying
evershell audit -o json --filter category=audit | jq '.events[].event_type' | sort | uniq -c
# Auto-paginate through every result page (no manual cursor passing).
# JSON output still wraps in `{events, cursor}` so the same jq selector
# works whether you pass --all or not.
evershell audit -o json --all --filter category=audit | jq '.events | length'
# Workspace-scoped — every actor's events on this workspace, not just
# yours. The user-id narrowing that bare `evershell audit` applies for
# audit:read:own callers is skipped on this route, so a Member who
# owns the workspace (or holds workspace:read) sees every event that
# affected it.
evershell audit --workspace ws_01HZ --all

Results larger than one page (--limit, default 100) come back with a cursor field — pass it back as --cursor <value> for the next page, or --all to auto-paginate from the start.

--workspace <id> routes to /v1/workspaces/{id}/audit instead of /v1/audit. The two endpoints share filter columns, paging, and response shape; they differ in scoping. Bare evershell audit is the org-wide view, narrowed by user_id for audit:read:own callers. evershell audit --workspace <id> is the workspace view — no user_id narrowing, so a Member investigating their own workspace sees the same row set an Owner would.

See Audit events for the full event-type catalog and filter column whitelist.

evershell files — inspect / extract workspace files

Section titled “evershell files — inspect / extract workspace files”

Permissions: workspace:read or workspace:read:own.

Terminal window
evershell files ls ws_01HZ # every entry in the sandbox tree
evershell files cat ws_01HZ /logs/run.log
# Truncated at 512 KB by default — for big files use get, or
# raise the cap inline:
evershell files cat ws_01HZ /logs/run.log --max-bytes 2097152
# Binary files print a "use evershell files get" hint to stderr
# instead of dumping bytes that would clobber the terminal.
evershell files get ws_01HZ /reports/q3.csv ./local.csv
# Wrote 14823 bytes to ./local.csv
# Local path is optional — defaults to the remote basename in CWD:
evershell files get ws_01HZ /reports/q3.csv
# Wrote 14823 bytes to ./q3.csv
# Pass `-` as the local path to stream stdout (binary-safe, uncapped):
evershell files get ws_01HZ /artifacts/build.tar.gz - | tar -xz
# Read from a stopped workspace's snapshot instead of live sandbox:
evershell files ls ws_01HZ --from snapshot
evershell files get ws_01HZ /artifacts/build.tar.gz . --from snapshot

evershell files cat truncates at 512 KB by default (override with --max-bytes <N>) and is text-friendly: binary files print a hint to stderr rather than dumping raw bytes. evershell files get streams without a size cap and is safe for binaries. The --from snapshot flag works on all three sub-commands and reads from the stopped-workspace snapshot instead of the live sandbox.

evershell caps validate / evershell caps compile

Section titled “evershell caps validate / evershell caps compile”

Permissions: none — runs locally, no network or auth.

Local validation of caps.yaml against the same parser the control plane uses at agent-role create time. Runs in CI / pre-commit hooks.

Terminal window
evershell caps validate ./caps.yaml
# caps.yaml: OK (3 capabilities)
evershell caps validate ./caps.yaml --strict
# Upgrade warnings to errors. Exit 2 on either errors or warnings.
evershell caps compile ./caps.yaml > policy.rego
# Print the OPA Rego the proxy would enforce.

Both verbs accept - for stdin so cat caps.yaml | evershell caps validate - works in piped flows.

evershell version / evershell upgrade — self-update

Section titled “evershell version / evershell upgrade — self-update”

Permissions: none — talks to the public release bucket, not the control plane.

Terminal window
evershell version # current version + platform; "vX available" hint
evershell version --no-check # skip the manifest fetch (offline / CI)
evershell upgrade # download + verify + atomically replace
evershell upgrade --check # print the upgrade plan; don't touch disk
evershell upgrade --to 0.2.0 # pin to a specific version (rollback)

evershell upgrade walks the same pipeline curl | tar -xz does manually: fetches the release manifest, verifies the archive’s SHA-256 against the published checksums.txt, extracts the binary, and atomically replaces the running executable.

Self-upgrade is POSIX-only — on Windows the command refuses with a “download manually” message that includes the right URL. Permission errors on the install directory (e.g. /usr/local/bin owned by root) print a sudo hint.

Set EVERSHELL_UPGRADE_URL to point the upgrader at a staging bucket or air-gapped mirror; default is https://downloads.evershell.ai/evershell.

After any successful command, evershell prints a one-line (evershell vX available — run evershell upgrade to install.) hint to stderr when a newer release is out. The check is rate-limited to one network round-trip per 24h (cached in ~/.config/evershell/update-check.json) and silently skipped when:

  • EVERSHELL_NO_UPDATE_CHECK=1 is set
  • --output json is in effect (avoids polluting machine-readable pipelines)
  • The running binary is a dev build
  • The command was evershell version or evershell upgrade (already redundant)
  • The manifest fetch fails (errors swallowed — a flaky network must never fail your command)

Homebrew installs are detected — if the resolved binary lives inside a Cellar/ path, evershell upgrade refuses with a redirect to brew upgrade evershell so brew’s package tracking stays consistent.

evershell orgs — list / switch between organizations

Section titled “evershell orgs — list / switch between organizations”

Permissions: any signed-in caller (reads from /v1/me/session).

Terminal window
evershell orgs list
# SLUG ORG NAME ROLE BILLING
# * acme Acme Corp owner active
# contoso Contoso member active
evershell orgs switch contoso
# Switched to contoso. Credentials updated at ~/.config/evershell/credentials.

Note: API keys are org-scoped — switching slugs only works if the saved key was minted for the destination org. Most workflows call evershell login against each org separately instead.

Env varEffect
EVERSHELL_SLUGTenant subdomain. Wins over the saved file.
EVERSHELL_API_KEYAPI key. Wins over the saved file.
EVERSHELL_API_URLFull base URL override. Skips slug → DNS resolution. Useful for pointing the CLI at a non-default endpoint (custom domain, internal mirror).
EVERSHELL_UPGRADE_URLOverride the release bucket evershell upgrade pulls from. Default https://downloads.evershell.ai/evershell.
EVERSHELL_NO_UPDATE_CHECKWhen set to 1, suppresses the manifest fetch on evershell version.

The credentials file is plain JSON at ~/.config/evershell/credentials with mode 0600. (Honors XDG_CONFIG_HOME if you’ve set the XDG Base Directory env var.)

Conventions match common lint tools (eslint, ruff, shellcheck):

CodeMeaning
0Success
1Command failed — network error, server-side error, missing arg, or caps validate found warnings (no errors)
2caps validate found errors (or warnings with --strict)

Exit 2 is reserved for caps validate; every other verb maps failures to exit 1 via Cobra’s default error handling.

Output goes to stdout in table form by default; pipe-friendly JSON via -o json. Errors and progress hints go to stderr.