CLI

Reference for shard: account setup, workspaces, exec, files, templates, ports, secrets, volumes, usage, output and exit codes.

Install

Linux (Ubuntu 24.04, x64 and arm64) and macOS are supported. On Linux, sign-in opens the browser with xdg-open; in a headless terminal, use the displayed URL and device code. --accept-terms accepts the terms notice.

Shell
npm i -g shardflux
shard --help

Or run without installing: npx shardflux. The CLI 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 the commands, grouped by the credential they use, 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):

Shell
shard version --check

npm permission errors

If npm i -g shardflux fails with EACCES or EPERM under a root-owned directory such as /usr/local/lib/node_modules, install the published package in your own home directory:

Shell
npm install --global --prefix "$HOME/.local" shardflux@latest
"$HOME/.local/bin/shard" --help

This sets the prefix for this install only. It keeps your npm configuration, shell PATH, and other global packages as they are. Do not use sudo or change ownership or permissions of the system npm directory.

If ~/.local/bin is already on PATH, check command -v shard: it should name your home directory's .local/bin/shard. Otherwise keep using "$HOME/.local/bin/shard" for the commands in this guide. Adding that directory to your shell PATH is optional; review that change yourself. An older shard on PATH may still point at the system install.

Update this installation with "$HOME/.local/bin/shard" update (0.13.5+), which retains its installed prefix, or repeat npm install --global --prefix "$HOME/.local" shardflux@latest. Plain npm i -g shardflux still uses your configured global prefix and may fail again. If the old system installation includes a global @shardflux/mcp you also want to move, install it explicitly with the same --prefix "$HOME/.local" and point your MCP client at "$HOME/.local/bin/shardflux-mcp"; leave the old installation and other packages alone.

The hosted MCP endpoint is remote and needs no global npm install; the CLI is optional there.

Quick start

No account yet? One command (0.9.0+) creates it, signs you in and saves an API key: no browser, no password.

Shell
shard signup                                  # or: shard signup --email you@example.com
shard exec acme/demo --template default -- python3 -c 'print(40 + 2)'   # created on first use
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 --wait

With a key from the console instead, skip the account steps:

Shell
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-browser

For 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 or the --ask page, and documented exit codes.

Setting Shardflux up for someone? Run every step yourself; they only decide (0.22.0+): ask one multiple-choice question at a time with the recommended answer first, and never hand them a command, a link to copy or a secret to paste into the chat. They answer your questions, agree to the terms, approve sign-ins in the browser tabs shard opens and type secrets into the page it opens (--ask). The steps below set up their product to run VMs for its customers through the API, SDK or MCP.

  1. Account (0.9.0+). Show the person the Terms of Service and the Privacy Policy; once they agree, shard signup --accept-terms --json (0.15.0+). Pass --email <email> to create the account automatically without a browser. It then runs shard setup: an organization, a project and an API key with every workspace tool, saved in the credentials file. With two-factor authentication it exits 4 with mfa_required: ask the person for the code, then shard auth mfa --code <code> (within 10 minutes), or pass --code.

  2. Verify identity and start the trial (or subscribe to a paid plan). For an --email signup, shard verify --json emails a 6-digit code; ask the person for it, then shard verify <code>. Nothing is signed out. Compute runs on organizations with a card on file and an active trial or paid plan: once the account has a verified work domain (registered at least 30 days ago with active MX records) or a linked GitHub account (at least 30 days old), shard billing trial --wait (0.32.4+) prints the Stripe page where the person saves a non-prepaid card directly and approves it with their bank (nothing is charged), which starts the 7-day trial; it exits 0 once the trial has started. Consumer webmail signups can link GitHub in Account & security, verify an organization domain, or upgrade directly in step 5.

  3. Set up again any time. shard setup --json is idempotent.

  4. Work. shard exec <key> --template default -- <command> (0.10.0+) creates the workspace on first use and runs the command; later commands reuse it. shard ws open <key> --template <slug> --json and shard files ... use the saved key too. eval "$(shard env)" exports it for the SDKs and the MCP server.

  5. A paid plan. shard billing plans, then shard billing upgrade <plan> --json prints the Stripe Checkout URL. Give it to the person, then run shard billing upgrade <plan> --wait (or shard billing status) until the plan is active. The API activates a plan only when Stripe confirms the payment.

  6. 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 terminal shard does not ask: the command fails with step_up_required (exit 4), and the hint names this command.

  7. Feedback (0.22.0+). Report only when the user asks. shard feedback previews the message and context; obtain explicit authorization before repeating it with --yes (see Feedback).

