@shardflux/cli 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -0
- package/README.md +87 -23
- package/dist/account-args.js +32 -4
- package/dist/account-commands.js +234 -111
- package/dist/args.d.ts +1 -1
- package/dist/args.js +80 -4
- package/dist/commands.d.ts +14 -0
- package/dist/commands.js +144 -3
- package/dist/format.d.ts +21 -1
- package/dist/format.js +61 -0
- package/dist/main.js +8 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.0 — 2026-10-04 (not yet published)
|
|
4
|
+
|
|
5
|
+
- `shard ws hint <workspace>` explicitly stages a parked workspace ahead of a VM tool call, without waiting for restore or resuming a suspended workspace.
|
|
6
|
+
|
|
3
7
|
Every command and option the README shows is available from the version named here. Breaking changes ship in minor
|
|
4
8
|
releases and are marked **Breaking**.
|
|
5
9
|
|
|
@@ -7,6 +11,20 @@ releases and are marked **Breaking**.
|
|
|
7
11
|
|
|
8
12
|
Needs `@shardflux/sdk` 0.14.0 or later.
|
|
9
13
|
|
|
14
|
+
### Sign up from an agent
|
|
15
|
+
|
|
16
|
+
- `shard signup [--email <email>] [--name <name>] [--no-codex] [--no-setup] [--tool <tool>...]`: creates the account,
|
|
17
|
+
signs in and runs `shard setup` in one command, with no browser and no password. With the Codex CLI signed in with
|
|
18
|
+
ChatGPT on the machine, Codex refreshes its login (`codex app-server`) and the ID token from `$CODEX_HOME/auth.json`
|
|
19
|
+
verifies the email (the account starts with its trial; an existing account of that identity or email is signed
|
|
20
|
+
in). Without one, `--email` creates an account that works at once on the Free plan. `--json`: `{created, access,
|
|
21
|
+
method, user, setup}`.
|
|
22
|
+
- `shard verify [<code>]`: emails a 6-digit verification code (and asks for it on a terminal), or confirms one.
|
|
23
|
+
Nothing is signed out; an account from `shard signup` gets its trial.
|
|
24
|
+
- `shard auth login --codex` signs in with the Codex login; `shard auth step-up --codex` confirms a sensitive action
|
|
25
|
+
with it instead of the password.
|
|
26
|
+
- After signing in with an unverified email, the next step printed is `shard verify`.
|
|
27
|
+
|
|
10
28
|
### Workspaces working at once
|
|
11
29
|
|
|
12
30
|
- A command whose workspace call finds every workspace the plan allows to work at once busy is sent again after
|
|
@@ -21,6 +39,55 @@ Needs `@shardflux/sdk` 0.14.0 or later.
|
|
|
21
39
|
- `shard usage` says `retained state used up: new workspaces and forks are refused (...)` when the Retained state
|
|
22
40
|
allowance's `cap_state` is `storage_blocked` (`enforcement` `storage_block`).
|
|
23
41
|
|
|
42
|
+
### Inbound ports
|
|
43
|
+
|
|
44
|
+
Additive. Serve a port of a processful workspace at its own private HTTPS URL; a request wakes a parked or suspended
|
|
45
|
+
workspace.
|
|
46
|
+
|
|
47
|
+
- `shard ws port expose <id|key> <port>`: the URL and how requests get in (`--json`: the API's port object
|
|
48
|
+
`{port, url, created_at, callback}`). Idempotent.
|
|
49
|
+
- `shard ws port ls <id|key>`: port, URL, exposure time and callback URL (`--json`: `{ports}`).
|
|
50
|
+
- `shard ws port close <id|key> <port>` (`--json`: `{workspace_id, port, closed}`).
|
|
51
|
+
- `shard ws port token <id|key> <port> [--ttl 1m..24h]`: the port token alone on stdout, how to send it on stderr
|
|
52
|
+
(`--json`: `{token, expires_at, url}`).
|
|
53
|
+
- `shard ws port link <id|key> <port> [--ttl 1m..7d] [--path /...]`: a URL that opens the port in a browser
|
|
54
|
+
(`--json`: `{url, expires_at}`).
|
|
55
|
+
- `shard ws port callback <id|key> <port> [--revoke]`: the port's callback URL for webhooks and OAuth redirects, shown
|
|
56
|
+
once (`--json`: `{url, created_at}`; with `--revoke`: `{workspace_id, port, revoked}`).
|
|
57
|
+
- `ports` is an alias of `port`. A port outside 1-65535, a `--ttl` out of range or not in whole seconds, and a
|
|
58
|
+
`--path` without a leading `/` exit 2 before any request; a file-first workspace is refused before any port
|
|
59
|
+
request. Hints for `port_not_exposed` (expose it first) and `port_limit` (close a port first).
|
|
60
|
+
|
|
61
|
+
### Memory across platform upgrades
|
|
62
|
+
|
|
63
|
+
- The cold-boot note and `--json --timing` name the new reason `runtime_retired` (the runtime the workspace was
|
|
64
|
+
suspended on was retired after an announced window): `note: workspace <id> resumed from its saved disk; running
|
|
65
|
+
processes were restarted (runtime_retired)`.
|
|
66
|
+
|
|
67
|
+
### Resize a workspace
|
|
68
|
+
|
|
69
|
+
- `shard ws resize <id|key> [--memory MIB] [--held MIB] [--fixed|--elastic] [--cpu MILLIS] [--disk GIB]
|
|
70
|
+
[--timeout D] [--timing]`: changes the caps of a running, suspended or stopped workspace without a restart
|
|
71
|
+
(`PATCH /v1/workspaces/{id}/caps` through `workspace.resize()`), and waits until the resize has finished. It prints
|
|
72
|
+
per resource the change and when it applies, e.g. `memory 2048 → 6144 MiB now` or `memory 4096 → 8192 MiB
|
|
73
|
+
elastic, held 1024 MiB on resume`, with what was clamped to a limit or applied in part. `--json` prints the result
|
|
74
|
+
(`workspace_id`, `operation_id`, `state`, the `memory` / `cpu` / `disk` named, `caps`, and `operation` when one was
|
|
75
|
+
waited for). No resource flag, `--fixed` with `--elastic`, or `--held` with `--fixed` are usage errors (exit 2) with
|
|
76
|
+
no request. Ctrl-C names the operation, which continues server side.
|
|
77
|
+
|
|
78
|
+
### Memory hint for commands
|
|
79
|
+
|
|
80
|
+
- `shard ws exec --resource-hint auto|light|heavy` and `shard ws exec-start --resource-hint …` send `resource_hint`
|
|
81
|
+
with the exec start: `heavy` gives an elastic workspace its memory before the command starts, `light` starts it at
|
|
82
|
+
once, `auto` (the default) decides from the command. Without the flag nothing is sent. On a file-first workspace
|
|
83
|
+
`--resource-hint` is a usage error (exit 2).
|
|
84
|
+
|
|
85
|
+
### Elastic memory
|
|
86
|
+
|
|
87
|
+
- `--memory-held` on `shard ws open` / `shard ws fork` no longer needs `--allocation-mode elastic`: without a mode the
|
|
88
|
+
API decides (with elastic-by-default enabled for the organization a new workspace is elastic; otherwise
|
|
89
|
+
`requires_elastic`). With `--allocation-mode fixed` it stays a usage error.
|
|
90
|
+
|
|
24
91
|
## 0.8.1 (not yet published)
|
|
25
92
|
|
|
26
93
|
Needs `@shardflux/sdk` 0.13.1 or later.
|
package/README.md
CHANGED
|
@@ -37,14 +37,11 @@ Or run it without installing: `npx @shardflux/cli --help`. The unscoped
|
|
|
37
37
|
|
|
38
38
|
## Quick start
|
|
39
39
|
|
|
40
|
-
No account yet?
|
|
41
|
-
|
|
40
|
+
No account yet? One command (0.9.0+) creates it, signs you in and saves an API key: no browser, no
|
|
41
|
+
password. With the Codex CLI signed in with ChatGPT on this machine, your email is verified by it.
|
|
42
42
|
|
|
43
43
|
```sh
|
|
44
|
-
|
|
45
|
-
shard auth verify-email 'https://app.shardflux.dev/auth/verify-email#token=...' # the link from the email
|
|
46
|
-
printf '%s\n' "$PASSWORD" | shard auth login --email you@example.com
|
|
47
|
-
shard setup # organization, project and an API key, saved
|
|
44
|
+
shard signup # or: shard signup --email you@example.com
|
|
48
45
|
shard workspaces open acme/demo --template python-node-browser
|
|
49
46
|
shard ws exec acme/demo -- python3 -c 'print(40 + 2)'
|
|
50
47
|
shard files write acme/demo /home/user/notes.txt --from notes.txt
|
|
@@ -111,14 +108,14 @@ npm test 2>&1 | tail -n 60 | shard feedback --category bug --workspace acme/demo
|
|
|
111
108
|
`shard` is built to be driven by an agent: no browser, no prompts when standard input is not a
|
|
112
109
|
terminal, `--json` on every command, secrets only on standard input, and documented exit codes.
|
|
113
110
|
|
|
114
|
-
1. **Account:** `
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
111
|
+
1. **Account (0.9.0+):** `shard signup --json`. With the Codex CLI signed in with ChatGPT on the
|
|
112
|
+
machine it signs up (or signs in) verified by that login; otherwise pass `--email <email>` and the
|
|
113
|
+
account works at once on the Free plan. It then runs `shard setup`: an organization, a project and
|
|
114
|
+
an API key with every workspace tool, saved in the credentials file. With two-factor authentication
|
|
115
|
+
it exits 4 with `mfa_required`: ask the person for the code, then `shard auth mfa --code <code>`.
|
|
116
|
+
2. **Verify the email** (an `--email` signup, to start the trial): `shard verify --json` emails a
|
|
117
|
+
6-digit code; ask the person for it, then `shard verify <code>`. Nothing is signed out.
|
|
118
|
+
3. **Set up again any time:** `shard setup --json` is idempotent.
|
|
122
119
|
4. **Work:** `shard ws open <key> --template <slug> --json`, `shard ws exec <key> -- <cmd>`,
|
|
123
120
|
`shard files ...` use the saved key.
|
|
124
121
|
5. **A paid plan:** `shard billing plans`, then `shard billing upgrade <plan> --json` prints the Stripe
|
|
@@ -132,12 +129,15 @@ terminal, `--json` on every command, secrets only on standard input, and documen
|
|
|
132
129
|
7. **Feedback:** send `shard feedback` as you work, the moment something fails, confuses you or is
|
|
133
130
|
missing, or your user asks for an improvement (see [Feedback](#feedback-agents-use-this-while-you-work)).
|
|
134
131
|
|
|
135
|
-
What
|
|
136
|
-
|
|
132
|
+
What a person does: entering a card in Stripe Checkout, the authenticator app's codes, and (for an
|
|
133
|
+
`--email` signup) reading the 6-digit code.
|
|
137
134
|
|
|
138
135
|
## Accounts and sign-in (0.5.0+)
|
|
139
136
|
|
|
140
137
|
```sh
|
|
138
|
+
shard signup [--email you@example.com] [--name "Ada Lovelace"] [--no-codex] [--no-setup] # 0.9.0+
|
|
139
|
+
shard verify [<code>] # 0.9.0+: emails a 6-digit code, then confirms it
|
|
140
|
+
shard auth login --codex # 0.9.0+: sign in with the Codex login on this machine
|
|
141
141
|
printf '%s\n' "$PASSWORD" | shard auth register --email you@example.com [--name "Ada Lovelace"]
|
|
142
142
|
shard auth verify-email '<link from the email>' # or just the token in it
|
|
143
143
|
shard auth resend-verification # signed in, email not verified yet
|
|
@@ -147,6 +147,7 @@ shard auth status # session and saved key,
|
|
|
147
147
|
shard auth sessions [--revoke <session-id>] # browser and CLI sessions
|
|
148
148
|
shard auth logout [--all]
|
|
149
149
|
printf '%s\n' "$PASSWORD" | shard auth step-up [--code 123456]
|
|
150
|
+
shard auth step-up --codex [--code 123456] # 0.9.0+: confirm with the linked Codex login
|
|
150
151
|
printf '%s\n%s\n' "$CURRENT" "$NEW" | shard auth password change
|
|
151
152
|
shard auth password reset --email you@example.com
|
|
152
153
|
printf '%s\n' "$NEW" | shard auth password reset-confirm '<link from the email>'
|
|
@@ -157,6 +158,12 @@ shard auth totp disable --code 123456
|
|
|
157
158
|
shard auth totp recovery-codes
|
|
158
159
|
```
|
|
159
160
|
|
|
161
|
+
- **`shard signup`** (0.9.0+) asks the Codex CLI on this machine to refresh its ChatGPT login
|
|
162
|
+
(`codex app-server`) and sends the ID token from `$CODEX_HOME/auth.json` (default `~/.codex`), never
|
|
163
|
+
Codex's access or refresh token. The account is verified and starts with its trial; an account that
|
|
164
|
+
already uses that ChatGPT identity or email is signed in instead. Without a Codex login, `--email`
|
|
165
|
+
creates an account that works at once on the Free plan; `shard verify` starts the trial.
|
|
166
|
+
`--no-codex` uses `--email` even when Codex is signed in; `--no-setup` skips `shard setup`.
|
|
160
167
|
- **Passwords never come from arguments** (`--password` is refused). On a terminal `shard` asks without
|
|
161
168
|
echo (a new password twice); otherwise it reads standard input, one line per secret: `auth password
|
|
162
169
|
change` reads the current password, then the new one. Emailed links and tokens are single-use
|
|
@@ -177,7 +184,7 @@ shard auth totp recovery-codes
|
|
|
177
184
|
it from standard input (or asks), sets it, and otherwise prints the `auth password reset-confirm`
|
|
178
185
|
command to run.
|
|
179
186
|
- After `auth login`, `shard` prints who you are, whether the email is verified, your organizations
|
|
180
|
-
and the next step (`shard setup`, or `shard
|
|
187
|
+
and the next step (`shard setup`, or `shard verify`).
|
|
181
188
|
|
|
182
189
|
## Setup (0.5.0+)
|
|
183
190
|
|
|
@@ -378,8 +385,8 @@ shows the status; `shard version --check` asks now (`--json`: `{"cli", "sdk", "u
|
|
|
378
385
|
| `workspaces list [--state S] [--prefix P] [--lifetime persistent\|session\|any] [--purpose standard\|template_draft\|template_test\|any] [--include-deleted] [--all] [--limit N] [--cursor C]` | One page, or every page with `--all`. The next cursor is printed on stderr. By default only persistent standard workspaces are listed. A file-first workspace's state reads `running (file-first)` (0.5.0+). |
|
|
379
386
|
| `workspaces get <id\|key>` | One workspace (deleted ones included), with the startup of its template's start commands and services (0.4.0+): a failed step shows its exit code, reason and output tail. Its mode, and a file-first workspace's tree revision (0.5.0+). Its memory (0.8.0+): `fixed 4096 MiB`, or `elastic: promised …, held …, plugged +… MiB`. The template version whose [immutable paths](#immutable-paths-080) it has mounted (0.8.0+): `immutable paths v3 (mounted read-only)`. |
|
|
380
387
|
| `workspaces inputs <id\|key>` | The workspace's text inputs (0.4.0+). |
|
|
381
|
-
| `workspaces exec <id\|key> [--cwd D] [--env K=V]... [--timeout T] [--stdin F\|-] [-v] [--execution-id ID] [--output-limit N] [--burst [--burst-vcpus N] [--burst-memory MIB]] -- <cmd> [args...]` | Runs argv with no shell. Output is streamed (in the start request itself, 0.8.0+) and resumes from byte offsets after dropped connections. `shard` exits with the command's exit code. Ctrl-C cancels the command. `-v` (0.5.0+) then prints the session id and exit status on stderr, and the memory grow the command waited for on an elastic workspace (0.8.0+; `--json`: `memory_grow`). `--cwd` is an absolute path (default `/home/user`); a relative one is refused (`invalid_cwd`, exit 2). 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 (0.5.1+; before, it exited 1 with no output). On a file-first workspace (0.5.0+) the command runs as an execution instead: see [File-first workspaces](#file-first-workspaces). `--burst` (0.8.0+): [burst execution](#burst-execution-080). |
|
|
382
|
-
| `workspaces exec-start <id\|key> [--session-id ID] [--cwd D] [--timeout T] [--stdin-open] -- <cmd> [args...]`, `workspaces exec-read <id\|key> <session-id> [--follow]`, `workspaces exec-cancel <id\|key> <session-id> [--grace D]` | Background commands (0.8.0+): start a command and return at once, read its output and state (`--follow` streams it to its exit and exits with its code; while it runs `exec-read` exits 5), stop it. See [Background commands](#background-commands-080). |
|
|
388
|
+
| `workspaces exec <id\|key> [--cwd D] [--env K=V]... [--timeout T] [--stdin F\|-] [-v] [--execution-id ID] [--output-limit N] [--resource-hint auto\|light\|heavy] [--burst [--burst-vcpus N] [--burst-memory MIB]] -- <cmd> [args...]` | Runs argv with no shell. Output is streamed (in the start request itself, 0.8.0+) and resumes from byte offsets after dropped connections. `shard` exits with the command's exit code. Ctrl-C cancels the command. `-v` (0.5.0+) then prints the session id and exit status on stderr, and the memory grow the command waited for on an elastic workspace (0.8.0+; `--json`: `memory_grow`). `--cwd` is an absolute path (default `/home/user`); a relative one is refused (`invalid_cwd`, exit 2). 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 (0.5.1+; before, it exited 1 with no output). On a file-first workspace (0.5.0+) the command runs as an execution instead: see [File-first workspaces](#file-first-workspaces). `--burst` (0.8.0+): [burst execution](#burst-execution-080). `--resource-hint` (0.9.0+): [elastic memory](#elastic-memory-080). |
|
|
389
|
+
| `workspaces exec-start <id\|key> [--session-id ID] [--cwd D] [--timeout T] [--stdin-open] [--resource-hint auto\|light\|heavy] -- <cmd> [args...]`, `workspaces exec-read <id\|key> <session-id> [--follow]`, `workspaces exec-cancel <id\|key> <session-id> [--grace D]` | Background commands (0.8.0+): start a command and return at once, read its output and state (`--follow` streams it to its exit and exits with its code; while it runs `exec-read` exits 5), stop it. See [Background commands](#background-commands-080). |
|
|
383
390
|
| `executions get <id\|key> <execution-id> [--wait D]` | The result of a file-first workspace's execution (0.5.0+): its output, then what ran. Exits with the command's code, 6 if the execution failed or was lost, 5 while it still runs. |
|
|
384
391
|
| `files read <id\|key> <path> [--out F]` | Raw bytes to stdout, or to a local file. |
|
|
385
392
|
| `files write <id\|key> <path> [--from F\|-] [--append] [--no-parents] [--if-revision N]` | Atomic write. The default source is stdin. `--if-revision` (0.5.0+): file-first workspaces only, see [Tree revisions](#tree-revisions). |
|
|
@@ -391,6 +398,7 @@ shows the status; `shard version --check` asks now (`--json`: `{"cli", "sdk", "u
|
|
|
391
398
|
| `workspaces suspend <id\|key> --durable [--timeout T]` | (0.7.0+) Suspend and wait until the copy is in durable storage. See "Durable storage". |
|
|
392
399
|
| `workspaces suspend <id\|key> --when-idle D` / `--cancel-when-idle` | (0.5.1+) Suspend once the workspace has been idle for `D` (0 to 1h; `0` = as soon as it is idle, 0.6.1+), or cancel that. See "Suspend when idle". |
|
|
393
400
|
| `workspaces fork <id\|key> <new-key> [caps] [--allocation-mode fixed\|elastic] [--memory-held N] [--wait]` | Fork into a new key. Without caps the fork keeps the source's caps and memory allocation (0.8.0+). With `--wait` the API holds the fork until the copy runs and returns it ready in the same request (0.8.0+; `--timing` shows one `request` phase marked `(held)`). |
|
|
401
|
+
| `workspaces resize <id\|key> [--memory MIB] [--held MIB] [--fixed\|--elastic] [--cpu MILLIS] [--disk GIB] [--timeout 5m] [--timing]` | Change the memory, CPU and disk of a running or suspended workspace without a restart (0.9.0+). Prints per resource the change and when it applies (`now`, `on resume`, `next start`). See [Resize a workspace](#resize-a-workspace-090). |
|
|
394
402
|
| `workspaces delete <id\|key> --yes [--wait]` | Delete the workspace. Tool access ends at once. After deletion finishes, the key can open a new workspace ID. |
|
|
395
403
|
| `workspaces close <id\|key> [--wait]` | End a session workspace now: it is deleted, and the key then opens a new workspace. A persistent workspace is refused (`not_session`). |
|
|
396
404
|
| `workspaces reset <id\|key> --yes [--wait]` | Layered workspaces: wipe every change and restart on the template. The previous state stays restorable for 7 days. |
|
|
@@ -398,6 +406,8 @@ shows the status; `shard version --check` asks now (`--json`: `{"cli", "sdk", "u
|
|
|
398
406
|
| `workspaces changes <id\|key> [--path P] [--hash] [--summary] [--all] [--limit N] [--cursor C]` | What a layered, running workspace changed against its template. |
|
|
399
407
|
| `workspaces sessions <id\|key>` | Attributed agent sessions: label, principal and tokens issued. |
|
|
400
408
|
| `workspaces secrets <id\|key> [--set NAME]... [--clear]` | Show the secret names bound to the workspace and their status, or replace them. |
|
|
409
|
+
| `workspaces port expose <id\|key> <port>`, `workspaces port ls <id\|key>`, `workspaces port close <id\|key> <port>` | Serve a port of the workspace at its own private HTTPS URL, list the exposed ports, close one (0.9.0+; see [Inbound ports](#inbound-ports-090)). |
|
|
410
|
+
| `workspaces port token <id\|key> <port> [--ttl D]`, `workspaces port link <id\|key> <port> [--ttl D] [--path P]`, `workspaces port callback <id\|key> <port> [--revoke]` | A port token (printed alone), a link that opens the port in a browser, the port's callback URL for webhooks and OAuth redirects (0.9.0+). |
|
|
401
411
|
| `secrets create <NAME> [--from-file F] [--description T] [--tool T]... [--allow-workspace ID]... [--org ID [--allow-project ID]... [--all-projects]]` | Create a secret. The value comes from standard input or `--from-file`, never from an argument. |
|
|
402
412
|
| `secrets list [--org ID] [--include-deleted] [--all]`, `secrets get <id\|NAME>` | Secret metadata. Values are never shown. |
|
|
403
413
|
| `secrets update <id\|NAME> [--description T] [--tool T]... [--allow-workspace ID]... [--any-workspace] [--allow-project ID]... [--all-projects] [--clear-projects]` | Change the description or usage permissions. |
|
|
@@ -650,19 +660,40 @@ shard ws suspend acme/demo --cancel-when-idle
|
|
|
650
660
|
|
|
651
661
|
## Elastic memory (0.8.0+)
|
|
652
662
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
instruction
|
|
663
|
+
A workspace can hold only the memory its commands use and grow up to `--memory-mib` when they need more; billing counts
|
|
664
|
+
the memory it holds. It idles at `--memory-held` (default 1024 MiB). Package installs, test runners, compilers and
|
|
665
|
+
bundlers get their memory before they start, so they see what they need from their first instruction; everything else
|
|
666
|
+
starts at once and the workspace grows while it runs.
|
|
656
667
|
|
|
657
668
|
```sh
|
|
658
669
|
shard ws open acme/demo --template python-node-browser --memory-mib 8192 --allocation-mode elastic
|
|
659
670
|
shard ws get acme/demo # memory elastic: promised 8192 MiB, held 1024 MiB, plugged +3072 MiB
|
|
660
671
|
shard ws exec acme/demo -v -- npm test # memory grow delivered 1024 -> 4096 MiB in 175 ms
|
|
672
|
+
shard ws exec acme/demo --resource-hint heavy -- python3 train.py # 0.9.0+: memory first, then the command
|
|
661
673
|
```
|
|
662
674
|
|
|
663
|
-
|
|
675
|
+
`--allocation-mode fixed` gives a static allocation of `--memory-mib`. `--resource-hint` (0.9.0+) is `auto` (the
|
|
676
|
+
default: decided from the command), `heavy` or `light`. `--json` output carries `memory` on the workspace and
|
|
664
677
|
`memory_grow` on a command that grew it.
|
|
665
678
|
|
|
679
|
+
## Resize a workspace (0.9.0+)
|
|
680
|
+
|
|
681
|
+
Change the memory, CPU and disk of any workspace, running or suspended, fixed or elastic, without a restart:
|
|
682
|
+
|
|
683
|
+
```sh
|
|
684
|
+
$ shard ws resize acme/demo --memory 6144 --disk 20
|
|
685
|
+
Resized acme/demo (0f6c…), running:
|
|
686
|
+
memory 2048 → 6144 MiB now
|
|
687
|
+
disk 10 → 20 GiB now
|
|
688
|
+
|
|
689
|
+
$ shard ws resize acme/demo --elastic --held 1024 # switch modes live
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
Memory changes live, and disks grow online. A suspended workspace gets its new size when it resumes, before its first
|
|
693
|
+
call. CPU changes live within the vCPUs the workspace booted with; a larger CPU size applies at the next start. Each
|
|
694
|
+
resource says when it applies (`now`, `on resume` or `next start`), and the new caps are stored, so every later start
|
|
695
|
+
uses them. `--json` prints the result with `applies_at` per resource and the stored `caps`.
|
|
696
|
+
|
|
666
697
|
## Burst execution (0.8.0+)
|
|
667
698
|
|
|
668
699
|
Run one heavy command, such as a cold build or a full test suite, on a larger VM without resizing the workspace:
|
|
@@ -695,6 +726,31 @@ shard ws exec-cancel acme/demo build-1 --grace 10s
|
|
|
695
726
|
code and output.
|
|
696
727
|
- `exec-cancel` sends SIGTERM, then SIGKILL after `--grace` (default 5s, at most 60s).
|
|
697
728
|
|
|
729
|
+
## Inbound ports (0.9.0+)
|
|
730
|
+
|
|
731
|
+
Serve a port of a workspace at its own HTTPS URL: a preview of the app your agent is building, a webhook receiver, an
|
|
732
|
+
OAuth redirect, a live view. A request wakes a parked or suspended workspace and is answered once it runs. Every port
|
|
733
|
+
is private: a request carries a port token, a browser link's session, or arrives on the port's callback URL.
|
|
734
|
+
|
|
735
|
+
```sh
|
|
736
|
+
shard ws exec-start acme/demo -- python3 -m http.server 3000 --bind 0.0.0.0
|
|
737
|
+
shard ws port expose acme/demo 3000 # https://3000-<handle>.shardflux.app
|
|
738
|
+
curl -H "Authorization: Bearer $(shard ws port token acme/demo 3000)" https://3000-<handle>.shardflux.app/
|
|
739
|
+
shard ws port link acme/demo 3000 --path /dashboard # open it in a browser
|
|
740
|
+
shard ws port callback acme/demo 3000 # register <url>webhooks/github with GitHub
|
|
741
|
+
shard ws port close acme/demo 3000
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
- The server inside the workspace listens on `0.0.0.0`, not only `127.0.0.1`.
|
|
745
|
+
- `expose` is idempotent: an exposed port keeps its URL, tokens, links and callback URL. `port ls` lists them.
|
|
746
|
+
- `token` prints the token alone on stdout (`--ttl` 1m to 24h, default 1h). Send it as `Authorization: Bearer
|
|
747
|
+
<token>`, or as `X-Shardflux-Token` when the app reads `Authorization` itself.
|
|
748
|
+
- `link` prints a URL that starts a browser session for the port (`--ttl` 1m to 7d, default 24h) and lands on
|
|
749
|
+
`--path`. Anyone with the link can open the port until it expires.
|
|
750
|
+
- `callback` prints the callback URL once; a request to `<url><rest>` reaches `/<rest>` without a token. Running it
|
|
751
|
+
again replaces the URL; `--revoke` removes it.
|
|
752
|
+
- `close` stops the port's tokens, links and callback URL at once.
|
|
753
|
+
|
|
698
754
|
## Start deadlines
|
|
699
755
|
|
|
700
756
|
A queued open, resume or fork (`capacity_pending`) has a deadline 15 minutes after it was created.
|
|
@@ -833,6 +889,10 @@ printf %s "$NEW_KEY" | shard secrets rotate OPENAI_API_KEY
|
|
|
833
889
|
- `secrets create`/`get`/`update` print the secret's metadata; `list`, `versions` and `access-log`
|
|
834
890
|
print `{data, next_cursor}`; `rotate` prints `{secret, version}`; `delete` prints
|
|
835
891
|
`{deleted, id, name, scope}`; `workspaces secrets` prints `{workspace_id, names, secrets}`.
|
|
892
|
+
- `workspaces port expose` prints the port `{port, url, created_at, callback}`; `port ls` prints `{ports}`;
|
|
893
|
+
`port token` prints `{token, expires_at, url}` (`jq -r .token`); `port link` prints `{url, expires_at}`;
|
|
894
|
+
`port callback` prints `{url, created_at}`; `port close` prints `{workspace_id, port, closed}` and
|
|
895
|
+
`port callback --revoke` prints `{workspace_id, port, revoked}` (0.9.0+).
|
|
836
896
|
- Account commands (0.5.0+) print the API's objects too: lists are `{data, next_cursor}` (with
|
|
837
897
|
`default_organization_id`, `default_project_id` or `saved_api_key_id` where a default applies);
|
|
838
898
|
`auth login`/`auth mfa` print `{status, user, session: {expires_at, credentials_file}, organizations,
|
|
@@ -917,3 +977,7 @@ shard ws exec-input qm/project-42 qm-worker-1 --offset 5 --close
|
|
|
917
977
|
```
|
|
918
978
|
|
|
919
979
|
Use the byte offset in each acknowledgement, including partial writes. `ws resume` can recover a failed workspace with its existing ID and disk. A completed delete frees the key; old IDs remain deleted. Protocol-error JSON includes `source`; HTTP 404 alone does not mean a workspace was deleted.
|
|
980
|
+
|
|
981
|
+
### Prepare an imminent command (0.9.0+)
|
|
982
|
+
|
|
983
|
+
Call `shard ws hint <workspace>` ahead of a tool call to stage a parked workspace while the input is prepared. It returns without waiting for restore. Resume a suspended workspace first. The hint is explicit; ordinary commands add no early hint.
|
package/dist/account-args.js
CHANGED
|
@@ -40,6 +40,30 @@ const VOLUME_WAIT = {
|
|
|
40
40
|
timeout: { type: 'string', value: '<duration>', description: 'Give up waiting after this long (default 5m); the operation continues server side.' },
|
|
41
41
|
};
|
|
42
42
|
export const ACCOUNT_COMMANDS = [
|
|
43
|
+
// ---- agent signup (0.9.0+) -----------------------------------------------------------------------------
|
|
44
|
+
{
|
|
45
|
+
path: ['signup'],
|
|
46
|
+
summary: 'Create your account and get ready to run workspaces in one command: no browser, no password',
|
|
47
|
+
description: 'Signs up with the Codex login on this machine (ChatGPT): your email is verified by it, so the account starts with its trial, and an account that already uses that ChatGPT identity or email is signed in instead. Without a Codex login, pass --email: the account works at once on the Free plan, and "shard verify" starts the trial. Then it runs "shard setup" (organization, project and an API key, saved) unless --no-setup. Two-factor accounts: pass --code or type it at the prompt.',
|
|
48
|
+
positionals: [],
|
|
49
|
+
options: {
|
|
50
|
+
email: { type: 'string', value: '<email>', description: 'Your email address, used when there is no Codex login (or with --no-codex).' },
|
|
51
|
+
name: { type: 'string', value: '<display name>', description: 'Your name as others see it (setup names the organization after it).' },
|
|
52
|
+
codex: { type: 'boolean', description: 'Use the Codex login on this machine (default; --no-codex signs up with --email).' },
|
|
53
|
+
setup: { type: 'boolean', description: 'Run shard setup afterwards (default; --no-setup skips it).' },
|
|
54
|
+
tool: { type: 'string', multiple: true, value: '<tool>', description: 'Workspace tool the saved API key may use (repeatable; exec, files, pty, process, git, browser). Default: all.' },
|
|
55
|
+
...SECOND_FACTOR,
|
|
56
|
+
},
|
|
57
|
+
examples: ['shard signup', 'shard signup --email you@example.com', 'shard signup --no-codex --email you@example.com --name "Ada Lovelace"'],
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
path: ['verify'],
|
|
61
|
+
summary: 'Verify your email with a 6-digit code: emails the code, then confirm it',
|
|
62
|
+
description: 'Without a code it emails one (valid 15 minutes) and, on a terminal, asks for it; otherwise pass it next: "shard verify <code>". Nothing is signed out and saved API keys keep working; an account from "shard signup" gets its trial.',
|
|
63
|
+
positionals: [{ name: 'code', required: false }],
|
|
64
|
+
options: {},
|
|
65
|
+
examples: ['shard verify', 'shard verify 123456'],
|
|
66
|
+
},
|
|
43
67
|
// ---- sign-in (auth) ------------------------------------------------------------------------------------
|
|
44
68
|
{
|
|
45
69
|
path: ['auth', 'register'],
|
|
@@ -66,8 +90,12 @@ export const ACCOUNT_COMMANDS = [
|
|
|
66
90
|
summary: 'Sign in: saves a session for this API in the credentials file (the password is read from standard input or a prompt)',
|
|
67
91
|
description: 'Two-factor accounts: pass --code (or --recovery-code), or type the code at the prompt; without either the pending sign-in is saved and "shard auth mfa --code <code>" completes it within 10 minutes (exit 4 until then). Prints who you are, your organizations and the next step. A session lasts 30 days of use (90 at most). SHARDFLUX_SESSION_TOKEN, when set, is used instead of the saved session.',
|
|
68
92
|
positionals: [],
|
|
69
|
-
options: {
|
|
70
|
-
|
|
93
|
+
options: {
|
|
94
|
+
email: { type: 'string', value: '<email>', description: 'Your email address (required without --codex).' },
|
|
95
|
+
codex: { type: 'boolean', description: 'Sign in with the Codex login on this machine instead of a password (0.9.0+; creates the account when there is none).' },
|
|
96
|
+
...SECOND_FACTOR,
|
|
97
|
+
},
|
|
98
|
+
examples: [`printf '%s\\n' "$PASSWORD" | shard auth login --email you@example.com`, `printf '%s\\n' "$PASSWORD" | shard auth login --email you@example.com --code 123456`, 'shard auth login --codex'],
|
|
71
99
|
},
|
|
72
100
|
{
|
|
73
101
|
path: ['auth', 'mfa'],
|
|
@@ -98,9 +126,9 @@ export const ACCOUNT_COMMANDS = [
|
|
|
98
126
|
{
|
|
99
127
|
path: ['auth', 'step-up'],
|
|
100
128
|
summary: 'Confirm your password (and code) for sensitive actions: valid 10 minutes',
|
|
101
|
-
description: 'Needed for two-factor changes, an email change, data exports and deletions. On a terminal "shard" asks by itself when the API requires it; scripts run this first. The password comes from standard input or a prompt;
|
|
129
|
+
description: 'Needed for two-factor changes, an email change, data exports and deletions. On a terminal "shard" asks by itself when the API requires it; scripts run this first. The password comes from standard input or a prompt; with --codex (0.9.0+) the Codex login linked to the account confirms it instead. Two-factor accounts add --code (or type it at the prompt).',
|
|
102
130
|
positionals: [],
|
|
103
|
-
options: { ...SECOND_FACTOR },
|
|
131
|
+
options: { codex: { type: 'boolean', description: 'Confirm with the Codex login on this machine instead of the password (accounts it signs in to).' }, ...SECOND_FACTOR },
|
|
104
132
|
examples: [`printf '%s\\n' "$PASSWORD" | shard auth step-up`, `printf '%s\\n' "$PASSWORD" | shard auth step-up --code 123456`],
|
|
105
133
|
},
|
|
106
134
|
{
|