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

Shell
npm install -g @shardflux/cli
shard --help

Or 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):

Text
shard 0.5.3 (@shardflux/sdk 0.10.2)
up to date: latest 0.5.3, checked 2026-10-01 09:00:00Z

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

Shell
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 --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, and documented exit codes.

  1. 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 run shard auth verify-email '<link>' (the whole link, quoted).

  2. Sign in. printf '%s\n' "$PASSWORD" | shard auth login --email <email> --json. 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 to auth login.

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

  4. Work. shard ws open <key> --template <slug> --json, shard ws exec <key> -- <command> and shard files ... use the saved key. 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.5.0+). While you work, send shard feedback the 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.

Shell
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-label or SHARDFLUX_AGENT_LABEL names the reporting agent (e.g. claude-code); shard adds its own version as the client.
  • 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@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). 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 production, staging and a local API 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 laptop"}}}}
  • 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.
-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.

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

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

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

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

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

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 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 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). An execution cannot be canceled; 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), a deployment without file-first workspaces answers 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), --timing Waits for an operation to finish: exit 0 succeeded, 6 failed or canceled, 5 timeout.

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 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, --password and similar flags are refused.
  • 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).

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

  • (0.5.0+) files read, ls, stat and search of 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, shard exits 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 (or SHARDFLUX_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:

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

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

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

Text
$ 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:

Text
@shardflux/cli 0.5.3 is outdated: 0.6.0 is available. Update: npm install -g @shardflux/cli@latest

or 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-versions at 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 shardflux npm package it checks shardflux instead, and names that package's upgrade command.
  • 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. npx @shardflux/cli@latest always 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.

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

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.

View this page as Markdown