What a person does: entering a card in Stripe Checkout, the authenticator app's codes, and, after an --email signup, reading the 6-digit code.

Feedback

(0.22.0+) shard feedback previews the exact message, category and context without sending. Add --yes only after reviewing that preview and obtaining explicit user authorization. Earlier CLI versions send immediately.

Agents: report only when your user asks to send feedback. Show the exact message and context first, then obtain explicit authorization. A failure or request for a feature is not consent. Leave out private data, secrets and code the user did not mean to share; paraphrase, never paste chat logs. Tell the user what was sent.

Shell
shard feedback --category bug --request-id req-5c7744b2bb5c457b86b76101 --error-code template_not_found \
  "ws open --template python-node failed; expected a suggestion of the closest slug"
shard feedback --category idea \
  "user would like shard ws open to remember the last template they used"
npm test 2>&1 | tail -n 60 | shard feedback --category bug --workspace acme/demo --from-file -

These commands only preview. After the user approves the exact message and context, repeat the chosen command with --yes. Re-preview file or piped input if its contents changed.

Option Meaning
<message...> The remaining arguments joined with spaces, of any length (0.32.4+). Quote it, or put it after --, when it contains shell characters or words starting with -.
--yes Send after reviewing the preview and obtaining explicit user authorization (0.22.0+). Omitted: preview only.
--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. template_not_found.
--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-label or SHARDFLUX_AGENT_LABEL names the reporting agent; shard adds its own version as the client.
  • Preview output includes sent: false, authorization_required: true, preview and note with --json.
  • Approved submission output: one line with the feedback id. Already received means 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@shardflux.dev.
  • 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. (0.16.0+) Without either, a resume queued for capacity is waited for until its deadline.
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). shard warns 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 to credentials.json.corrupt-<time>.

  • Profiles: one per API URL, so credentials for different API URLs never mix. Each holds the session, the default organization and project, and the saved API key:

    JSON
    {"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 devbox"}}}}
  • Precedence: the project API key is SHARDFLUX_API_KEY, else the saved api_key. The session is SHARDFLUX_SESSION_TOKEN, else the saved session. shard auth logout removes 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. (0.16.0+) Without it, a resume queued for capacity is waited for until its deadline.
-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 signup and shard auth login save.

