CLI
Reference for the shard command line (@shardflux/cli 0.5.3, shardflux npm bundle 0.7.2). Account, sign-in, billing, workspaces, environment and exit codes.
Install
npm install -g @shardflux/cli
shard --helpOr run it without installing: npx @shardflux/cli --help. This page describes @shardflux/cli 0.5.3, which is
built on @shardflux/sdk 0.10.2 and needs Node.js 24 or later. A feature marked with a version, such as (0.5.0+),
is not in earlier releases.
From 0.5.0 shard does everything the console does, without a browser: create an account, sign in (with two-factor
authentication), set up an organization, project and API key, manage members, invitations and keys, buy or change a
plan, export data and delete an account. Before 0.5.0 it worked with a project API key only.
The unscoped shardflux package installs the same CLI as shardflux and shard. Install
one of the two packages globally, not both: both provide shard.
shard --help lists every command, grouped by the credential it uses, and every command and group has its own
--help. shard -V prints the CLI and SDK versions; shard version adds whether a newer shard exists (see
Updates):
shard 0.5.3 (@shardflux/sdk 0.10.2)
up to date: latest 0.5.3, checked 2026-10-01 09:00:00ZQuick start
No account yet (0.5.0+)? Everything happens in the terminal. A person only opens the emailed link (or hands it to
shard) and, for a paid plan, pays in Stripe Checkout.
printf '%s\n' "$PASSWORD" | shard auth register --email you@example.com --name "Ada Lovelace"
shard auth verify-email '<link from the verification email>'
printf '%s\n' "$PASSWORD" | shard auth login --email you@example.com
shard setup # organization, project and an API key, saved
shard workspaces open acme/demo --template python-node-browser
shard ws exec acme/demo -- python3 -c 'print(40 + 2)'
shard files write acme/demo /home/user/notes.txt --from notes.txt
shard files read acme/demo /home/user/notes.txt
shard ws suspend acme/demo --waitWith a key from the console instead, skip the account steps:
export SHARDFLUX_API_KEY=sfk_... # project API key from the console
shard login # verify the key: organization, project, tools
shard workspaces open acme/demo --template python-node-browserFor AI agents
shard is built to be driven by an agent: no browser, no prompts when standard input is not a terminal, --json on
every command, secrets only on standard input, and documented exit codes.
-
Account (0.5.0+).
printf '%s\n' "$PASSWORD" | shard auth register --email <email>answers the same whether or not the address exists. Ask the person for the link in the verification email and runshard auth verify-email '<link>'(the whole link, quoted). -
Sign in.
printf '%s\n' "$PASSWORD" | shard auth login --email <email> --json. With two-factor authentication it exits 4 withmfa_required: ask the person for the code, thenshard auth mfa --code <code>(within 10 minutes), or pass--codetoauth login. -
Set up.
shard setup --json: an organization, a project and an API key with every workspace tool, saved in the credentials file. It is idempotent: run it again any time. -
Work.
shard ws open <key> --template <slug> --json,shard ws exec <key> -- <command>andshard files ...use the saved key.eval "$(shard env)"exports it for the SDKs and the MCP server. -
A paid plan.
shard billing plans, thenshard billing upgrade <plan> --jsonprints the Stripe Checkout URL. Give it to the person, then runshard billing upgrade <plan> --wait(orshard billing status) until the plan is active. The API activates a plan only when Stripe confirms the payment. -
Sensitive actions (exports, deletions, two-factor and email changes) need a recent step-up:
printf '%s\n' "$PASSWORD" | shard auth step-up(add--code <code>with two-factor authentication; valid 10 minutes). Without a terminalsharddoes not ask: the command fails withstep_up_required(exit 4), and the hint names this command. -
Feedback (0.5.0+). While you work, send
shard feedbackthe moment something fails, confuses you or is missing, or your person is frustrated with Shardflux (see Feedback).
What stays with a person: reading the verification email, entering a card in Stripe Checkout, and the authenticator app's codes.
Feedback
(0.5.0+) shard feedback sends a message straight to the Shardflux founder, who reads every one. Coding agents
driving shard are asked to use it actively while they work, not once at the end. Send a short note the moment:
- something fails unexpectedly, an error or doc is unclear, an option is missing, or you needed a workaround;
- your user complains or is frustrated about Shardflux or the workflow around it (slowness, cost or limits, confusing setup, a missing feature, a workaround): paraphrase it, with what they were trying to do;
- your user asked for something Shardflux could not do, or made awkward.
Short and frequent beats polished: what you ran, what happened, what you expected, with the request id and error code of the failure. No need to ask first, but tell your user you sent it. Leave out private data about the user and secrets or code they did not mean to share; paraphrase, never paste transcripts.
shard feedback --category bug --request-id req-5c7744b2bb5c457b86b76101 --error-code capacity_unavailable \
"ws open failed twice in 10 min; expected a start within a minute"
shard feedback --category confusing \
"user was frustrated that ws open needs a template slug they had to look up; they expected a default"
npm test 2>&1 | tail -n 60 | shard feedback --category bug --workspace acme/demo --from-file -| Option | Meaning |
|---|---|
<message...> |
The remaining arguments joined with spaces, 1-8000 characters. Quote it, or put it after --, when it contains shell characters or words starting with -. |
--from-file <file|-> |
Read the message from a file, or standard input with - (for logs). Not together with a message argument. |
--category <c> |
bug (something failed or behaved wrongly), confusing (an error, doc, name or output was unclear), missing (a capability, option or template you needed), idea, praise or other (the default). |
--workspace <id|key> |
The workspace it is about. |
--request-id <id> |
The request_id of the error, so the logs can be found. |
--error-code <code> |
The error code seen, e.g. capacity_unavailable. |
--command <text> |
What you ran. |
- It sends with the project API key (any key; no tool permission), or, when no key is configured yet, with your
signed-in session, so it works while you are still setting up.
--agent-labelorSHARDFLUX_AGENT_LABELnames the reporting agent (e.g.claude-code);shardadds its own version as the client. - Output: one line with the feedback id.
Already receivedmeans the same message came from this key or user in the last 24 hours; it is not emailed again. With--json:{"id", "received_at", "duplicate"}. - It is rate limited: 10 per 10 minutes and 50 per day per key or user, 200 per day per organization
(
rate_limited, exit 1, with the wait in the hint). - Anything shaped like an API key, token or private key is redacted before the message is stored or emailed; leave other secrets out. If it cannot be sent, email shardflux@heliosone.fi.
- A failed command ends with a ready-made
feedback:line to fill in (see Output).
Environment
| Variable | Meaning |
|---|---|
SHARDFLUX_API_KEY |
Project API key (sfk_<key id>_<secret>) for the workspace commands. Default: the key shard setup saved (0.5.0+). |
SHARDFLUX_SESSION_TOKEN |
(0.5.0+) A person's CLI session (sfu_...) for the account commands. Default: the session shard auth login saved. |
SHARDFLUX_API_URL |
API base URL. Default https://api.shardflux.dev; --api-url overrides it. Plain http:// is allowed only for loopback hosts. Credentials are saved per API URL. |
SHARDFLUX_CONFIG_DIR |
(0.5.0+) Directory of credentials.json and update-check.json. Default $XDG_CONFIG_HOME/shardflux, else ~/.config/shardflux (%APPDATA%\shardflux on Windows). |
SHARDFLUX_NO_UPDATE_CHECK=1 |
(0.5.0+) Never ask whether a newer shard exists (also true, yes, on). NO_UPDATE_NOTIFIER=1 does the same. |
SHARDFLUX_AGENT_LABEL |
Attribution label for the tool tokens shard obtains. Default cli; --agent-label overrides it. Each label is one agent session, listed by shard ws sessions. |
SHARDFLUX_NO_WAKE=1 |
Do not resume a suspended workspace on use (same as --no-wake; --wake overrides it). |
SHARDFLUX_WAKE_TIMEOUT_MS |
Longest wait, in milliseconds, for a workspace to wake or finish a transition. Default 120000; --wake-timeout overrides it. |
SHARDFLUX_HTTP_KEEPALIVE=1 |
Reuse HTTP connections (see HTTP connections). |
BROWSER |
(0.5.0+) Program that --open runs with a URL. Default xdg-open, open (macOS) or rundll32 (Windows). |
shard never accepts a key, session or password as an argument (--api-key, --token, --password and similar
flags are refused with exit 2). It never prints the key or the session, except shard env, which prints the key on
purpose, and it redacts anything shaped like a key (sfk_...) or a session token (sfu_...) from error output.
Credentials file
Changed in 0.5.0: shard now stores credentials. Before 0.5.0 it stored nothing and read the key from
SHARDFLUX_API_KEY on every run. That still works and still wins. The file is written only by the commands that sign
in or save something: auth login, auth mfa, setup, api-keys create --save, orgs use, projects use,
invitations accept --use, and the session renewals of step-up, password and two-factor changes. shard login, the
key check, still stores nothing.
-
Where:
$SHARDFLUX_CONFIG_DIR/credentials.json, else$XDG_CONFIG_HOME/shardflux/, else~/.config/shardflux/(Windows:%APPDATA%\shardflux\). -
Protection: the directory is created with mode 0700 and the file 0600, written atomically (a temporary file, then a rename).
shardwarns when the file is readable by others. A file that is not valid JSON, or not this format, is never overwritten silently: commands that read it stop with exit 2 naming it, and a command that writes credentials first moves it tocredentials.json.corrupt-<time>. -
Profiles: one per API URL, so production, staging and a local API never mix. Each holds the session, the default organization and project, and the saved API key:
{"version": 1, "profiles": {"https://api.shardflux.dev": { "session": {"token": "sfu_...", "expires_at": "...", "user": {"id": "...", "email": "..."}, "state": "active"}, "organization_id": "...", "project_id": "...", "api_key": {"token": "sfk_...", "id": "...", "key_id": "...", "project_id": "...", "name": "shard-cli laptop"}}}} -
Precedence: the project API key is
SHARDFLUX_API_KEY, else the savedapi_key. The session isSHARDFLUX_SESSION_TOKEN, else the savedsession.shard auth logoutremoves the session (the key stays); delete the file to forget everything.
Global options
| Option | Meaning |
|---|---|
--api-url <url> |
API base URL (default $SHARDFLUX_API_URL, else https://api.shardflux.dev). |
--json |
Machine-readable JSON on stdout; errors as JSON on stderr. |
--agent-label <label> |
Attribution label for workspace tool tokens (default $SHARDFLUX_AGENT_LABEL, else cli). |
--wake, --no-wake |
Resume a suspended workspace when exec, files or changes use it (default), or fail with workspace_not_running. |
--wake-timeout <ms> |
Longest wait for a workspace to wake or finish a transition (default 120000); then exit 5. |
-h, --help |
Show help. |
-V, --version |
Print the version. |
Aliases: ws for workspaces, ops for operations, secret for secrets, template for templates, and
(0.5.0+) org/organizations for orgs, project for projects, keys/api-key for api-keys, member for
members, invite/invitation for invitations, volume for volumes. shard workspaces files ... and
shard workspaces operations ... also work.
Naming a workspace. <id|key> is tried as an id when it is a UUID. Otherwise, or if no workspace has that id, it
is matched as an exact workspace key across every lifetime and purpose, so sessions, drafts and test instances resolve
too. The live workspace wins over tombstones that ended sessions left with the same key.
Durations. --timeout takes a duration such as 90s, 5m or 30m.
Accounts and sign-in
(0.5.0+) These commands use a person's CLI session (sfu_...), which shard auth login saves.
printf '%s\n' "$PASSWORD" | shard auth register --email you@example.com [--name "Ada Lovelace"]
shard auth verify-email '<link from the email>' # or just the token in it
shard auth resend-verification # signed in, email not verified yet
printf '%s\n' "$PASSWORD" | shard auth login --email you@example.com [--code 123456 | --recovery-code X]
shard auth mfa --code 123456 # completes a sign-in that waits for its second factor
shard auth status # session and saved key, without secrets
shard auth sessions [--revoke <session-id>] # browser and CLI sessions
shard auth logout [--all]
printf '%s\n' "$PASSWORD" | shard auth step-up [--code 123456]
printf '%s\n%s\n' "$CURRENT" "$NEW" | shard auth password change
shard auth password reset --email you@example.com
printf '%s\n' "$NEW" | shard auth password reset-confirm '<link from the email>'
shard auth email change --email new@example.com # then: shard auth email confirm '<link>'
shard auth totp enroll # secret and otpauth:// URI for the authenticator app
shard auth totp confirm --code 123456 # prints recovery codes once
shard auth totp disable --code 123456
shard auth totp recovery-codes| Command | Options | Does |
|---|---|---|
shard auth register |
--email <email> (required), --name <name> |
Creates an account and emails a verification link. It answers the same whether or not the address exists. |
shard auth verify-email <link|token> |
Verifies the email address with the emailed link, or the token in it. | |
shard auth resend-verification |
Emails a new verification link (signed in, email not verified yet). That link also sets a new password: auth verify-email reads it from standard input (or asks), else prints the auth password reset-confirm command to run. |
|
shard auth login |
--email <email> (required), --code <code>, --recovery-code <code> |
Signs in and saves the session for this API URL. Then prints who you are, whether the email is verified, your organizations and the next step (shard setup, or shard auth verify-email). |
shard auth mfa |
--code <code>, --recovery-code <code> |
Completes a pending two-factor sign-in. |
shard auth status |
The session (user, verification, two-factor, expiry, step-up) and the saved API key, without secrets. | |
shard auth sessions |
--revoke <session-id> |
Your live sessions, browser and CLI, or revokes one. |
shard auth logout |
--all |
Ends the session and removes it from the credentials file; --all ends every session of the account. A saved API key stays. |
shard auth step-up |
--code <code>, --recovery-code <code> |
Confirms the password (and the code, with two-factor authentication) for sensitive actions, for 10 minutes. |
shard auth password change |
Current, then new password, from standard input lines or prompts. Other sessions end. | |
shard auth password reset |
--email <email> |
Emails a password reset link. |
shard auth password reset-confirm <link|token> |
Sets a new password (standard input or a prompt) with the emailed reset link. | |
shard auth email change |
--email <email> |
Sends a confirmation link to the new address (step-up). |
shard auth email confirm <link|token> |
Confirms the email change. | |
shard auth totp enroll |
Starts two-factor authentication: prints the secret and the otpauth:// URI for the authenticator app. |
|
shard auth totp confirm |
--code <code> |
Turns two-factor authentication on; prints the recovery codes once. |
shard auth totp disable |
--code <code>, --recovery-code <code> |
Turns two-factor authentication off (step-up first; the password from standard input or a prompt). |
shard auth totp recovery-codes |
Replaces the recovery codes; prints the new ones once. |
- Passwords never come from arguments (
--passwordis refused). On a terminalshardasks without echo (a new password twice); otherwise it reads standard input, one line per secret. Emailed links and tokens are single-use arguments; quote a link. Two-factor codes and recovery codes may be arguments. - Sessions.
auth loginsaves the session in the credentials file. It lasts 30 days from its last use and at most 90 days. Step-up, password changes and two-factor changes renew it, andshardsaves the new one at once. A saved session the API no longer accepts is removed, and the error says to sign in again. The person sees every CLI session in the console (Settings > Account & security) and can sign it out there. - Two-factor sign-in.
--codeor--recovery-code, or the code typed at the prompt. Without either (and without a terminal) the pending sign-in is saved andauth loginexits 4 withmfa_required;shard auth mfa --codecompletes it within 10 minutes. - Step-up. Exports, deletions, email changes and two-factor changes need the password again within the last 10
minutes. On a terminal
shardasks (and for a code with two-factor authentication) and retries once. Otherwise the command exits 4 withstep_up_required: runprintf '%s\n' "$PASSWORD" | shard auth step-upfirst (with two-factor authentication add--code, or pipe the code as the second line).
Setup
(0.5.0+) shard setup makes a signed-in account ready for the workspace commands:
- The organization:
--org, the saved default, or your only one. With none it creates "<your name>'s organization" (--org-nameto choose); with several it lists them. - The project:
--project, the saved default, or the organization's only one. With none it creates "Default" (--project-name). - An API key with every workspace tool (
--tool, repeatable, narrows it), namedshard-cli <hostname>(--key-name), saved in the credentials file and checked against the API.
It is idempotent: a saved key that still works is kept (--new-key makes a new one). It prints what it found or
created and the next command. The key is never printed; shard env prints it for tools that read SHARDFLUX_API_KEY
(the Python SDK, the MCP server, your own scripts):
eval "$(shard env)" # sh, bash, zsh
shard env --shell fish | source
shard env --shell powershell | Invoke-Expressionshard env prints the saved key and the API URL as export lines (set -gx for fish, $env: for PowerShell).
Organizations, projects, keys and members
(0.5.0+) Account commands work on the default organization and project: --org/--project (an id or a slug), else
the one saved by orgs use, projects use or setup, else the only one you have. With several and no default, the
usage error lists them.
shard orgs list | create <name> [--slug S] [--use] | get [org] | use <org>
shard orgs export [org] [--out file] # JSON, written 0600 (step-up)
shard orgs workspaces [org] [--project P] [--state S] [--all] # every project's workspaces, as the console lists them
shard orgs deletion [org] # what deleting would do, and what blocks it
shard orgs delete <org> --confirm <slug> --yes # irreversible (step-up)
shard projects list | create <name> [--slug S] [--use] | get <project> | use <project>
shard api-keys list | create <name> [--tool T]... [--read-only] [--expires 30d|90d|365d|never] [--save] | revoke <id|key_id> --yes
shard members list | set-role <user|email> <owner|admin|member|billing> | remove <user|email> --yes
shard invitations list | create <email> --role <role> | revoke <id|email> | accept '<link>' [--use]
shard templates publish <slug>@<version> | archive <slug>@<version>| Command | Does |
|---|---|
shard orgs list, get, use |
Your organizations and your role in each; one with its plan; the default for account commands. |
shard orgs create <name> |
Creates an organization; you become its owner. --use makes it the default. |
shard orgs workspaces [org] |
The organization's workspaces in every project, as the console lists them (--project, --state, --prefix, --lifetime, --purpose, --include-deleted, --all). |
shard orgs export [org] |
The organization's data as JSON, to a file (owners; step-up). |
shard orgs deletion [org], shard orgs delete <org> |
What deleting would do and what blocks it; the deletion itself (owners; step-up; --confirm <slug> --yes). An active subscription or an open checkout blocks it. |
shard projects list, create, get, use |
The organization's projects; creating one needs an owner or admin. |
shard api-keys list, create, revoke |
The project's API keys. create prints the new key once, alone on stdout (KEY=$(shard api-keys create ci)), with what it is on stderr; --save stores it in the credentials file instead of printing it. Revoking the saved key also removes it from the file. |
shard members list, set-role, remove |
Members and their roles: owner, admin, member or billing. remove yourself to leave. |
shard invitations list, create, revoke, accept |
Invitations by email (owners and admins). accept takes the emailed link; your verified email must be the invited one. |
shard templates publish, archive <slug>@<version> |
Publishes or archives a version of an organization template (owners and admins, signed in). The other template commands use the API key. |
With --json, api-keys create prints {api_key, secret, saved: false}, or {api_key, saved: true, credentials_file} with --save.
Billing
(0.5.0+)
shard billing plans # public: no sign-in needed
shard billing status # plan, billing state, period end, pending checkout
shard billing upgrade <plan> [--open] [--wait] [--timeout 15m]
shard billing portal [--open] # plan changes, payment methods, invoices, cancellation
shard billing invoices [--all]
shard billing alerts [--set 50,80,100 | --clear] # usage alert emails, percent of each allowance
shard billing overage [status | on --cap <dollars> | cap <dollars> | off] # (0.5.1+) opt-in overage and its spend capbilling overage is described in Usage and overage.
billing upgrade checks the plan against the public catalog (an unknown one lists the plans you can buy), starts
Stripe Checkout and prints its URL: a person pays there. --open also opens it in the default browser ($BROWSER,
else xdg-open, open or start; best effort). The API activates the plan only when Stripe confirms the payment, so
--wait polls until the subscription is active (exit 0), the checkout expires or is canceled (exit 6,
checkout_ended), or --timeout runs out (exit 5; the checkout stays open). An organization that already has a
subscription changes plans in the billing portal: the command prints the portal URL instead (exit 0). Buying a plan
needs an owner or billing member.
Audit, exports and account deletion
(0.5.0+)
shard audit list [--action api_key.] [--from 7d] [--to <time>] [--source app|cell_tool] [--outcome denied] [--all]
shard audit export [--format ndjson|csv] [--out file] [filters] # at most 90 days, 50 000 rows
shard account status # profile, memberships, deletion state
shard account export [--out file] # your data as JSON (step-up)
shard account delete --confirm you@example.com --yes # after a grace period (step-up)
shard account cancel-deletion--from and --to take an RFC 3339 time or a duration ago (90m, 24h, 7d, 2w). Files that shard writes for
exports are created with mode 0600 and never overwritten without --force. The audit log belongs to owners and
admins. Deleting the account is refused while you are the only owner of an organization with other members, or the
only member of one: transfer or delete those first (shard account status lists them).
Key, usage and version commands
These use the project API key: SHARDFLUX_API_KEY, else the key shard setup saved.
| Command | Does |
|---|---|
shard login |
Verifies the key and shows its organization, project and tool permissions. It stores nothing. |
shard whoami |
Shows the principal behind the key. |
shard usage [--org <organization-id>] |
Usage summary for the current period: plan, meters and allowances, and the overage block (0.5.1+). |
shard usage --estimate |
(0.5.0+) The bill so far and the projected use of each allowance, with the API's notes. |
shard usage --series |
(0.5.0+) Usage over time: --from, --to, --granularity hour|day, --meter <meter>. |
shard usage --workspace <id|key> |
(0.5.0+) One workspace's usage over time, with the same range options. |
shard version [--check] |
The CLI and SDK versions and the update status; --check asks the API now (see Updates). |
Workspaces
shard workspaces open
shard workspaces open <key> --template <slug> [options]Opens a workspace by key: creates it on first use, reconnects to or resumes it afterwards, never resets it. Waits
until the workspace is ready, the template's start commands and services included, unless --no-wait.
| Option | Meaning |
|---|---|
--template <slug> |
Template slug (required), for example python-node-browser. |
--secret <NAME> |
Bind this secret name (repeatable). Replaces the binding of an existing workspace; omit to leave it unchanged. |
--input <NAME=value> |
(0.4.0+) Text input of the template version (repeatable). Replaces the inputs of an existing workspace. Not for credentials: those are secret inputs. |
--input-file <file> |
(0.4.0+) NAME=value lines (# comments) or a JSON object. --input wins for a name in both. |
--lifetime <persistent|session> |
session: the workspace is discarded when the session ends (shard ws close or the idle timeout), and the key then opens a new one. Default: the template's default, else persistent. |
--cpu-millis <n>, --memory-mib <n>, --disk-gib <n> |
Caps in millicores, MiB and GiB. |
--mode <processful|file-first> |
(0.5.0+) file-first opens a file-first workspace (file_first works too). Default: processful for a new key, the stored mode for an existing one. With --lifetime session it is a usage error. |
--wait, --no-wait |
Wait until ready (default), or return at once. |
--timeout <duration> |
Give up waiting after this long (default 5m). The start continues server side. |
--timing |
Print where the time went (see Timing). |
Other workspace commands
| Command | Options | Does |
|---|---|---|
shard workspaces list |
--state <state>, --prefix <key-prefix>, --lifetime <persistent|session|any>, --purpose <standard|template_draft|template_test|any>, --include-deleted, --all, --limit <n> (1-200, default 50), --cursor <cursor> |
One page, or every page with --all. The next cursor is printed on stderr. By default only persistent standard workspaces. A file-first workspace reads running (file-first) (0.5.0+). |
shard workspaces get <id|key> |
One workspace (deleted ones included), with the startup of its template's start commands and services (0.4.0+), its mode and a file-first workspace's tree revision (0.5.0+), and a pending suspend when idle (0.5.1+). | |
shard workspaces inputs <id|key> |
(0.4.0+) The workspace's text inputs. | |
shard workspaces exec <id|key> -- <command> [args...] |
--cwd <dir> (an absolute path, default /home/user; a relative one is refused with invalid_cwd, exit 2), --env <K=V> (repeatable), --timeout <duration> (exit 124), --stdin <file|-> (max 1 MiB), -v / --verbose (0.5.0+), --execution-id <id> and --output-limit <bytes> (0.5.0+, file-first only), --timing |
Runs argv with no shell (use -- bash -lc "..." for shell syntax). Output is streamed and resumes from byte offsets after dropped connections. Exits with the command's exit code; Ctrl-C cancels the command. -v then prints the session id and exit status on stderr. On a file-first workspace the command runs as an execution instead (see File-first workspaces). (0.5.1+) A command that could not start (a --cwd that is not a directory, a program not on PATH) exits 6 with the workspace's reason and a hint; before 0.5.1 it exited 1 with no output. |
shard executions get <id|key> <execution-id> |
--wait <duration> |
(0.5.0+) A file-first workspace's execution (also shard workspaces executions get): its output, then what ran. Exits like exec; 5 while it still runs. |
shard workspaces suspend <id|key> |
--wait, --timeout <duration> (default 5m), --timing; --when-idle <duration> (30s to 1h) or --cancel-when-idle (0.5.1+) |
Suspends a running workspace (durable checkpoint). Returns at once unless --wait. --when-idle (0.5.1+) suspends it when idle instead: once it has been idle that long, counted from the later of its last work and the request; the next tool call or a resume cancels it, and a running command, attached stream or keepalive postpones it. --cancel-when-idle cancels that. Neither combines with --wait or --timeout (exit 2). --json prints {workspace, operation, suspend_request}. |
shard workspaces resume <id|key> |
--wait, --timeout, --timing |
Resumes a suspended workspace. |
shard workspaces fork <id|key> <new-key> |
--cpu-millis, --memory-mib, --disk-gib, --wait, --timeout, --timing |
Forks into a new key. |
shard workspaces delete <id|key> |
--yes (required), --wait, --timeout, --timing |
Deletes the workspace. Tool access ends at once; storage is cleaned up asynchronously; the key of a persistent workspace is never reused. |
shard workspaces close <id|key> |
--wait, --timeout, --timing |
Ends a session workspace now (it is deleted; the key then opens a new workspace). A persistent workspace is refused (not_session). |
shard workspaces reset <id|key> |
--yes (required), --wait, --timeout, --timing |
Layered workspaces: wipes every change and restarts on the template. Keeps key, id, template version, caps, secret bindings and volume attachments. The previous state stays restorable for 7 days. |
shard workspaces save-as-template <id|key> |
--template <slug> (required), --display-name <name>, --description <text>, --checkpoint <checkpoint-id>, --default-lifetime <persistent|session>, --default-idle-timeout <duration> (60s-24h), --acknowledge <path> (repeatable, up to 200), --auto-publish / --no-auto-publish, --wait, --timeout (default 30m) |
Saves a layered workspace as the next version of an organization template. --wait follows the build. |
shard workspaces changes <id|key> |
--path <prefix>, --hash, --summary, --all, --limit <n> (1-1000), --cursor <cursor>, --timing |
What a layered, running workspace changed against its template: added, modified, metadata (with --hash), deleted, replaced. |
shard workspaces sessions <id|key> |
Attributed agent sessions: label, principal and tokens issued. | |
shard workspaces secrets <id|key> |
--set <NAME> (repeatable), --clear |
Shows the secret names bound to the workspace and their status, or replaces them. Values are never shown. |
Files
| Command | Options | Does |
|---|---|---|
shard files read <id|key> <path> |
--out <file>, --timing |
Raw bytes to stdout, or to a local file. |
shard files write <id|key> <path> |
--from <file|-> (default -, standard input), --append, --parents / --no-parents, --if-revision <n> (0.5.0+, file-first only), --timing |
Atomic write, durable once acknowledged. Missing parent directories are created unless --no-parents. |
shard files ls <id|key> <path> |
--limit <n> (default 1000), --timing |
Directory listing. |
shard files stat <id|key> <path> |
--revision, --timing |
(0.5.0+) One path's metadata. --revision adds the content's SHA-256, the value --expected-revision takes. |
shard files search <id|key> <path> <pattern> |
--regex, -i / --ignore-case, --include <glob> and --exclude <glob> (repeatable), --max <n> (1-5000, default 200), --timing |
(0.5.0+) Searches file contents under a directory (or in one file): path:line:column: text per match. A search stopped early says why on stderr. --exclude replaces the default .git and node_modules exclusions. |
shard files patch <id|key> <path> |
--old <text> --new <text> (repeatable pairs), --replace-all, or --content-file <file|->; --expected-revision <sha256|absent>, --if-revision <n> (file-first only), --timing |
(0.5.0+) Replaces exact text (each --old must occur once unless --replace-all; in order, all or none), or the whole content, atomically. Prints the new revision. |
See Search and edit files for search, patches and revisions. files read, ls, stat and search
of a suspended workspace are answered from its disk without waking it (0.5.0+; files search notes it on stderr).
While the fleet is upgraded, a workspace on a host without search or patches gets host_feature_unavailable (exit 1,
not retried), with a hint naming another way.
File-first workspaces
(0.5.0+) A file-first workspace has no VM between commands; its state is a versioned file tree
under /home/user. Each shard ws exec runs the command as an execution: a fresh VM on the latest tree revision,
whose changed files become the next revision.
shard ws open acme/agent-7 --template python-node-browser --mode file-first
shard files write acme/agent-7 /home/user/app/main.py --from main.py # prints the new tree revision
shard ws exec acme/agent-7 -v -- python3 /home/user/app/main.py
shard ws exec acme/agent-7 --execution-id build-42 --timeout 10m -- bash -lc "make -C /home/user/app"
shard executions get acme/agent-7 build-42 # the recorded result, again- Output is printed when the command has ended, not streamed: stdout and stderr byte for byte.
--output-limit <bytes>keeps at most that much of each (default 1 MiB, at most 16 MiB). - Exit code: the command's own (124 timed out, 128+N killed by signal N). An execution that ended
failedorlostpublished nothing and exits 6, naming its reason and whether a new execution may succeed. -vprints on stderr, after the output, the execution id, its state and exit status, the tree revision before and after (1 -> 2),replayed, the timings and the changed paths (A,M,D; the first 100).--execution-id <id>is the execution's idempotency key (default a freshex-<uuid>): the same id with the same command returns the recorded result instead of running it again, so a script can repeat the call safely.shardsends the request again with the same id after a dropped connection and afterno_execution_host, and waits within--wake-timeoutwhile another execution holds the workspace.- Ctrl-C stops waiting (exit 130). An execution cannot be canceled;
shardprints theshard executions getcommand that fetches its result later. Results are kept for 7 days. - Tree revisions:
shard ws getshows the current one, andfiles writeandfiles patchprint the revision after their change.--if-revision <n>applies the change only while the tree is at revision n; otherwise nothing changes,shardexits 1 and the hint names the current revision. - Not in file-first mode:
workspaces suspend,resume,fork,reset,save-as-templateandchangesare refused without a request (not_supported_for_mode, exit 1).--execution-id,--output-limitand--if-revisionon a processful workspace are usage errors (exit 2). - Opening: the other mode for an existing key is
mode_mismatch(exit 1), a deployment without file-first workspaces answersmode_not_available(exit 2), and a template version without layered diskslayout_unsupported(exit 1). Each comes with a hint.
Operations
| Command | Options | Does |
|---|---|---|
shard operations list <id|key> |
--state <state>, --kind <kind>, --limit <n> (1-200, default 50) |
A workspace's operations, newest first. |
shard operations get <operation-id> |
One operation. | |
shard operations wait <operation-id> |
--timeout <duration> (default 5m), --timing |
Waits for an operation to finish: exit 0 succeeded, 6 failed or canceled, 5 timeout. |
Secrets
printf %s "$OPENAI_API_KEY" | shard secrets create OPENAI_API_KEY # value from standard input
shard secrets create DATABASE_URL --from-file ./database-url.txt # or from a file
shard ws open acme/demo --template python-node-browser --secret OPENAI_API_KEY --secret DATABASE_URL
shard ws exec acme/demo -- python3 agent.py # sees both as environment variables
shard ws secrets acme/demo # names and status, never values
printf %s "$NEW_KEY" | shard secrets rotate OPENAI_API_KEY| Command | Options | Does |
|---|---|---|
shard secrets create <name> |
--from-file <file>, --description <text>, --tool <tool> (repeatable; default exec and pty), --allow-workspace <workspace-id> (repeatable), --org <organization-id>, --allow-project <project-id> (repeatable), --all-projects |
Creates a secret. The value (UTF-8, up to 64 KiB) comes from standard input or --from-file, never from an argument. |
shard secrets list |
--org, --include-deleted, --all, --limit <n>, --cursor <cursor> |
Secret metadata; values are never shown. |
shard secrets get <id|name> |
--org |
One secret's metadata. |
shard secrets update <id|name> |
--org, --description, --tool, --allow-workspace, --any-workspace, --allow-project, --all-projects, --clear-projects |
Changes the description or usage permissions, from the next session start. |
shard secrets rotate <id|name> |
--org, --from-file <file> |
Stores a new value as the next version; older values are erased. |
shard secrets versions <id|name> |
--org, --limit <n> |
Versions, newest first. |
shard secrets delete <id|name> |
--org, --yes (required) |
Erases the values and removes the name from every workspace binding. |
shard secrets access-log <id|name> |
--org, --outcome <granted|denied|failed>, --workspace <workspace-id>, --limit <n> |
Which sessions resolved a secret. |
- Values are read only from standard input or
--from-file, with one trailing newline removed.--value,--passwordand similar flags are refused. - Secrets are project secrets of the API key's project by default.
--orgaddresses organization-wide secrets; those, andsecrets access-log, belong to organization owners and admins, so a project API key gets 403 (exit 4). <id|name>is tried as an id when it is a UUID, otherwise matched by name in the project (or the organization with--org).- A secret name that is unknown, or one the workspace may not use, is refused on open (exit 2,
secret_not_availablewith the names).
Egress and volumes
(0.5.0+) These use the project API key, like the other workspace commands.
shard egress get [--project <id> | --workspace <ws>]
shard egress set --file policy.json [--project <id> | --workspace <ws>] [--if-version N]
shard egress history [--project <id> | --workspace <ws>]
shard egress clear --workspace <ws>
shard volumes list [--include-org-shared] | create <name> --quota-gib N [--org-shared] | get <id|name>
shard volumes attach <ws> <volume> --mount /mnt/data [--read-only] | detach <ws> <volume>
shard volumes attachments <id|name> | delete <id|name> [--force] --yes- A policy file is
{"mode": "allow_all" | "allowlist" | "deny_all", "rules": [{"host": "api.github.com", "ports": [443]}], "cidrs": []}.egress get --workspacealso shows the enforcement;egress clearmakes the workspace follow the project policy again. - Volume commands wait until the cell has finished unless
--no-wait.volumes deleteis refused while the volume is attached unless--force.
Templates
Build a template from template.yaml
(0.4.0+) See Build a template for the recipe format.
shard templates init --base ubuntu-24.04 # writes template.yaml on the base's current version
shard templates languages --base ubuntu-24.04@1 # what build.languages offers there
shard templates packages search apt ffmpeg --base ubuntu-24.04@1
shard templates build template.yaml --slug acme-dev --wait --timing
shard templates test acme-dev@1 --input PROJECT_NAME=demo
shard templates build template.yaml --slug acme-dev --publish --wait
shard ws open acme/main --template acme-dev --input PROJECT_NAME=acme- Local
fromfiles and folders are uploaded first. Folders are packed as a reproducible tar (the same bytes the SDKs pack), and bytes the organization already has are not sent again. Progress lines go to stderr. - The version stays unpublished unless
--publish: try it withshard templates test <slug>@<version>. Without--slug, the slug is the name of the directory holding the file. --waitfollows the build until it is registered or fails (exit 6 when it failed or was canceled, 5 when--timeoutran out; the build continues). A host the build network refused is listed underdenied hosts: add it tobuild.network.extra_hostsand build again.- A file
shardcannot read or pack is refused before any request (exit 2). The API's refusals (upload_missing,language_unavailable,invalid_settings, ...) exit 2 with the reason. A storage refusal of an upload isupload_failed(exit 1).
Template commands
| Command | Options | Does |
|---|---|---|
shard templates list |
--owner <platform|organization>, --include-archived, --all, --limit <n>, --cursor <cursor> |
Templates the project can open, with their open version, layouts, file list state and draft. |
shard templates get <slug> |
--owner, --include-archived |
(0.4.0+) Versions, what open resolves to, and the open version's settings. |
shard templates init |
--base <slug[@version]> (required), --out <file> (default template.yaml), --force |
(0.4.0+) Writes a starter template.yaml on a base. |
shard templates build <file> |
--slug <slug>, --display-name <name>, --description <text>, --publish, --acknowledge <path> (repeatable, up to 200), --wait, --timeout <duration> (default 30m), --timing |
(0.4.0+) Builds a template from template.yaml. |
shard templates export <slug@version> |
--out <file>, --force, --owner |
(0.4.0+) The template.yaml a version was built from (exit 3 for a version without a recipe). |
shard templates test <slug@version> |
--instance-key <key>, --input <NAME=value>, --input-file <file>, --cpu-millis, --memory-mib, --disk-gib, --wait / --no-wait, --timeout (default 5m), --timing |
(0.4.0+) A test instance of a version, published or not: a session workspace that runs its start commands and services. End it with shard ws close <key>. |
shard templates builds list |
--template <slug>, --state <state>, --all, --limit, --cursor |
(0.4.0+) The organization's template builds, newest first. |
shard templates builds get <build-id> |
(0.4.0+) One build: state, registration, denied hosts, failure. | |
shard templates builds log <build-id> |
--out <file> |
(0.4.0+) A build's full log. |
shard templates builds cancel <build-id> |
(0.4.0+) Cancels a build (queued: at once; running: honoured until publishing starts). | |
shard templates languages |
--base <slug@version> (required) |
(0.4.0+) Languages and versions a base offers build.languages. |
shard templates packages search <apt|pip|npm> <query> |
--base <slug@version> (apt only, required there), --limit <n> (1-50, default 20) |
(0.4.0+) Package names for build.packages. |
shard templates files <slug> <version> [path] |
--stat, --owner, --all, --limit <n> (1-1000, default 200), --cursor |
One directory of a version's file tree, or one entry with --stat. |
shard templates diff <slug> |
--from <version|base> (required), --to <version> (required), --prefix <path>, --change <kind>, --owner, --all, --limit, --cursor |
Diff two versions: added, removed, changed, type_changed, metadata. |
Drafts
| Command | Options | Does |
|---|---|---|
shard templates draft open <slug> |
--base <slug@version>, --cpu-millis, --memory-mib, --disk-gib, --wait / --no-wait, --timeout, --timing |
Opens the template's draft, a layered workspace you edit with shard ws exec and shard files. One live draft per template. |
shard templates draft status <slug> |
The draft's workspace, base version, states and live test instances. | |
shard templates draft state <slug> |
--label <text>, --list, --wait, --timeout, --timing |
Captures a state of the running draft, or lists its states. |
shard templates draft test <slug> |
--state <state-id>, --instance-key <key>, --list, --include-ended, caps, --wait / --no-wait, --timeout, --timing |
Opens a test instance (a session on a copy of a state), or lists them. |
shard templates draft publish <slug> |
--state <state-id>, --description, --default-lifetime, --default-idle-timeout, --acknowledge, --auto-publish / --no-auto-publish, --wait, --timeout (default 30m) |
Publishes the draft as the template's next version. Refused (draft_stale) when the template got a version from elsewhere. |
shard templates draft discard <slug> |
--yes (required), --wait, --timeout, --timing |
Deletes the draft and ends its live test instances. |
Suspended workspaces
workspaces exec, files read|write|ls|stat|search|patch and workspaces changes wake a suspended workspace: they
resume it (or join the resume or open already running), wait until it runs, then run the request. A request made during
a suspend or resume waits for the transition. The request itself never runs twice, because the workspace refused it
before doing anything.
-
(0.5.0+) The wake is one request: the API holds the resume until the workspace runs and answers with the CLI's tool token.
shard ws resume --waitis the same request. -
(0.5.0+)
files read,ls,statandsearchof a suspended workspace whose disk a host still holds are answered from that disk without waking it: the files as they were at the suspend. -
A file-first workspace is never suspended, so none of this applies to it.
-
--wake-timeout <ms>bounds the wait. Past it,shardexits 5 and names the operation and its state. The operation continues server side:shard operations wait <id>keeps waiting. -
A resume or open that fails exits 6.
-
--no-wake(orSHARDFLUX_NO_WAKE=1) turns this off: a workspace that is not running is refused at once (exit 1,workspace_not_running).
Starts that wait for capacity
An open, resume or fork that no host can admit yet waits in capacity_pending for at most 15 minutes. If --timeout
ends first, the timeout error names the time the start gives up. A start still pending then fails with
capacity_unavailable: nothing was started, and a suspended workspace stays suspended. shard exits 6 as for any
failed operation, and the error says retryable=true with a hint to retry later:
error: Operation 01a0df37-b3a9-7a14-a3e7-11395c349c39 (open) failed: capacity_unavailable (no_ready_hosts) [code=operation_failed operation_id=01a0df37-b3a9-7a14-a3e7-11395c349c39 retryable=true]
hint: no host could admit it before its deadline; nothing was started. Retry later.shard does not retry it for you. A definitive failure has retryable=false.
Usage and overage
shard usage prints the current period's plan, meters and allowances. With opt-in overage
(0.5.1+), an allowance past its included amount while overage is on shows cap state overage, and a block follows:
the overage state, the spend cap, the charges of the cap, the date the cap is projected to be reached, and per
allowance the units past it and their amount.
overage accruing (usage past the allowances is charged on the next invoice)
spend cap $9.00 (at most $9.00, the plan price)
overage charges $3.00 of $9.00 (33.33%), $6.00 left; billed on the next invoice
cap reached 2026-09-29 15:02:46Z (projected at this period's average use)
OVERAGE UNIT PAST ALLOWANCE BILLED RATE AMOUNT
ram_gib_hours gib_hours 70 60 $0.04 $2.40
cpu_hours hours 5 5 $0.12 $0.60--json prints the API's summary, with spend_cap and exhausted_reason.
Owners and billing members turn overage on and set the cap with shard billing overage (0.5.1+, signed in with
shard auth login) or under Usage & billing in the console:
| Command | Does |
|---|---|
shard billing overage [status] |
The state (unavailable, off, on, paused), the spend cap and its range ($1 up to the plan price) and the rates. |
shard billing overage on [--cap <dollars>] |
Turns overage on. A cap is needed the first time, e.g. --cap 9 or --cap 9.50. |
shard billing overage cap <dollars> |
Changes the spend cap per billing period. |
shard billing overage off |
Turns overage off (always allowed; what it charged stays on the next invoice). |
They take --org <id|slug>, --json (the API's spend policy) and --if-version <n> (the policy version: a
concurrent change is refused with version_mismatch, exit 1). A refused change exits 2 with the API's reason and a hint
that names the bound: spend_cap_above_plan_price (the plan price), spend_cap_below_minimum ($1),
spend_cap_below_charges (what overage already charged this period), overage_unavailable (the plan has no overage)
or spend_cap_required (turning it on without a cap).
$ shard billing overage on --cap 9
Acme: overage is on, spend cap $9.00 per billing period ($1.00 to $9.00, the plan price).
Rates past the allowances: $0.04 per RAM GiB-hour, $0.12 per CPU-hour, charged on the next invoice (this period: shard usage).
Saved (policy version 1).While an allowance is used up, opens, resumes and forks are refused with 402 allowance_exhausted (exit 1). The error
names the reason, and a hint says what to do (0.5.1+):
| Reason | Hint |
|---|---|
allowance_used |
Upgrade (shard billing plans), or turn on overage: shard billing overage on --cap <dollars>. |
spend_cap_reached |
The spend cap is reached: raise it (shard billing overage cap <dollars>, at most the plan price) or upgrade. |
overage_paused |
A payment is past due: update the payment method (shard billing portal --open). |
Timing
--timing prints, on stderr after the call, the lifecycle timing the SDK measured. It is printed when the call fails,
times out or is interrupted too, before the error, and the exit code does not change.
$ shard ws open acme/demo --template python-node-browser --timing
Workspace acme/demo (01a0e5a8-3edd-74ba-b489-d62b8925e342) is ready.
...
open 34.18 s, succeeded (workspace 01a0e5a8-3edd-74ba-b489-d62b8925e342, operation 01a0e5a8-3ef0-7ecb-975e-dff2d5ca6e33)
client: request 20.01 s (held) → capacity_pending 13.52 s (no_ready_host) → running 0.59 s → view 42 ms ∥ token 61 ms
server: queued 33.40 s, ran 0.62 s, total 34.02 s; start warm, boot to ready 79 ms
outside the server: 0.16 s| Command | What is timed |
|---|---|
workspaces open, templates test, templates draft open|test |
The open, including the wait unless --no-wait. |
templates build |
Packing, uploads, the request and the wait, then the build's own queued and run time. |
workspaces suspend|resume|fork|delete|close|reset, templates draft state|discard |
With --wait, the request and the whole wait; without it, the request. |
operations wait |
The wait. |
workspaces exec, files read|write|ls|stat|search|patch, workspaces changes |
The wake, when the command had to wake a suspended workspace. Nothing is printed otherwise. |
workspaces exec on a file-first workspace (0.5.0+) |
The execution's own timings as the cell reports them; nothing is woken. |
With --json, stdout carries the timing as a timing field of the command's JSON instead: action, outcome,
workspace_id, operation_id, total_ms, phases, retries, server and outside_server_ms. It is null when
the command made no lifecycle call. On a failure the error document on stderr carries it: {"error": {...}, "timing": {...}}. shard does not stream progress while it waits.
Output
Human (default). Aligned tables and key/value blocks on stdout. Errors go to stderr as
error: <message> (<reason>) [code=... status=... request_id=... operation_id=...], with a hint when there is one. A
failed operation adds retryable=true|false. (0.5.0+) An unexpected failure ends with a line that reports it:
feedback: shard feedback --category bug --request-id <id> --error-code <code> "<what you expected>". The expected
flow has none: usage and validation errors, Ctrl-C, a missing or refused credential, a sign-in or step-up to finish, a
wait that gave up, and refusals whose hint names the next step (a stale revision, an edit that does not match, a mode
the workspace lacks).
--json. stdout carries the API's own objects:
| Command | JSON on stdout |
|---|---|
workspaces open, workspaces get |
The workspace view. |
workspaces list |
{data, next_cursor} |
| Lifecycle commands | The operation. fork prints {operation, workspace}. |
login, whoami |
{api_url, organization_id, project_id, api_key: {id, key_id}, tool_permissions} |
workspaces exec |
{session_id, exit_code, term_signal, timed_out, canceled, stdout, stderr, truncated, reconnects}; (0.5.1+) also state (exited, or lost without an exit code) and error when the session has one |
workspaces exec, executions get on a file-first workspace (0.5.0+) |
{execution_id, state, exit_code, term_signal, timed_out, base_revision, tree_revision, changed, changed_truncated, stdout, stdout_truncated, stderr, stderr_truncated, replayed, timings, error, created_at, finished_at}; stdout_base64 / stderr_base64 too when a stream is not UTF-8 |
files read |
{path, bytes, content_base64} |
files write |
The write result (tree_revision added on a file-first workspace). |
files stat (0.5.0+) |
The file info, with revision when asked. |
files search (0.5.0+) |
{matches, truncated, stop_reason, files_scanned, served_from} |
files patch (0.5.0+) |
{path, revision, previous_revision, bytes_written, durable, replacements, file} (tree_revision added on a file-first workspace) |
secrets create, get, update |
The secret's metadata. |
secrets list, versions, access-log |
{data, next_cursor} |
secrets rotate |
{secret, version} |
secrets delete |
{deleted, id, name, scope} |
workspaces secrets |
{workspace_id, names, secrets} |
| Account lists (0.5.0+) | {data, next_cursor}, with default_organization_id, default_project_id or saved_api_key_id where a default applies |
auth login, auth mfa (0.5.0+) |
{status, user, session: {expires_at, credentials_file}, organizations, next}, never the token |
auth status (0.5.0+) |
{api_url, credentials_file, session, api_key, defaults} |
setup (0.5.0+) |
{organization, project, api_key: {id, key_id, name, project_id, tool_permissions}, created: {organization, project, api_key}, credentials_file, next} |
api-keys create (0.5.0+) |
{api_key, secret, saved: false}, or {api_key, saved: true, credentials_file} with --save |
billing upgrade (0.5.0+) |
{subscription_exists: false, organization_id, plan_key, checkout, url, opened, subscription_active}, or {subscription_exists: true, organization_id, plan_key, portal_url, opened} |
| Exports (0.5.0+) | {export, out, bytes} |
env (0.5.0+) |
{shell, variables} |
version |
{cli, sdk, update} (update 0.5.0+) |
feedback (0.5.0+) |
{id, received_at, duplicate} |
Errors go to stderr as one JSON document, {"error": {...}}. (0.5.0+) An unexpected failure adds a sibling field
"feedback" with the shard feedback command that reports it (the same failures that print a feedback: line):
| Error | error fields |
|---|---|
| An API or cell gateway refusal | code, message, status, request_id, retryable, operation_id, details, source (api or cell): the error envelope |
| A failed operation | code: "operation_failed", message, operation_id, retryable (the operation error's own flag), details: {error_code, reason}, operation (the full operation) |
| A wait that gave up | code: "timeout", message, operation_id, last_state. For billing upgrade --wait (0.5.0+): details: {checkout_id, status, url}; the checkout stays open. |
| A checkout that ended (0.5.0+) | code: "checkout_ended", message, details: {checkout_id, status} (expired, canceled or failed) |
| A failed or lost execution (0.5.0+) | code: "execution_failed", message, execution_id, retryable, details: {reason, error_code, state}, after the execution on stdout. executions get of one still running: code: "timeout", execution_id, last_state. |
| Local failures | code: usage, unauthenticated (no key, or no session for an account command), mfa_required (0.5.0+: a sign-in waits for its second factor), not_found (no workspace or secret by that id, key or name; a version without a recipe to export), interrupted, upload_failed (details.sha256, details.storage_code), protocol_error, network_error or internal_error |
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success. |
| 1 | Error: an API refusal such as conflict, quota_exceeded or workspace_not_running, or a network or protocol failure. |
| 2 | Usage error: bad arguments, or input the API rejected as validation_failed. |
| 3 | Not found: workspace, operation or route. |
| 4 | Authentication or authorization: missing, malformed, revoked or insufficient key or session. (0.5.0+) Also step_up_required (run shard auth step-up), mfa_required (a sign-in waiting for its code), email_unverified, invalid_credentials and token_invalid (an emailed link that is invalid, expired or already used). |
| 5 | Timeout: waiting gave up (--timeout, or --wake-timeout while waking). The operation continues server side (shard operations wait <id>). billing upgrade --wait (0.5.0+): nobody paid in time; the checkout stays open. executions get (0.5.0+): the execution is still queued or running. |
| 6 | The awaited operation ended failed or canceled (also a resume or open that failed while waking). retryable=true in the error means it may succeed later (capacity_unavailable). billing upgrade --wait (0.5.0+): the checkout expired or was canceled (checkout_ended). exec and executions get on a file-first workspace (0.5.0+): the execution ended failed or lost (execution_failed). exec on a processful workspace (0.5.1+): the command could not start (exec_failed_to_start). |
| 130 | Interrupted (Ctrl-C). Waits stop at once, and exec sends a cancel to the session. |
exec |
The command's own exit code: 124 if it timed out, 128+N if killed by signal N. Failures before the command ran use the codes above; use --json to tell them apart. |
HTTP connections
shard opens a fresh HTTP connection for every request (Connection: close). On some Node.js releases a request
sent on a reused keep-alive connection can stall until the request timeout. Set SHARDFLUX_HTTP_KEEPALIVE=1 to reuse
connections instead.
Updates
(0.5.0+) shard tells you when a newer version exists, on stderr after the command's output:
@shardflux/cli 0.5.3 is outdated: 0.6.0 is available. Update: npm install -g @shardflux/cli@latestor that the API no longer supports it (... is no longer supported by the Shardflux API (minimum 0.6.0). Update: ...); it keeps working either way.
- It asks the API's
GET /v1/client-versionsat most once a day per API URL (cached in<config dir>/update-check.json), in parallel with the command. A slow answer is skipped (the next run uses it), the exit code never changes, and nothing is printed after a command that failed with--json. - Installed through the
shardfluxnpm package it checksshardfluxinstead, and names that package's upgrade command. shard versionshows the status;shard version --checkasks now. With--json:{"cli", "sdk", "update": {"package", "current", "status", "latest", "minimum_supported", "upgrade_command", "checked_at"}}, wherestatusiscurrent,outdated,unsupportedorunknown.SHARDFLUX_NO_UPDATE_CHECK=1(orNO_UPDATE_NOTIFIER=1) turns it off.npx @shardflux/cli@latestalways runs the newest version.
The shardflux package
shardflux 0.7.2 bundles both JavaScript clients: the TypeScript SDK (@shardflux/sdk ^0.10.0) and this CLI
(@shardflux/cli ^0.5.1). It needs Node.js 24 or later and is ESM only.
npm install shardflux # the SDK: import { Shardflux, ShardfluxAccount } from 'shardflux'
npm install -g shardflux # the CLI, as `shardflux` and `shard`
npx shardflux workspaces open acme/demo --template python-node-browser- Everything
@shardflux/sdkexports is exported fromshardflux, includingworkspaceTools(),ShardfluxAccountandcheckClientVersion()(0.6.0+), the error classes and the API types. See the TypeScript SDK. shardfluxandshardare the same command; its help text calls itshard. From 0.6.0 its update notice is aboutshardfluxitself.- Install
shardfluxor@shardflux/cliglobally, not both: both provideshard.
Compatibility
The CLI is below 1.0: commands and output may change in a minor release, marked Breaking in the changelog. With
--json, the objects are the API's own; new fields can appear in any release. 0.5.0 changes one behaviour: shard
now keeps a credentials file; environment variables still win over it. The account commands need
an API that serves CLI sessions (/v1/auth), which https://api.shardflux.dev does.