Shell
shard signup [--email you@example.com] [--name "Ada Lovelace"] [--no-setup] [--accept-terms]
shard auth login --browser [--no-open]                 # approve this computer on the sign-in page
shard verify [<code>]                                  # emails a 6-digit code, then confirms it
printf '%s\n' "$PASSWORD" | shard auth register --email you@example.com [--name "Ada Lovelace"] [--accept-terms]
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 signup --email <email>, --name <name>, --no-setup, --tool <tool>, --accept-terms, --code <code>, --recovery-code <code> (0.9.0+) Creates the account, signs in and runs shard setup. --email creates an account automatically; new accounts need the signup trial (verified work domain or established GitHub account + $0 Stripe card check) or a paid plan before starting compute (an address that has an account answers conflict, reason email_registered). --json: {created, access, method, user, setup}.
shard verify [<code>] (0.9.0+) Without a code, emails a 6-digit code (valid 15 minutes) and, on a terminal, asks for it; with one, verifies the email. Nothing is signed out and saved keys keep working.
shard auth register --email <email> (required), --name <name>, --accept-terms 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 --browser, --no-open, --client-name <name>, --email <email>, --code <code>, --recovery-code <code> Signs in and saves the session for this API URL. --browser (0.15.0+) signs in on the web (see Accounts and sign-in); on a terminal it is the default without --email. --email signs in with a password. Then prints who you are, whether the email is verified, your organizations and the next step (shard setup, or shard verify).
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.
  • Browser sign-in. (0.15.0+) shard auth login --browser opens the sign-in page (https://app.shardflux.dev/cli?code=XXXX-XXXX) in the default browser and prints the link and the code. Sign in or create your account with Google, GitHub or email on the page, check that it shows the same code, and approve: the session is saved here as with a password, and two-factor accounts enter their code on the page. --no-open only prints the link (open it on any device); --client-name sets the name the page shows (default shard CLI on <hostname>). The code is valid for 10 minutes. --no-wait (0.18.0+) prints the link and the code and returns; the next shard auth login --browser waits for that same request while it is valid (its open event adds "resumed": true), so a command cut off by an agent's tool time limit is run again and the code stays the same. On a terminal, shard signup without --email continues the same way and then runs shard setup. Before the browser opens, shard prints the terms notice: by continuing you agree to the Terms of Service and acknowledge the Privacy Policy. With --json the command prints one JSON object per line, for apps that drive it:

    JSON
    {"event":"open","verification_uri_complete":"https://app.shardflux.dev/cli?code=BCDF-GHJK","user_code":"BCDF-GHJK","expires_in":600,"terms_url":"https://shardflux.dev/terms","privacy_url":"https://shardflux.dev/privacy"}
    {"event":"signed_in","email":"ada@example.com"}

    A refusal ends with {"event":"error","code":"access_denied","message":"..."} instead (expired_token when the code was not approved in time), and the command exits 4.

  • Passwords never come from arguments (--password is refused). On a terminal shard asks 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 login saves 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, and shard saves 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. --code or --recovery-code, or the code typed at the prompt. Without either (and without a terminal) the pending sign-in is saved and auth login exits 4 with mfa_required; shard auth mfa --code completes 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 shard asks (and for a code with two-factor authentication) and retries once. Otherwise the command exits 4 with step_up_required: run printf '%s\n' "$PASSWORD" | shard auth step-up first (with two-factor authentication add --code, or pipe the code as the second line).

The terms

(0.15.0+) The commands that can create an account (shard signup and shard auth register) need the person's agreement to the Terms of Service and the Privacy Policy before they send anything: --accept-terms (or SHARDFLUX_ACCEPT_TERMS=1), or "Continue? [Y/n]" on a terminal. The new account records the agreement. Without either, the command stops with terms_not_accepted (exit 2); its details carry terms_url, privacy_url and flag, so an agent can show the person both pages and run the command again with the flag once they agree:

JSON
{"error":{"code":"terms_not_accepted","message":"Re-run with --accept-terms to agree to the Terms of Service (https://shardflux.dev/terms) and Privacy Policy (https://shardflux.dev/privacy); creating an account needs that agreement.","retryable":false,"details":{"terms_url":"https://shardflux.dev/terms","privacy_url":"https://shardflux.dev/privacy","flag":"--accept-terms"}}}

Signing in to an account prints the same line (terms_url and privacy_url in --json) and needs no flag; so does shard auth login --browser, because an account created on the sign-in page agrees to the terms there.

Setup

(0.5.0+) shard setup makes a signed-in account ready for the workspace commands:

  1. The organization: --org, the saved default, or your only one. With none it creates "<your name>'s organization" (--org-name to choose); with several it lists them.
  2. The project: --project, the saved default, or the organization's only one. With none it creates "Default" (--project-name).
  3. An API key with every workspace tool (--tool, repeatable, narrows it), named shard-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 for each path (next_steps with --json, 0.18.0+). 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):

Shell
eval "$(shard env)"                       # sh, bash, zsh
shard env --shell fish | source
shard env --shell powershell | Invoke-Expression

shard 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.

In more than one organization (0.22.0+), workspace and usage commands act where the API key belongs, and account commands where the default is. orgs use and projects use say when the key belongs to another organization and name the command that makes one for the new default, shard setup --org <org> --new-key (in a terminal they offer to run it). whoami distinguishes departed defaults and keys from a key in another organization you still belong to. A stale default names shard orgs use <org>; a key elsewhere names shard setup --org <org> --new-key. These checks require your signed-in session. Switches retain the key unless you accept the replacement prompt. SHARDFLUX_API_KEY wins over the saved key: after recovery, unset it to use the replacement. Text warnings and JSON warnings carry the same message and recovery; setup --json also warns about an environment key that still overrides the key it saved.

Shell
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+)

Shell
shard billing plans                                  # public: no sign-in needed
shard billing status                                 # plan, billing state, period end, pending checkout
shard billing trial [--open] [--wait] [--timeout 15m]  # (0.32.4+) start the 7-day trial: a card check, nothing charged
shard billing card [--open] [--wait] [--timeout 15m]   # (0.34.0+) save a card for compute, nothing charged
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 cap

billing 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). 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.

Compute runs on organizations with a card on file and an active trial or paid plan. New accounts start workspace compute with either a paid plan or the 7-day signup trial, which requires a verified work domain (registered at least 30 days ago with active MX records) or a linked GitHub account (at least 30 days old) plus a non-prepaid, non-wallet $0 Stripe card check approved by the card's bank (3-D Secure). Run shard billing trial --wait and give the person the Stripe page (or shard billing card --wait (0.34.0+) to save a card on an organization without one). One person, card and GitHub account earn one trial across all accounts, ever. The trial applies to the organization where you start it; additional organizations, and compute after the trial ends, need a paid plan ($9/mo Developer and up). Organization, project and credential creation remain automatic.

Audit, exports and account deletion

(0.5.0+)

Shell
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 <id|slug>] Usage summary for the current period: plan, meters and allowances, and the overage block (0.5.1+). --org of another of your organizations (id or slug) is read with your signed-in session (0.22.0+).
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).

Organization summaries, estimates and series keep the project key in its own organization (0.22.0+). An explicit --org for another of your organizations uses your signed-in session. Without one, run shard auth login; to save a key for that organization, then run shard setup --org <org> --new-key. If SHARDFLUX_API_KEY is set, unset it after saving the replacement so the saved key takes effect. A forbidden organization stays denied, and workspace usage keeps the project key.

Workspaces

shard workspaces open

Shell
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.
--memory-held <MiB> (0.8.0+) Elastic memory: --memory-mib is the most the workspace may use and --memory-held what it holds while idle. Caps flags replace the stored caps; without any, the workspace keeps its caps. --allocation-mode is deprecated: accepted and ignored.
--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. (0.16.0+) Without it, a start queued for capacity is waited for until its deadline.
--timing Print where the time went (see Timing).

ws open also accepts --like and repeated --volume name:/path[:ro|rw]; volumes open defaults to 1 GiB for new storage.

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+), a pending suspend when idle (0.5.1+), and the version its immutable paths show (0.8.0+). (0.33.1+) A failed workspace has a failed line with the reason: vm_start_failed: The workspace could not start. (host_reason=budget_exhausted), then the operation and when. (0.8.0+) A memory line, for example elastic: promised 8192 MiB, held 1024 MiB, plugged +2048 MiB.
shard workspaces inputs <id|key> (0.4.0+) The workspace's text inputs.
shard workspaces exec <id|key> -- <command> [args...], also shard exec (0.10.0+) --template <slug> (0.10.0+: opens the key first, creating the workspace on first use; stderr says created workspace <key> (template <slug>); without it the key must have a workspace), --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), --resource-hint <auto|light|heavy> (0.9.0+), --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, and (0.8.0+) the memory grow its start waited for on an elastic workspace (--json: memory_grow). 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.
shard workspaces resize <id|key> --memory <MiB>, --held <MiB>, --cpu <millis>, --disk <GiB>, --timeout, --timing (0.9.0+) Resizes a running, suspended or stopped workspace without a restart, waits until it has finished, and prints per resource the change and when it applies, for example memory 4096 → 6144 MiB now. --memory is the maximum and --held the idle floor; --fixed and --elastic are deprecated: accepted and ignored. --json prints the result.
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> (0 to 1h; 0, as soon as it is idle, 0.6.1+) or --cancel-when-idle (0.5.1+) ; --durable (0.7.0+) Suspends a running workspace. Returns at once unless --wait, which returns once the workspace is sealed on its host; the output shows whether its checkpoint is in durable storage yet. --durable (0.7.0+) implies --wait and returns once it is (result.durable: true), within --timeout. --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, --durable or --timeout (exit 2). --json prints {workspace, operation, suspend_request}; the operation's result carries durable and durability (0.7.0+).
shard workspaces resume <id|key> --wait, --timeout, --timing Resumes a suspended workspace. (0.7.0+) The output shows a lost_suspend from the resume's result (lifecycle). (0.8.1+) A host_lost in the result is shown too, with a note on stderr (lifecycle).
shard workspaces fork <id|key> <new-key> --cpu-millis, --memory-mib, --disk-gib, --allocation-mode, --memory-held (0.8.0+), --wait, --timeout, --timing Forks into a new key. (0.7.0+) A fork of a running workspace shows its durable state like a suspend.
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 becomes reusable once deletion finishes, creating a new workspace ID and disk.
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.
shard workspaces port expose <id|key> <port> (0.9.0+) Serves the port at its own private HTTPS URL (inbound ports) and prints it. Idempotent.
shard workspaces port ls <id|key> (0.9.0+) The exposed ports, with their URLs and whether a callback URL exists.
shard workspaces port token <id|key> <port> --ttl <seconds> (60-86400, default 3600) (0.9.0+) Prints a port token alone on stdout, for Authorization: Bearer $(shard ws port token ...).
shard workspaces port link <id|key> <port> --path <path> (default /), --ttl <seconds> (60-604800, default 86400) (0.9.0+) Prints a signed link that opens the port in a browser. Share it like a password.
shard workspaces port callback <id|key> <port> --revoke (0.9.0+) Creates (or replaces) the port's callback URL for webhooks and OAuth redirects and prints it; it is shown only once. --revoke removes it.
shard workspaces port close <id|key> <port> (0.9.0+) Closes the port: its tokens, links and callback URL stop working.

shard ws resize <workspace> --at-least (0.11.0+) grows each named resource independently. Add --no-wait to return the held server answer and operation; the default waits for completion.

ws is short for workspaces and ports for port. With --json the port commands print the API's bodies.

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), --ask, --timeout <duration>, --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. --ask (0.22.0+) opens a one-time page on this computer where the person types or pastes the contents, for a secret file such as ~/.npmrc; an agent running the command never sees them, and a new file gets mode 0600. See Values typed in a page.
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). If search or patches are not available for a workspace, shard exits 1 with host_feature_unavailable and a hint naming the equivalent command.

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.

Shell
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 in full when the command ends: 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 failed or lost published nothing and exits 6, naming its reason and whether a new execution may succeed.
  • -v prints 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 fresh ex-<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. shard sends the request again with the same id after a dropped connection and after no_execution_host, and waits within --wake-timeout while another execution holds the workspace.
  • Ctrl-C stops waiting (exit 130). The execution runs to completion; shard prints the shard executions get command that fetches its result later. Results are kept for 7 days.
  • Tree revisions: shard ws get shows the current one, and files write and files patch print the revision after their change. --if-revision <n> applies the change only while the tree is at revision n; otherwise nothing changes, shard exits 1 and the hint names the current revision.
  • Not in file-first mode: workspaces suspend, resume, fork, reset, save-as-template and changes are refused without a request (not_supported_for_mode, exit 1). --execution-id, --output-limit and --if-revision on a processful workspace are usage errors (exit 2).
  • Opening: the other mode for an existing key is mode_mismatch (exit 1), an account without file-first workspaces gets mode_not_available (exit 2), and a template version without layered disks layout_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; 0.16.0+: without it, a start queued for capacity is waited for until its deadline), --timing; --durable (0.7.0+) Waits for an operation to finish: exit 0 succeeded, 6 failed or canceled, 5 timeout. With --durable, a suspend or fork also waits until its checkpoint is in durable storage (lifecycle).
shard operations progress <operation-id> (0.22.0+) A suspend's live progress, read without waking the workspace: its phase, whether it is cancelable, the next action, and when the phase started and the host's deadline. --json: {progress} (fields).
shard operations cancel <operation-id> --wait, --timeout <duration> (with --wait, default 5m) (0.22.0+) Cancels a suspend before its capture starts; the workspace keeps running as it was. Without --wait it returns as soon as the host accepts (cancel request: accepted); with --wait, once the operation is canceled with suspend_canceled (exit 5 if --timeout passes first; the cancellation continues server side). --json: {operation, progress}. Once capture has started the suspend completes (exit 1, 409 conflict suspend_capture_started): wait for it, then resume.

Suspend progress

(0.22.0+) Cancel a suspend while the workspace is still preparing it:

Shell
op=$(shard ws suspend customer-42/main --json | jq -r .id)
shard operations progress "$op"          # phase preparing_snapshot, cancelable yes
shard operations cancel "$op" --wait     # operation state canceled, workspace state running
Field (--json) Text Meaning
phase phase Where the suspend is, for example preparing_snapshot or capturing.
state, workspace_state operation state, workspace state The operation's and the workspace's states.
cancelable cancelable true while the suspend can still be canceled (preparing_snapshot).
supported progress supported Whether the phase is reported live for this suspend.
safe_action next action wait_for_terminal (wait for the operation), resume (it is suspended), retry_tools (the workspace is running: carry on), inspect_failure (read the operation's error).
phase_started_at, deadline_at phase started, host deadline When the phase began and when the host must finish, when reported.
accepted cancel request On cancel: the host accepted the cancellation.

Secrets

Shell
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 secrets create GITHUB_TOKEN --ask                                # or typed in a page shard opens (0.22.0+)
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>, --ask, --timeout <duration>, --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 the --ask page (0.22.0+), 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>, --ask, --timeout <duration> Stores a new value as the next version; older values are erased. --ask as for create (0.22.0+).
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 the --ask page, standard input or --from-file, with one trailing newline removed. --value, --password and similar flags are refused. With nothing piped, a terminal gets a hidden prompt and an agent's shell the --ask page (0.22.0+).
  • Secrets are project secrets of the API key's project by default. --org addresses organization-wide secrets; those, and secrets 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_available with the names).

Values typed in a page (0.22.0+)

secrets create, secrets rotate and files write take --ask: shard serves a one-time page on 127.0.0.1, opens it in the browser and prints its link. The person types the value there and it goes straight to the API (or the file); the page says Saved once it is stored, and an agent running the command sees only the result. The page closes after one use, a cancel or --timeout (default 10m; then exit 5, ask_timeout). With --json the first line is the page, then the command's result once it was submitted:

JSON
{"event":"open","url":"http://127.0.0.1:52817/0kZ6rT2bWq8yXn4uJp1sLm7vHc3dFg9aEo5iKt0RzYw","opened":true,"expires_in":600}

Egress and volumes

(0.5.0+) These use the project API key, like the other workspace commands.

Shell
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 --workspace also shows the enforcement; egress clear makes the workspace follow the project policy again.
  • Volume commands wait until the cell has finished unless --no-wait. volumes delete is 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.

Shell
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 from files 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 with shard templates test <slug>@<version>. Without --slug, the slug is the name of the directory holding the file.
  • --wait follows the build until it is registered or fails (exit 6 when it failed or was canceled, 5 when --timeout ran out; the build continues). A host the build network refused is listed under denied hosts: add it to build.network.extra_hosts and build again.
  • A file shard cannot 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 is upload_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. (0.8.0+) Each version's immutable paths and image size.
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.

Computer use (0.10.0+)

The workspace desktop; see the computer use guide.

Command Does
shard ws open <key> --computer-use on|off|inherit, shard ws computer enable|disable|inherit <ws> The workspace's switch (inherit follows the template)
shard templates computer-use <slug> on|off The switch for every workspace of one of your templates
shard ws computer status|start [--width --height]|stop <ws> The desktop itself
shard ws computer screenshot <ws> [--out F] [--format jpeg --quality N] Saves a screenshot
shard ws computer click <ws> [x y] [--button left|right|middle] [--count 2|3] [--mods keys] A click, double or triple click
shard ws computer type <ws> <text|->, key <ws> <keys> [--repeat n] Types text; presses keys and combinations
shard ws computer scroll <ws> up|down|left|right [x y] [--amount n] Scrolls (default 3 wheel clicks)
shard ws computer move|drag|mouse-down|mouse-up|hold-key|wait <ws> ... The other pointer and keyboard actions
shard ws computer zoom <ws> <x0> <y0> <x1> <y1> [--out F], cursor <ws> An enlarged region; the pointer position
shard ws computer act <ws> <json|-> A batch of actions (a JSON array)
shard ws computer stream <ws> [--interactive] [--ttl D] [--stop] A private link to the live view

Input commands and act take --screenshot F, --settle MS and --format jpeg --quality N; they print one line per action and exit 1 when one failed.

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 --wait is the same request.

  • (0.5.0+) files read, ls, stat and search of a suspended workspace are answered from its saved 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, shard exits 5 and names the operation and its state. The operation continues server side: shard operations wait <id> keeps waiting. (0.16.0+) Without --wake-timeout or SHARDFLUX_WAKE_TIMEOUT_MS, a resume queued for capacity is waited for until its deadline, its place shown on stderr (see Start deadlines).

  • (0.16.0+) A call refused before it ran, while the workspace's host makes room to wake it (503 host_capacity) or while every workspace the plan lets work at once is busy (429 quota_exceeded), is sent again after each Retry-After for up to 2 minutes, ws exec starts and ws open included. stderr says so once, for example waiting for room on the workspace's host (position 2).

  • A resume or open that fails exits 6.

  • --no-wake (or SHARDFLUX_NO_WAKE=1) turns this off: a workspace that is not running is refused at once (exit 1, workspace_not_running).

Start deadlines

A queued open, resume or fork (capacity_pending) has a deadline 15 minutes after it was created, moved later while new capacity is starting for it (start deadlines). (0.16.0+) While shard waits for it, stderr says where it stands, again whenever that changes (dim on a terminal, never with --json):

Text
queued for capacity (position 3): a new host is starting, ready by 21:40Z; it holds its place until 21:51Z

(0.16.0+) Without --timeout, a queued start is waited for until its deadline. An explicit --timeout is kept: if it ends first, shard exits 5 and the timeout error names the deadline and the queue position (--json: last_reason, deadline_at and queue_position). A start still pending at the deadline 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:

Text
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]

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.

Text
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  $1.10 of $9.00 (12.22%), $7.90 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.015  $0.90
cpu_hours      hours      5               5       $0.04   $0.20

--json prints the API's summary, with spend_cap and exhausted_reason.

On plans with GPU-hours, a GPU-hours line shows the hours used of those included and, with overage on, the hours past them and the part billed (0.19.0+), and a GPU line with the next step whenever GPU rendering needs one (GPU frame requests lists the reasons):

Text
GPU-hours  3.4 of 25 used

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).

Text
$ 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.015 per RAM GiB-hour, $0.04 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).

A feature the plan does not include is refused with 402 entitlement_required, not_included (exit 1); the hint names the plans that include it, for example upgrade to Startup or Scale: shard billing plans for the GPU (0.19.0+).

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. Host metrics on the server line print in their own units (0.30.1+): a …_us span in µs or ms, a …_ms span or a host phase in ms, counters and flags as plain numbers; --json keeps the raw values.

Text
$ shard ws resume acme/demo --wait --timing
Resuming acme/demo (01a0ead6-92e5-7d19-ab7a-f565bf4676cb): operation 01a0ead6-bd61-737a-ae88-66e2d01a6e25 resume succeeded
resume 413 ms, succeeded (workspace 01a0ead6-92e5-7d19-ab7a-f565bf4676cb, operation 01a0ead6-bd61-737a-ae88-66e2d01a6e25)
  client: request 218 ms → queued 195 ms
  server: queued 51 ms, ran 290 ms, total 341 ms; resume from local_cache, boot to ready 211 ms, host disk 0 ms, load 6 ms, ready 62 ms, total 211 ms, after_restore 36 ms
  outside the server: 72 ms
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": {...}}.

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}; whoami adds warnings (code, message, fix) for departed defaults/keys or a key in another accessible default organization (0.22.0+)
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 login --browser (0.15.0+) prints one event per line instead (see Accounts and sign-in)
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+)
update (0.13.5+) {update_available, components: [{package, label, current, latest, status}], install: {manager, command}}; after an install also updated and changes
feedback (0.22.0+) Preview: {sent: false, authorization_required: true, preview, note}. With approved --yes: {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 a shard feedback command that previews a report for user approval (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; (0.16.0+) last_reason, deadline_at and queue_position when the operation reports them. 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. (0.15.0+) Also terms_not_accepted: a command that can create an account ran without the agreement to the terms (see The terms).
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). (0.15.0+) access_denied and expired_token from auth login --browser.
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

From 0.7.0, shard uses the SDK's private HTTP/1.1 connection pool on Node 26; other runtimes use native fetch. SHARDFLUX_HTTP_KEEPALIVE=0 forces connection closure for diagnosis; =1 selects native pooling.

Updates

(0.5.0+) shard tells you when a newer version exists, on stderr after the command's output:

The notice names the installed version and the current published version, and gives shard update as the upgrade command.

It also reports when the API no longer supports the installed version, including the minimum supported version and the upgrade command. The update notice does not stop the command.

  • It reads the latest release from npm (its latest tag, which npm i -g shardflux installs; 0.15.2+), so a new release shows up the moment it is published, and the oldest supported version from the API's GET /v1/client-versions. It asks at most every 12 hours 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 shardflux npm package it checks shardflux instead.
  • shard version shows the status; shard version --check asks now. With --json: {"cli", "sdk", "update": {"package", "current", "status", "latest", "minimum_supported", "upgrade_command", "checked_at"}}, where status is current, outdated, unsupported or unknown.
  • SHARDFLUX_NO_UPDATE_CHECK=1 (or NO_UPDATE_NOTIFIER=1) turns it off.
  • shard update (0.13.5+) installs the latest shard with the package manager that installed it, together with a global @shardflux/mcp; shard update --check lists what is behind. Right after a release, while npm is still rolling it out, it waits and tries again until the install goes through (0.32.5+), and says so on stderr.

The shardflux package

shardflux 0.36.3 bundles both JavaScript clients: the TypeScript SDK (@shardflux/sdk ^0.35.2) and this CLI (CLI 0.34.3 on a fresh install). It needs Node.js 24 or later and is ESM only.

Shell
npm install shardflux          # the SDK: import { Shardflux, ShardfluxAccount } from 'shardflux'
npm i -g shardflux       # the CLI, as `shardflux` and `shard`
shard workspaces open acme/demo --template python-node-browser
  • Everything @shardflux/sdk exports is exported from shardflux, including workspaceTools(), ShardfluxAccount and checkClientVersion() (0.6.0+), the error classes and the API types. See the TypeScript SDK.
  • shardflux and shard are the same command; its help text calls it shard. From 0.6.0 its update notice is about shardflux itself.
  • Install shardflux or @shardflux/cli globally, not both: both provide shard.

Compatibility

Breaking changes to commands and output ship only in minor releases and are 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.

Integration controls (0.7.0+)

ws open accepts --labels '{"scope":"project-42"}' and --idle-policy never. ws list --labels '{"scope":"project-42"}' filters exact labels. ws labels <key> --set '<json>' replaces metadata; omit --set to read. ws idle <key> inspects idle signals, --keepalive 60 declares work and --policy adaptive sets policy (default clears the override).

ws exec-start <key> --stdin-open --session-id worker-1 -- cat starts a tracked background session. ws exec-input <key> worker-1 hello --offset 0 writes bytes; use the acknowledged offset on the next call, and --close for EOF.

Background commands (0.8.0+)

A long command (a build, a test suite, a training run, a server) runs in the background of a processful workspace while you or your agent do other work:

Shell
shard ws exec-start acme/demo --session-id build-1 --timeout 2h -- bash -lc "make -C /home/user/app"
shard ws exec-read acme/demo build-1            # the output so far; exits 5 while it runs
shard ws exec-read acme/demo build-1 --follow   # streams to the end; exits with the command's exit code
shard ws exec-cancel acme/demo build-1 --grace 10s
  • --timeout is the longest the command may run; the workspace stays awake until it ends or that time passes.
  • exec-read prints stdout and stderr from the start. --follow resumes from byte offsets after a dropped connection; Ctrl-C stops following and the command keeps running. --json prints one object with the state, exit code and output.
  • exec-cancel sends SIGTERM, then SIGKILL after --grace (default 5s, at most 60s).
  • (0.9.0+) exec-start --resource-hint heavy gives an elastic workspace its memory before the command starts.

The CLI shares SDK 0.12.0's pooled transport. Protocol-error JSON includes source. Resume can recover failed workspaces; completed deletion frees the key for a new ID.

Prepare an imminent tool call (0.9.0+)

shard ws hint <id|key> explicitly stages a parked workspace ahead of a VM tool call and returns without waiting for restore. Resume a suspended workspace first. Ordinary commands add no early hint.

shard ws computer stream reuses a private cached link of the same kind with more than 60 seconds left across invocations. --fresh mints a new link; --stop clears it. Canceled exec commands exit 130, timeouts 124, and signal exits use 128 + signal. SHARDFLUX_BASE_URL aliases SHARDFLUX_API_URL; SHARDFLUX_API_URL and --api-url take precedence. Environment HTTP(S)_PROXY and NO_PROXY are honored by the SDK transport.

Upgrade in place (0.11.0+)

shard ws upgrade <key> keeps the disk through a cold start. Use --at next-resume to schedule it for the next resume, --no-wait to return once requested, or --json for the operation and its result. Memory and running processes end at the cold start.

View this page as Markdown