ghostdock 0.0.19 → 0.1.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/dist/cli.md DELETED
@@ -1,923 +0,0 @@
1
- # Ghostdock CLI
2
-
3
- Command-line access to your Ghostdock account — built for agents, but usable by humans too.
4
- Authenticate once, then call Ghostdock's tools without leaving the terminal.
5
-
6
- This document is written for an agent (or human) driving the CLI directly. It is also published at
7
- `https://ghostdock.brainchimps.com/cli.md` so an agent can `curl`/fetch it without cloning this repo.
8
-
9
- ## Install / run
10
-
11
- No install required — run it with `npx`:
12
-
13
- ```bash
14
- npx ghostdock --help
15
- ```
16
-
17
- Or install it globally:
18
-
19
- ```bash
20
- npm install -g ghostdock
21
- ghostdock --help
22
- ```
23
-
24
- A global install also gives you `gdock`, a short name for the same CLI. Help
25
- and hints use whichever name you typed. With `npx`, use `npx ghostdock`:
26
- `npx gdock` does not work.
27
-
28
- Inside this monorepo (for development), run from the repo root or `packages/cli`:
29
-
30
- ```bash
31
- bun run --cwd packages/cli build # bundles src/index.ts -> dist/index.js
32
- bun run --cwd packages/cli dev -- --help # run from source without building
33
- ```
34
-
35
- ## Output: for people, and `--json` for scripts and agents
36
-
37
- Every command prints for people by default: one line per event, a symbol, then the message.
38
-
39
- ```
40
- $ ghostdock sandboxes list
41
- ⚓ Marketing site quiet-harbor running
42
- ◌ teal-jetty stopped
43
- $ ghostdock sites publish ./dist
44
- ↗ https://foggy-teal-bollard.static.ghostdock.app
45
- ✓ Published site foggy-teal-bollard.
46
- ```
47
-
48
- `⚓` ready, `✓` done, `↗` a URL, `◌` stopped or gone, `✗` failed, `▂▄▆` in progress. Every line
49
- carries the name and id the next command needs.
50
-
51
- Commands that wait show a progress line on stderr while they run. Starting a sandbox
52
- (`sandboxes create`, `sandboxes wake`) prints how long each step took, measured on the server, each
53
- step with its own time:
54
-
55
- ```
56
- $ ghostdock sandboxes wake quiet-harbor
57
- ⚓ quiet-harbor running
58
- ⚓ sandbox started in 125ms
59
- ✓ container started in 3.0s
60
- ```
61
-
62
- The container line is missing when no container was started, or when the host is older and did
63
- not report it. `sandboxes status` prints the same lines for the last start. With `--json` they are
64
- the `boot` field: `{ trigger, sandbox: { startedAt, readyAt, ms }, container: { … } | null }`, or
65
- `null` when the command started nothing.
66
-
67
- **Scripts and agents pass `--json`.** It prints the result as one JSON document on stdout, with
68
- every field, and nothing else there. It works on every command and anywhere on the line:
69
-
70
- ```bash
71
- ghostdock sandboxes list --json | jq -r '.sandboxes[].name'
72
- ```
73
-
74
- - **stdout is the result, stderr is everything else**: notices (`Using organization acme …`),
75
- hints and errors. Piping stdout never picks up a notice.
76
- - **Errors** print as `✗ <what went wrong and what to try>` on stderr and exit non-zero, with or
77
- without `--json`.
78
- - **Colour** only on a terminal: piped output and `NO_COLOR=1` get the same text without colour
79
- codes. `FORCE_COLOR=1` turns it back on.
80
-
81
- ## Global flags
82
-
83
- ```
84
- ghostdock --version
85
- ghostdock --base-url <url> <command>
86
- ghostdock <command> --json
87
- ```
88
-
89
- - `--version` / `-v` — print CLI version and exit
90
- - `--base-url <url>` — API origin for this invocation (wins over `GHOSTDOCK_BASE_URL`)
91
- - `--json` — print the result as one JSON document on stdout (see Output above)
92
-
93
- ## Commands
94
-
95
- Commands are grouped by resource, like `gh` or `kubectl`: `ghostdock <resource> <action>`.
96
-
97
- <!-- generated:command-groups:start (bun run sync:cli-reference; do not edit) -->
98
- ```
99
- ghostdock apps Published apps of an organization.
100
- ghostdock docker Docker over the private network: a sandbox's Docker engine from this machine.
101
- ghostdock env Manage organization environment variables and secrets.
102
- ghostdock images Organization image catalog: OCI bookmarks, Dockerfiles and Compose files.
103
- ghostdock login Sign in and store a device access token for this machine…
104
- ghostdock logout Revoke the device session and remove stored credentials.
105
- ghostdock network The private network: reach your sandboxes by address and name from this machine.
106
- ghostdock organizations Organizations you belong to.
107
- ghostdock projects Deployable projects, their deployments and environment.
108
- ghostdock providers Sandbox providers of an organization.
109
- ghostdock registry Log in to the organization container registry.
110
- ghostdock sandboxes Create, run and manage sandboxes.
111
- ghostdock sites Static sites on the CDN.
112
- ghostdock skills List and read Agent Skills (same catalog as MCP skill://index.json).
113
- ghostdock snapshots Sandbox snapshots.
114
- ghostdock tools List available agent tools.
115
- ghostdock whoami Show the account this CLI is currently authenticated as.
116
- ```
117
- <!-- generated:command-groups:end -->
118
-
119
- Run `ghostdock <command> --help` at any level for its subcommands or flags, e.g.
120
- `ghostdock sandboxes --help` or `ghostdock sandboxes urls create --help`.
121
-
122
- Most commands are generated from the tool catalog — see **Invoking a tool** below. Every command
123
- is listed in the [command index](#command-index); [`cli-reference.md`](cli-reference.md) has each
124
- one's full description and flags.
125
-
126
- ### Choosing an organization
127
-
128
- Every organization-scoped command acts on one organization, taken from the first of:
129
-
130
- 1. `--org <id-or-slug>` on the command
131
- 2. the `GHOSTDOCK_ORG` environment variable
132
- 3. the default set with `ghostdock organizations use <id-or-slug>`, stored in
133
- `~/.config/ghostdock/settings.json`
134
-
135
- With one organization there is nothing to do: `login` makes it the default, and every command,
136
- in any directory, uses it.
137
-
138
- ```bash
139
- ghostdock organizations use acme # the default (login sets one when it can)
140
- ghostdock sandboxes list # stderr: Using organization acme (default from ~/.config/ghostdock/settings.json)
141
- ghostdock sandboxes list --org beta # --org always wins
142
- ghostdock organizations current # which organization, and where it comes from
143
- ghostdock organizations use --clear
144
- ```
145
-
146
- When the organization does not come from `--org`, the command says which one it uses on stderr,
147
- so a default never acts silently. The default is stored next to the credentials, so it belongs to
148
- the same login. **Scripts and CI should pass `--org` or set `GHOSTDOCK_ORG`** rather than depend on
149
- (or change) a stored default, and use the organization id: renaming an organization changes its
150
- slug, not its id.
151
-
152
- ### `ghostdock login`
153
-
154
- Ghostdock uses a device-authorization flow: no password is ever typed into the terminal.
155
-
156
- **Default (print-and-exit) — best when a human is present to click the link:**
157
-
158
- ```bash
159
- ghostdock login
160
- ```
161
-
162
- This prints a URL to open in a browser and exits `0` immediately — it does not prompt for input or
163
- poll for approval. Approve the request in the browser, then complete login with
164
- **`ghostdock login --code <paste-code>`**, redeeming the one-time code from the browser's
165
- "Having trouble? Show code" link (see below).
166
-
167
- Each `login` invocation starts a **new** device session. A later `login --wait` does **not** resume
168
- polling for a prior plain `login`. To block until approval, run **`ghostdock login --wait` up
169
- front** instead of plain `login`.
170
-
171
- **`--wait` — poll until approved:**
172
-
173
- ```bash
174
- ghostdock login --wait
175
- # or with a custom timeout (seconds, default 300):
176
- ghostdock login --wait --timeout 120
177
- ```
178
-
179
- Prints the same URL, then polls the server every few seconds until the login is approved, denied,
180
- or the timeout elapses. Exits `0` on success, non-zero otherwise.
181
-
182
- **`--code` — paste-code fallback:**
183
-
184
- If the CLI can't poll (e.g. it's running in a sandbox with no long-lived process, or the browser
185
- approval happened on a different machine), the browser's "Having trouble? Show code" link reveals a
186
- short one-time code. Redeem it directly:
187
-
188
- ```bash
189
- ghostdock login --code <paste-code>
190
- ```
191
-
192
- On success, credentials are written and the command exits `0`. If the code hasn't been approved
193
- yet, it exits `1` — approve it in the browser first.
194
-
195
- Credentials are stored per machine, in `~/.config/ghostdock/credentials.json` (see
196
- [Credentials file](#credentials-file)), so one login works in every directory.
197
-
198
- **Default organization after login.** Once logged in (with `--wait` or `--code`), `login` sets the
199
- default organization when that is unambiguous:
200
-
201
- - `--org <id-or-slug>` sets that one, e.g. `ghostdock login --wait --org acme`. If you are not a
202
- member of it, no default is set and `login` exits `1`.
203
- - A default that is still one of your organizations stays as it is.
204
- - With exactly one organization, that one becomes the default.
205
- - With several, a person at a terminal picks one from a numbered list (Enter skips). Without a
206
- terminal (agents, CI) nothing is asked: `login` lists them and points to
207
- `ghostdock organizations use`.
208
-
209
- See [Choosing an organization](#choosing-an-organization) for how commands pick it up.
210
-
211
- ### `ghostdock logout`
212
-
213
- ```bash
214
- ghostdock logout
215
- ```
216
-
217
- Revokes the device session on the server (best-effort — still clears local credentials even if the
218
- server call fails, e.g. when offline) and deletes the credentials file. The default organization
219
- stays.
220
-
221
- ### `ghostdock whoami`
222
-
223
- ```bash
224
- ghostdock whoami
225
- ```
226
-
227
- Prints who the stored access token belongs to and which server it talks to (`--json`:
228
- `{ "userId": ..., "baseUrl": ... }`).
229
- Transparently refreshes an expired access token using the stored refresh token before failing.
230
- Exits `1` with a message if not logged in or the session can't be refreshed.
231
-
232
- ### `ghostdock tools`
233
-
234
- Lists the tool catalog for the authenticated account:
235
-
236
- ```bash
237
- ghostdock tools # name + description, one per line
238
- ghostdock tools --json # the full catalog (including each tool's JSON Schema) as JSON
239
- ```
240
-
241
- Requires login — prints a hint and exits `1` if there's no valid session.
242
-
243
- ### `ghostdock skills`
244
-
245
- Lists and reads **Agent Skills** for the authenticated account — the same catalog MCP
246
- clients discover at `skill://index.json` (SEP-2640 / Agent Skills discovery 0.2.0).
247
- Prefer resources. The MCP tools `skills_list` and `skills_get` are fallbacks for clients that
248
- cannot use `resources/list` and `resources/read` — skip them if those work.
249
-
250
- ```bash
251
- ghostdock skills list # name, description, and skill:// URI per skill
252
- ghostdock skills list --json # official discovery index ($schema + skills[])
253
- ghostdock skills get skill://github/SKILL.md # print SKILL.md
254
- ghostdock skills get github # same, by name
255
- ghostdock skills get org_1/release-notes # organization skill
256
- ```
257
-
258
- `--json` on `get` prints `{ uri, name, description, markdown }`. If the same name exists
259
- in more than one organization, pass the `skill://` URI from the index.
260
-
261
- Requires login — prints a hint and exits `1` if there's no valid session.
262
-
263
- ### Invoking a tool
264
-
265
- Every catalog tool is a command at its own path, with one `--flag` per schema property
266
- (`sandboxProviderId` -> `--sandbox-provider-id`). The one thing a command acts on is positional instead:
267
- `ghostdock sandboxes stop <sandbox-id>`, `ghostdock sandboxes urls delete <url-id>`,
268
- `ghostdock env get <name>`. The organization is always the `--org` flag, by id or slug: a slug is easier to type, an id keeps
269
- working after the organization is renamed (renaming changes the slug). The MCP tool name is the same path joined with
270
- underscores: `ghostdock sandboxes urls create` calls the `sandboxes_urls_create` tool. Run
271
- `ghostdock <command> --help` to see a command's full description, its flags and which are
272
- required; a group's `--help` lists its commands with one line each. Output is a line per item
273
- for people; `--json` prints the tool's result as it comes back over MCP.
274
-
275
- ```bash
276
- ghostdock organizations list
277
- # • Acme org_123
278
- ghostdock organizations list --json
279
- # {"organizations": [{"id": "org_123", "name": "Acme", "slug": "acme"}]}
280
- ```
281
-
282
- Number/boolean flags are parsed from their string form; array/object flags take a raw JSON string
283
- (e.g. `--tags '["a","b"]'`). Requires login — prints a hint and exits `1` if there's no valid
284
- session, or the server's error message (e.g. "Not a member of this organization") on a `4xx`.
285
-
286
- The tool list embedded in the CLI binary is generated at build time from the server's tool catalog
287
- (`bun run sync-catalog` in `packages/cli`), so `--help` and flag parsing work offline; invoking a
288
- tool still requires a network call and a valid session.
289
-
290
- Command descriptions are short on purpose. Concepts and workflows live in the built-in Agent
291
- Skills, the same documents MCP agents read:
292
-
293
- ```bash
294
- ghostdock skills get sandboxes # sources, manifests, lifecycle, providers, URLs and TCP
295
- ghostdock skills get sandbox-boot # processes that must come back after idle-stop
296
- ghostdock skills get environment # organization entries, bindings, local entries, secrets
297
- ghostdock skills get publishing # sites publish vs projects publish, outcomes, redeploys
298
- ghostdock skills get incus-setup # connecting your own Incus host
299
- ```
300
-
301
- ### Sandboxes
302
-
303
- Read `ghostdock skills get sandboxes` before your first sandbox: what it can boot from, manifests,
304
- idle-stop and auto-delete, providers, URLs.
305
-
306
- Every sandbox has a name like `quiet-harbor`, unique within its organization, and every command
307
- that takes a sandbox accepts it with the organization (`--org`, `GHOSTDOCK_ORG` or the default).
308
- The long `sandboxId` in `--json` output works too, in the same organization. A name never changes
309
- while the sandbox exists, so scripts can keep it; once a sandbox is deleted, its name may be given to
310
- a new one later. The display name is a separate label you can edit. For example, create a sandbox,
311
- then expose a URL:
312
-
313
- ```bash
314
- ghostdock sandboxes create --org org_123 --display-name "Marketing site"
315
- ghostdock sandboxes urls create quiet-harbor --port 8080 --auto-wake true --public true
316
- ```
317
-
318
- #### Containers in a sandbox
319
-
320
- On Ghostdock Cloud a sandbox runs one Docker engine; everything in it is an ordinary container.
321
- `ssh get`, `files`, `commands` and `shells` land in one of them: `--container <name>`, else the
322
- sandbox's default container, else the one running container. With several running and no default,
323
- the CLI asks which one at the keyboard and offers to make it the default; without a terminal it
324
- fails and lists the names. A command runs as `docker exec` does there: as the container's
325
- `ghostdock.login.user`, else the image's `USER`, else root.
326
-
327
- ```bash
328
- ghostdock sandboxes containers list quiet-harbor
329
- ghostdock sandboxes default-container quiet-harbor --container web # --clear true removes it
330
- ghostdock sandboxes commands run quiet-harbor --container db --command 'pg_isready'
331
- ghostdock sandboxes containers protection quiet-harbor workstation --protected false
332
- ```
333
-
334
- A shell session lives in its container: pass the same `--container` to every `shells` and
335
- `commands` call on it.
336
-
337
- #### Environment in a sandbox
338
-
339
- A sandbox exports **nothing** by default (unless you boot from an organization snapshot or catalog
340
- image whose manifest supplies defaults). `environment` has three parts: `organization` (plain same-name opt-ins from the
341
- catalogue, see [`ghostdock env`](#ghostdock-env)), `bindings` (slot ← org entry remaps), and `local` (sandbox-only variables/secrets). A local entry overrides an
342
- organization export of the same name. Prefer the CLI when setting secret values so they are not
343
- pasted into the agent conversation.
344
-
345
- ```bash
346
- # At create time, in one call:
347
- ghostdock sandboxes create --org org_123 \
348
- --environment '{"organization":["VITE_API_URL","BUILD_TOKEN"],"bindings":[{"name":"DATABASE_URL","organization":"PROD_DATABASE_URL"}],"local":[{"name":"API_KEY","value":"sk_live","kind":"secret"}]}'
349
-
350
- # Afterwards:
351
- ghostdock sandboxes env get quiet-harbor
352
- ghostdock sandboxes env select quiet-harbor --environment '["VITE_API_URL"]' \
353
- --bindings '[{"name":"DATABASE_URL","organization":"PROD_DATABASE_URL"}]'
354
- ghostdock sandboxes env select quiet-harbor --environment '[]' # clears plain + remaps (omit bindings)
355
- ghostdock sandboxes env set API_KEY --sandbox-id quiet-harbor --value sk_live --kind secret
356
- ghostdock sandboxes env delete API_KEY --sandbox-id quiet-harbor
357
- ```
358
-
359
- Values arrive as real environment variables, so read them with `process.env` / `$VAR` inside the
360
- sandbox. **Do not pass secrets in `sandboxes commands run` strings** — the command text is retained and
361
- readable through `sandboxes commands logs`. `sandboxes env get` reports every organization entry
362
- (selected + overriddenByLocal) and the sandbox's own local entries; `sandboxes status` reports
363
- just the resolved names.
364
-
365
- New shell commands and SSH sessions see a change immediately. Processes already running keep the
366
- values they booted with until restarted (pass `--restart` to `sandboxes env select` /
367
- `sandboxes env set` / `sandboxes env delete` to restart a running sandbox
368
- instead).
369
-
370
- ### Images
371
-
372
- Organization image catalog: OCI bookmarks (`images add`), stored Dockerfiles
373
- (`images add-dockerfile`), and refs currently in use on sandboxes. `images list` and `images get`
374
- cover the same catalog family as those add tools — each org row includes `kind`, a redacted
375
- `manifest` (from `ghostdock.*` Docker/OCI labels), `requiredEnvironment`, and `requiredUrls` (same
376
- shape as snapshots). `sandboxes create` with `--source '{"type":"image","id":"..."}'` boots a catalog
377
- row by id and applies its manifest (URLs + env) like an organization snapshot.
378
-
379
- ```bash
380
- ghostdock images list --org org_123
381
- ghostdock images get img_abc --org org_123
382
- ghostdock images add --org org_123 --ref ghcr.io/acme/app:latest --label "Acme app"
383
- ghostdock images add-dockerfile --org org_123 --name my-stack --dockerfile "$(cat Dockerfile)"
384
- ghostdock sandboxes create --org org_123 \
385
- --source '{"type":"image","id":"img_abc"}' \
386
- --environment '{"local":[{"name":"API_KEY","kind":"secret","value":"sk_test"}]}'
387
- ```
388
-
389
- Booting with `--source '{"type":"dockerfile","content":"..."}'` parses labels inline without
390
- persisting a catalog row. That JSON source is Dockerfile text only: COPY/ADD of local files fails.
391
- `--source '{"type":"compose","files":{"compose.yaml":"..."}}'` boots Docker-in-Docker from those
392
- inline files (must include `docker-compose.yml`/`yaml` or `compose.yml`/`yaml`) and runs
393
- `docker compose up`; `ghostdock.*` service labels become the create-time manifest. A directory or
394
- ZIP — Dockerfile build context, or a Compose project with extra files — is
395
- [`ghostdock sandboxes build`](#ghostdock-sandboxes-build), not this command. Any OCI ref may still
396
- be passed as `{ type: "image", ref }` even when it does not appear in `images list`. Catalog compose
397
- rows still boot via `{ type: "image", id }`.
398
-
399
- ### `ghostdock sites publish`
400
-
401
- Publish a local directory or ZIP to the CDN (durable public URL, no sandbox):
402
-
403
- ```bash
404
- ghostdock sites publish --org org_123 ./dist
405
- ghostdock sites publish --org org_123 --zip ./site.zip
406
- ```
407
-
408
- MCP `sites publish` is for small inline payloads. Use this command for a real directory or large ZIP.
409
-
410
- ### `ghostdock projects publish`
411
-
412
- Inspect a local source tree and publish (CDN when pre-built static, otherwise Compose from a DeploymentSpec).
413
- Required secrets without values return `awaiting_configuration` instead of a live URL.
414
- Re-invoke with `--environment` (same JSON shape as `sandboxes create`) after configuring.
415
- On `build_failed`, `start_failed`, or `verify_failed`, inspect the kept sandbox (unless verification tore it down), then re-invoke with `--spec` (JSON `DeploymentSpec`). The spec is executed on a fresh sandbox and stored for later replay. Do not pass `--spec` with `--replan`. Every terminal outcome stores the upload and returns authenticated `fileUrls`. Detected tests always run after the stack is up; pass `--require-verify` to refuse a deploy when they fail.
416
-
417
- ```bash
418
- ghostdock projects publish --org org_123 ./app
419
- ghostdock projects publish --org org_123 --auto-stop-interval-minutes -1 --zip ./app.zip
420
- ghostdock projects publish --org org_123 --project-id proj_123 ./app
421
- ghostdock projects publish --org org_123 ./app \
422
- --environment '{"organization":["DATABASE_URL"],"local":[{"name":"API_KEY","value":"sk_live","kind":"secret"}]}'
423
- ghostdock projects publish --org org_123 ./app --spec '{"version":1,"run":{"kind":"static","outputDir":"."},"env":[]}'
424
- ghostdock projects publish --org org_123 --require-verify ./app
425
- ghostdock projects publish --org org_123 --sandbox-provider-id prov_123 ./app
426
- ```
427
-
428
- MCP `projects publish` is for small inline payloads. Use this command for a real directory or large ZIP.
429
-
430
- ### `ghostdock sandboxes build`
431
-
432
- Create a sandbox from a local Dockerfile or Compose directory. The CLI zips the directory (or sends
433
- `--zip`) and the server builds it. MCP `sandboxes create` stays inline text only.
434
-
435
- ```bash
436
- ghostdock sandboxes build --org org_123 --kind dockerfile ./app
437
- ghostdock sandboxes build --org org_123 --kind compose --zip ./stack.zip
438
- ghostdock sandboxes build --org org_123 --kind dockerfile \
439
- --sandbox-provider-id prov_123 --display-name "API" ./app
440
- ```
441
-
442
- The Dockerfile (`Dockerfile` or `dockerfile`) or a compose file (`docker-compose.yml`/`yaml`,
443
- `compose.yml`/`yaml`) must sit at the directory root, or at the root of the ZIP. A ZIP that wraps
444
- the project in one folder is unwrapped. Pass one directory or `--zip`, not both.
445
-
446
- ### `ghostdock sandboxes files upload`
447
-
448
- `sandboxes files upload` is convenient for small payloads. For a local directory,
449
- multiple files, or a large ZIP, use the dedicated multipart upload command instead:
450
-
451
- ```bash
452
- ghostdock sandboxes files upload quiet-harbor ./dist
453
- ghostdock sandboxes files upload quiet-harbor ./index.html ./assets
454
- ghostdock sandboxes files upload quiet-harbor --zip ./site.zip
455
- ghostdock sandboxes files upload quiet-harbor ./dist --container web --start
456
- ```
457
-
458
- Each positional path may be a file or directory. Directory contents are uploaded recursively,
459
- preserving their relative paths; a file is uploaded by its basename. A `sandboxes files upload` call needs
460
- at least one path or `--zip`. Uploading to a stopped sandbox resumes it automatically.
461
- The files land in a container as the other `files` commands do (see
462
- [Containers in a sandbox](#containers-in-a-sandbox)): `--container <name>`, else the default,
463
- else the one running, and the CLI asks which one when it cannot tell. A stopped target container
464
- is started after a "Start it?" at the keyboard, or at once with `--start`.
465
-
466
- ### `ghostdock env`
467
-
468
- Manage the environment variables and secrets an organization offers to its sandboxes and projects.
469
- A sandbox inherits nothing automatically — select the entries it needs on that sandbox.
470
-
471
- ```bash
472
- ghostdock env list --org org_123
473
- ghostdock env get VITE_API_URL --org org_123
474
- ghostdock env set VITE_API_URL --org org_123 --value https://api.example.com
475
- ghostdock env delete VITE_API_URL --org org_123
476
- ```
477
-
478
- **Variables vs secrets.** A variable is readable by anyone who can see the organization; `env list`
479
- prints its value inline. A secret can be set and replaced but never read back — it shows as
480
- `<secret>` in `env list` and `env get` refuses it. Pass `--secret` to create one:
481
-
482
- ```bash
483
- # Keeps the value out of shell history and the process list
484
- printf %s "$STRIPE_KEY" | ghostdock env set STRIPE_SECRET_KEY --org org_123 --secret --value-stdin
485
- ```
486
-
487
- `--secret` is only required when creating; updating an existing entry keeps its kind. To convert one,
488
- pass `--kind variable` or `--kind secret` explicitly along with the new value:
489
-
490
- ```bash
491
- ghostdock env set STRIPE_SECRET_KEY --org org_123 --kind variable --value not-secret-anymore
492
- # Warning: STRIPE_SECRET_KEY was a secret and is now a variable — its value is readable by everyone in the organization.
493
- ```
494
-
495
- Converting never reveals the old secret: `set` always replaces the value, so the value you supply in
496
- that call is the one that becomes readable. The command prints what changed either way.
497
-
498
- `env get` prints the bare value so it can be captured in a shell (`API=$(ghostdock env get
499
- VITE_API_URL --org org_123)`). It also returns values too large for `env list`, which
500
- withholds anything over 1024 characters rather than truncating it — a printed value is always the
501
- complete value.
502
-
503
- With `--json`, `list`, `get` and `set` print the tool's result instead. These commands wrap the
504
- `env list`, `env get`, `env set` and
505
- `env delete` tools, which are also available directly (and over MCP).
506
-
507
- Names must be valid environment variable names, and names the sandbox runtime owns (`PATH`,
508
- `HOME`, anything starting with `GHOSTDOCK_`, …) are rejected. Prefix a name with `VITE_`
509
- only when browser code must read it: Vite inlines those into the published bundle, so a `VITE_`
510
- secret is public.
511
-
512
- ### `ghostdock network`
513
-
514
- Reach your organizations' sandboxes from this machine by private address and name, over
515
- WireGuard ([ADR 0027](../../docs/adr/0027-private-sandbox-network.md)). Everything on a
516
- sandbox's address is reachable: a container that publishes port 80 answers on
517
- `http://quiet-harbor.acme.ghostdock.internal/`, as it would on `localhost` inside the sandbox.
518
- Nothing reaches your machine from a sandbox.
519
-
520
- ```bash
521
- ghostdock network connect # your organization's default provider; sudo once
522
- ghostdock network connect helsinki # or name a provider (name or id)
523
- ghostdock network ls --org acme # sandboxes, addresses, names, and what is reachable
524
- curl http://quiet-harbor.acme.ghostdock.internal:8080/
525
- open https://quiet-harbor--acme.ghostdock.net:8080/ # in a browser: HTTPS, any port
526
- open https://quiet-harbor.ghostdock.net:8080/ # the short name, for the connect organization
527
- ghostdock network connect --org beta # short names now mean beta's sandboxes
528
- ghostdock network status
529
- ghostdock network disconnect
530
- ```
531
-
532
- - **One provider at a time.** Each sandbox provider is its own gateway, and a device reaches
533
- only the sandboxes on the provider it connected through. Without an argument, `connect` takes
534
- the organization (`--org`, `GHOSTDOCK_ORG`, the default from `organizations use`) and its
535
- default sandbox provider, else the platform default. Connecting through another provider
536
- replaces the connection: same interface and address, new gateway. `network status` says which
537
- provider you are connected through; `network ls` marks sandboxes elsewhere as
538
- `not reachable: on <provider>` with the `connect` command that reaches them. A provider
539
- without a private network (Incus, for now) is refused by the server; one your organization
540
- may not use answers 403.
541
- - **Needs `wg-quick`** (`brew install wireguard-tools`, `apt install wireguard-tools`). macOS
542
- and Linux. On Windows, run the CLI in WSL: then only tools inside WSL reach sandboxes.
543
- - **Tunnel MTU 1280**, so the tunnel works on networks with a smaller path than 1500 bytes
544
- (DS-Lite, VPNs, mobile). A config written before 2026-10-20 has 1420: `network status` and
545
- `network ls` then say *This machine's tunnel has MTU 1420, the network now uses 1280*. Run
546
- `ghostdock network connect` again; until then TCP works, other large packets can be lost.
547
- - **One key per machine**, kept in `~/.config/ghostdock/network/`.
548
- Only the public key is sent. The device belongs to the login it was connected with:
549
- `ghostdock logout` takes it out of the network, and so does not connecting for 90 days.
550
- - **Names**: `<sandbox>.<org>.ghostdock.internal`, for every organization you are a member
551
- of. A name always says its organization, so a browser origin never changes hands between
552
- organizations. Only AAAA records exist: the network is IPv6, and the sandbox sees IPv4.
553
- - **In a browser**, use the HTTPS name `https://<sandbox>--<org>.ghostdock.net:<port>`
554
- (`network ls` shows it): any port, a real certificate, so the page is a secure context
555
- (clipboard, `Secure` cookies, service workers). The host's `gdo-ingress` terminates TLS and
556
- forwards to the sandbox's port; it serves only devices of the sandbox's organization, and
557
- refuses background requests (fetch, forms, iframes, websockets) from pages outside that
558
- organization; pages on another HTTPS name of the same organization, any port, may call it. The
559
- sandbox sees the request from `198.18.0.0`, and your device's address in
560
- `X-Forwarded-For`. The desktop image's Desktop opens only this way, never on the raw
561
- address.
562
- - **Short names** in a browser: `https://<sandbox>.ghostdock.net:<port>` means the sandbox of
563
- this machine's organization: the one `network connect` resolved (`--org`, `GHOSTDOCK_ORG`,
564
- the default from `organizations use`). `connect` says which; `network status` too, and
565
- `network ls` shows a sandbox's short name next to its full one when it is that
566
- organization's. With one organization you need nothing else. To use another organization's
567
- short names, connect again with `--org <other>`: there is no other way to change it, so a
568
- short name never changes meaning behind your back (`cd` into another project does not
569
- change it). Full names (`<sandbox>--<org>`) keep working for every organization and never
570
- change meaning: use them in scripts, CI, `.env` files and links you share.
571
- - **When the organization changes,** each short-name site clears its browser data once
572
- (local storage, cache, cookies) before the other organization's sandbox sees a request, so
573
- it never reads the first one's data. Cookies are cleared for the whole site, not only the
574
- short name: every site under the net domain's registrable domain (`ghostdock.net`: every
575
- sandbox app there, full names included; a net domain under the app's domain, as on staging:
576
- the Ghostdock app too). `connect` names the site when the organization changes. A tab opened on a short name before the
577
- change keeps the old page until you reload it: reload or close those tabs (`connect` says
578
- so). The page *Switching organization* is that clearing and reloads by itself; *Clear this
579
- site's data* means your browser could not clear it (Safari before 17): clear the site's
580
- data in its settings, or use the full name.
581
- - Tools may use short names too (`curl https://quiet-harbor.ghostdock.net:8080/`), but a
582
- short name in a script means whatever this machine is connected with: prefer the full
583
- name.
584
- - **Browsers use the HTTPS name; tools keep the raw address.** A browser that opens
585
- `http://quiet-harbor.acme.ghostdock.internal:3000/app` (or the raw IPv6 address) gets a
586
- `308` to `https://quiet-harbor--acme.ghostdock.net:3000/app`. Any other browser request on
587
- the raw address (`fetch`, images, scripts, forms, websockets) gets `403` with
588
- `X-Ghostdock-Blocked: browser-https-only` and the HTTPS address in the body. This keeps
589
- websites you visit while connected from using your connection against your sandboxes,
590
- including through DNS rebinding.
591
- - **What counts as a browser:** a `User-Agent` that starts with `Mozilla/`, which every
592
- browser sends on its own requests. Browsers send no `Sec-Fetch-*` headers over plain
593
- `http://` to an address like this, so those cannot be the signal. (Firefox lets a page
594
- set its own `User-Agent` on a `fetch`; the `Host` check below stops that one.) Tools that send a
595
- browser's `User-Agent` (Playwright, Puppeteer, their request APIs) count as browsers too:
596
- point them at the HTTPS name. A frontend outside the sandbox (a dev server on your laptop)
597
- calls the sandbox's API by its HTTPS name as well.
598
- - **Tools** (`curl`, SDKs, test runners, Prometheus) pass untouched, and every other
599
- protocol does too, as long as they address the sandbox by its IP address, its
600
- `.internal` name (or a container's, `web.quiet-harbor.acme.ghostdock.internal`), or
601
- `localhost`: any other `Host` gets `421` (`X-Ghostdock-Blocked: host-not-allowed`). That
602
- check is what stops DNS rebinding for a page that sets its own `User-Agent`. A name of
603
- your own in `/etc/hosts` gets 421 too.
604
- - **One difference for tools:** a port where nothing listens accepts the connection and
605
- then resets it, so port checks such as `nc -z` report it open; check with a real request
606
- instead.
607
- - **In the sandbox,** firewall rules for these clients belong in the input path
608
- (`iptables -A INPUT`, an nft `hook input` chain): `FORWARD` and `DOCKER-USER` rules no
609
- longer see them, because the guard connects to a published container port from inside
610
- the VM.
611
- - **The network pause** ([ADR 0033](../../docs/adr/0033-gdo-net-dead-mans-switch.md)): a
612
- device that sent no traffic to a sandbox for its idle timeout (default 4 h), or whose session
613
- since the last connect reached its maximum (default 12 h), is paused at the gateway. Your
614
- organizations set both (Settings → Security). If you are in several, the strictest value
615
- applies. `connect` ends with this device's own numbers and names the organization that set a
616
- stricter one.
617
- - **While paused**, names still resolve, but every port of a sandbox answers `Connection
618
- refused`, and UDP and ping get *administratively prohibited*. Browsers get a pause page
619
- with a *Reconnect* button, and Docker gets `Ghostdock: network access for this device is
620
- paused (idle 4 h)`. Every `ghostdock` command prints `! Network access for this device is
621
- paused (…). Run: ghostdock network connect` once.
622
- - **To resume**, run `ghostdock network connect`, or click *Reconnect* in the web app (User
623
- settings → Network devices). With the tunnel up and nothing changed, `connect` only
624
- re-arms: no sudo, *Re-armed: network access for this device runs until 22:14 (pauses after
625
- 4 h idle).* *Pause now* in the web app pauses a device at once.
626
- - DNS, WireGuard keepalives and ping do not count as traffic. A long stream does (a `docker
627
- logs -f`, an open desktop tab).
628
- - `ghostdock network devices` lists your devices with their state (*Active, pauses in 3 h 12
629
- min*, *Paused: idle 4 h*, *Paused: 12 h session limit*, *Paused by you*, *Not connected
630
- (…)*). `ghostdock network devices remove <id>` removes one.
631
- - **`ghostdock network disconnect`** also removes the split-DNS files a reboot or a crashed
632
- `wg-quick` left on macOS (`/etc/resolver/<zone>`), even when the tunnel is already down.
633
- Without that, names of the private network hang while you are disconnected. `network status`
634
- says when such a file is still there.
635
-
636
- ### `ghostdock docker context`
637
-
638
- Point your own `docker` and `docker compose` at a sandbox's Docker engine, over the private
639
- network with mutual TLS ([ADR 0032](../../docs/adr/0032-docker-api-over-gdo-net.md)). Connect
640
- first: the context uses this machine's device.
641
-
642
- ```bash
643
- ghostdock network connect
644
- ghostdock docker context quiet-harbor --org acme
645
- # ✓ Docker context ghostdock-acme-quiet-harbor (in use)
646
- # tcp://quiet-harbor.acme.ghostdock.internal:2376
647
- # Certificate for this device, valid until 2026-11-20.
648
- # → docker ps
649
- docker ps
650
- docker compose up -d
651
- ghostdock docker context north-pier --no-use # create only: docker --context ghostdock-acme-north-pier ps
652
- ```
653
-
654
- - **One Docker context per sandbox**, `ghostdock-<org>-<sandbox>`, for
655
- `tcp://<sandbox>.<org>.ghostdock.internal:2376`. Running the command again updates it;
656
- without `--no-use` it also becomes Docker's current context (`docker context use`). A
657
- `DOCKER_HOST` or `DOCKER_CONTEXT` in your shell wins over that: the command says so.
658
- - **One client certificate per organization and machine**, in
659
- `~/.config/ghostdock/docker/<organizationId>/`: `key.pem` (ECDSA P-256, made on this machine,
660
- 0600; only a certificate request is sent), `cert.pem` and `ca.pem`. The certificate names your
661
- user, this machine's device and the organization, and lives 30 days. A new one replaces the
662
- earlier one of this device for that organization: the old one stops working at once.
663
- - **Renewal:** `ghostdock network connect` and `ghostdock docker context` renew every
664
- certificate of this machine with less than 10 days left, and update the contexts they wrote
665
- (`~/.config/ghostdock/docker/contexts.json`). An expired certificate fails Docker's TLS
666
- handshake with Docker's own error: run `ghostdock docker context <sandbox>` again.
667
- - **`no such host`** on a `ghostdock.internal` address means this machine is not connected:
668
- run `ghostdock network connect`. The context's description in `docker context ls` says so
669
- too.
670
- - **Renamed organization:** the context's host keeps the old name, which stops resolving. Run
671
- `ghostdock docker context <sandbox>` again to update the host.
672
- - **Only from this device:** the sandbox checks every request with the app (membership, device,
673
- the network pause). A copied key and certificate do not work from another machine; a refusal
674
- comes back as Docker's `Error response from daemon: Ghostdock: …` with what to run.
675
- - **Warnings:** a sandbox on another provider than this machine's connection (with the
676
- `network connect` command that reaches it), and a sandbox whose base image is too old for
677
- Docker over the network (restart it to update). A sandbox that cannot have a Docker engine
678
- over the network (its provider has no private network, it has no address there yet, or a
679
- name that is not a DNS label) gets no context, and the command says why.
680
- - **A stopped sandbox** gets its context too: the first connection to it starts it (wake on
681
- SYN), and its Docker engine answers once it runs. A start that takes longer than Docker's
682
- 32 s dial timeout fails that one command with Docker's `i/o timeout`; the next one works.
683
- - **Needs Docker's CLI** (`docker` on `PATH`: Docker Desktop, OrbStack, or the CLI alone). The
684
- Docker engine itself runs in the sandbox.
685
-
686
- ## Command index
687
-
688
- Every command with its arguments and what it does. Run `ghostdock <command> --help` for its flags,
689
- or read [`cli-reference.md`](cli-reference.md) for every command's full description and flags.
690
-
691
- <!-- generated:command-index:start (bun run sync:cli-reference; do not edit) -->
692
- #### apps
693
-
694
- | Command | What it does |
695
- | --- | --- |
696
- | `ghostdock apps list [flags]` | List the live published apps (sites) of an organization, with their URLs. |
697
-
698
- #### docker
699
-
700
- | Command | What it does |
701
- | --- | --- |
702
- | `ghostdock docker context <sandbox> [flags]` | Point Docker at a sandbox's Docker engine over the private network: plain… |
703
-
704
- #### env
705
-
706
- | Command | What it does |
707
- | --- | --- |
708
- | `ghostdock env delete <name> [flags]` | Delete a variable or secret. |
709
- | `ghostdock env get <name> [flags]` | Print one variable value in full (secrets cannot be read). |
710
- | `ghostdock env list [flags]` | List variables and secrets. |
711
- | `ghostdock env set <name> [flags]` | Create or replace a variable or secret. |
712
-
713
- #### images
714
-
715
- | Command | What it does |
716
- | --- | --- |
717
- | `ghostdock images add --ref <string> [flags]` | Bookmark an OCI image ref in the organization’s image catalog. |
718
- | `ghostdock images add-compose --name <string> [flags]` | Add a Compose project to the organization’s image catalog. |
719
- | `ghostdock images add-dockerfile --name <string> --dockerfile <string> [flags]` | Add a Dockerfile to the organization’s image catalog. |
720
- | `ghostdock images get <image-id> [flags]` | Get one catalog image with its spec, manifest and requirements. |
721
- | `ghostdock images list [flags]` | List the images an organization can boot sandboxes from. |
722
- | `ghostdock images remove <image-id> [flags]` | Remove an image from the organization’s catalog. |
723
- | `ghostdock images update-compose <image-id> [flags]` | Replace a catalog Compose image’s files, reference, override and/or name. |
724
- | `ghostdock images update-dockerfile <image-id> --dockerfile <string> [flags]` | Replace a catalog Dockerfile, optionally renaming it. |
725
-
726
- #### login
727
-
728
- | Command | What it does |
729
- | --- | --- |
730
- | `ghostdock login [flags]` | Sign in and store a device access token for this machine… |
731
-
732
- #### logout
733
-
734
- | Command | What it does |
735
- | --- | --- |
736
- | `ghostdock logout` | Revoke the device session and remove stored credentials. |
737
-
738
- #### network
739
-
740
- | Command | What it does |
741
- | --- | --- |
742
- | `ghostdock network connect [provider] [flags]` | Put this machine into the private network through one provider: WireGuard and… |
743
- | `ghostdock network devices <command>` | Your devices in the private network. |
744
- | `ghostdock network devices remove <id>` | Remove one of your devices from the private network. |
745
- | `ghostdock network disconnect` | Take this machine out of the private network, and remove split DNS an earlier… |
746
- | `ghostdock network ls [flags]` | Sandboxes of an organization with their private addresses and names, and which… |
747
- | `ghostdock network status` | Whether this machine is connected, through which provider, and as which device. |
748
-
749
- #### organizations
750
-
751
- | Command | What it does |
752
- | --- | --- |
753
- | `ghostdock organizations current [flags]` | Show which organization commands use, and where it comes from. |
754
- | `ghostdock organizations list` | List the organizations you belong to, with their ids and slugs. |
755
- | `ghostdock organizations use [org] [flags]` | Set the default organization for commands run without --org (in every… |
756
-
757
- #### projects
758
-
759
- | Command | What it does |
760
- | --- | --- |
761
- | `ghostdock projects create --display-name <string> [flags]` | Create an empty project. |
762
- | `ghostdock projects deployments get <deployment-id> --project-id <string> [flags]` | Get one deploy attempt, with links to its stored files. |
763
- | `ghostdock projects deployments list <project-id> [flags]` | List a project’s deploy attempts, newest first. |
764
- | `ghostdock projects env delete <name> --project-id <string> [flags]` | Delete one of a project’s own variables or secrets. |
765
- | `ghostdock projects env get <project-id> [flags]` | Get a project’s stored environment. |
766
- | `ghostdock projects env select <project-id> --environment <array> [flags]` | Replace the organization entries a project exports. |
767
- | `ghostdock projects env set <name> --project-id <string> --value <string> --kind <string> [flags]` | Create or replace one of a project’s own variables or secrets. |
768
- | `ghostdock projects get <project-id> [flags]` | Get a project with its latest attempt and live deployment. |
769
- | `ghostdock projects list [flags]` | List an organization’s projects. |
770
- | `ghostdock projects publish [path] [flags]` | Inspect local source with the deploy agent and publish to the CDN or a sandbox. |
771
- | `ghostdock projects redeploy <project-id> [flags]` | Deploy a project’s stored source again, with its current environment. |
772
- | `ghostdock projects update <project-id> --display-name <string> [flags]` | Rename a project. |
773
-
774
- #### providers
775
-
776
- | Command | What it does |
777
- | --- | --- |
778
- | `ghostdock providers disconnect <sandbox-provider-id> [flags]` | Disconnect one of the organization’s own sandbox providers. |
779
- | `ghostdock providers list [flags]` | List the sandbox providers an organization can create sandboxes on. |
780
- | `ghostdock providers rename <sandbox-provider-id> --name <string> [flags]` | Rename one of the organization’s own sandbox providers. |
781
- | `ghostdock providers set-default <sandbox-provider-id> [flags]` | Set the provider used when a create omits sandboxProviderId. |
782
- | `ghostdock providers start-incus [flags]` | Start connecting an Incus host as a sandbox provider. |
783
- | `ghostdock providers verify-incus <sandbox-provider-id> [flags]` | Check or finish connecting an Incus host. |
784
-
785
- #### registry
786
-
787
- | Command | What it does |
788
- | --- | --- |
789
- | `ghostdock registry credentials [flags]` | Print registry host, username, and the one-hour password. |
790
- | `ghostdock registry login [flags]` | Fetch a one-hour password and run docker login --password-stdin. |
791
-
792
- #### sandboxes
793
-
794
- | Command | What it does |
795
- | --- | --- |
796
- | `ghostdock sandboxes build [path] --kind <value> [flags]` | Create a sandbox from a local Dockerfile or Compose directory. |
797
- | `ghostdock sandboxes commands get <command-id> --sandbox-id <string> --session-id <string> [flags]` | Get a shell command’s status and exit code. |
798
- | `ghostdock sandboxes commands kill <command-id> --sandbox-id <string> --session-id <string> [flags]` | Interrupt a running shell command. |
799
- | `ghostdock sandboxes commands logs <command-id> --sandbox-id <string> --session-id <string> [flags]` | Get a page of a shell command’s stdout and stderr. |
800
- | `ghostdock sandboxes commands run <sandbox-id> --command <string> [flags]` | Run a shell command in a sandbox. |
801
- | `ghostdock sandboxes containers list <sandbox-id> [flags]` | List the containers of a sandbox, running or not. |
802
- | `ghostdock sandboxes containers lock <sandbox-id> <container> [flags]` | Lock a container against removal. |
803
- | `ghostdock sandboxes containers logs <sandbox-id> <container> [flags]` | Read a container’s output, as docker logs does. |
804
- | `ghostdock sandboxes containers restart <sandbox-id> <container> [flags]` | Restart a container, as docker restart does (stopping as docker stop does). |
805
- | `ghostdock sandboxes containers start <sandbox-id> <container> [flags]` | Start a stopped container, as docker start does. |
806
- | `ghostdock sandboxes containers stop <sandbox-id> <container> [flags]` | Stop a container, as docker stop does. |
807
- | `ghostdock sandboxes containers unlock <sandbox-id> <container> [flags]` | Unlock a container so Docker can remove or recreate it. |
808
- | `ghostdock sandboxes create --source <object> [flags]` | Create a sandbox from a snapshot, OCI image, Dockerfile or Compose files. |
809
- | `ghostdock sandboxes default-container <sandbox-id> [flags]` | Show, set or clear the sandbox’s default container. |
810
- | `ghostdock sandboxes delete <sandbox-id> [flags]` | Permanently delete a sandbox and its files. |
811
- | `ghostdock sandboxes env delete <name> --sandbox-id <string> [flags]` | Delete one of a sandbox’s own variables or secrets. |
812
- | `ghostdock sandboxes env get <sandbox-id> [flags]` | Get a sandbox’s environment: selections, bindings and local entries. |
813
- | `ghostdock sandboxes env select <sandbox-id> --environment <array> [flags]` | Replace the organization entries a sandbox exports. |
814
- | `ghostdock sandboxes env set <name> --sandbox-id <string> --value <string> [flags]` | Create or replace one of a sandbox’s own variables or secrets. |
815
- | `ghostdock sandboxes files list <sandbox-id> [flags]` | List the files in a sandbox directory. |
816
- | `ghostdock sandboxes files read <path> --sandbox-id <string> [flags]` | Read a file from a sandbox: utf8 text, or base64 for small binaries. |
817
- | `ghostdock sandboxes files upload <sandbox-id> [path] [flags]` | Upload local files or directories to a sandbox's container, into its start… |
818
- | `ghostdock sandboxes list [flags]` | List the sandboxes of an organization, with their lifecycle and deadlines. |
819
- | `ghostdock sandboxes mcps create <sandbox-id> --name <string> --port <integer> [flags]` | Expose an MCP server running in a sandbox. |
820
- | `ghostdock sandboxes mcps delete <mcp-id>` | Delete an MCP endpoint of a sandbox. |
821
- | `ghostdock sandboxes mcps list <sandbox-id> [flags]` | List the MCP endpoints a sandbox exposes (name, port, path, autoWake). |
822
- | `ghostdock sandboxes mcps update <mcp-id> [flags]` | Change an MCP endpoint’s name, port, path or autoWake setting. |
823
- | `ghostdock sandboxes resize <sandbox-id> [flags]` | Change a sandbox’s CPU and/or memory. |
824
- | `ghostdock sandboxes resize-disk <sandbox-id> --disk-gib <number> [flags]` | Grow a sandbox’s disk. |
825
- | `ghostdock sandboxes shells close <session-id> --sandbox-id <string> [flags]` | Close a shell session. |
826
- | `ghostdock sandboxes shells create <sandbox-id> [flags]` | Open a shell session that keeps cwd and environment between commands. |
827
- | `ghostdock sandboxes ssh get <sandbox-id> [flags]` | Get temporary SSH access to a sandbox (command and token, 60 minutes). |
828
- | `ghostdock sandboxes ssh revoke <sandbox-id> [flags]` | Revoke a sandbox’s active SSH access. |
829
- | `ghostdock sandboxes status <sandbox-id> [flags]` | Get a sandbox’s status and lifecycle deadlines without waking it. |
830
- | `ghostdock sandboxes stop <sandbox-id> [flags]` | Stop a running sandbox without deleting its files. |
831
- | `ghostdock sandboxes storage delete <sandbox-id> --kind <string> --name <string> [flags]` | Delete a named volume or a top-level sandbox folder, with everything in it. |
832
- | `ghostdock sandboxes storage list <sandbox-id> [flags]` | List a sandbox’s volumes and sandbox folders. |
833
- | `ghostdock sandboxes tools call <name> --sandbox-id <string> --arguments <object> [flags]` | Call a tool on an MCP server inside a sandbox. |
834
- | `ghostdock sandboxes tools list <sandbox-id> [flags]` | List the tools of the MCP servers a sandbox exposes. |
835
- | `ghostdock sandboxes update <sandbox-id> [flags]` | Change a sandbox’s display name, idle-stop interval or lifecycle. |
836
- | `ghostdock sandboxes urls create <sandbox-id> --port <integer> [flags]` | Expose a sandbox port as a URL. |
837
- | `ghostdock sandboxes urls delete <url-id>` | Delete a sandbox URL. |
838
- | `ghostdock sandboxes urls list <sandbox-id> [flags]` | List the URLs that expose a sandbox’s ports, with protocol, access and title. |
839
- | `ghostdock sandboxes urls update <url-id> [flags]` | Change a sandbox URL’s port, protocol, autoWake, public setting or title. |
840
- | `ghostdock sandboxes wake <sandbox-id> [flags]` | Start a stopped sandbox, or reset the idle-stop countdown of a running one. |
841
-
842
- #### sites
843
-
844
- | Command | What it does |
845
- | --- | --- |
846
- | `ghostdock sites publish [path] [flags]` | Publish a local directory or ZIP to the CDN. |
847
- | `ghostdock sites unpublish <site-id> [flags]` | Take a published static site offline. |
848
-
849
- #### skills
850
-
851
- | Command | What it does |
852
- | --- | --- |
853
- | `ghostdock skills get <uri>` | Print one SKILL.md (URI from the discovery index, or a skill name). |
854
- | `ghostdock skills list` | List the Agent Skills discovery index. |
855
-
856
- #### snapshots
857
-
858
- | Command | What it does |
859
- | --- | --- |
860
- | `ghostdock snapshots create <sandbox-id> --name <string> [flags]` | Save a sandbox’s filesystem as a reusable organization snapshot. |
861
- | `ghostdock snapshots delete <snapshot-id> [flags]` | Permanently delete an organization snapshot (provider artifact and record). |
862
- | `ghostdock snapshots get <snapshot-id> [flags]` | Get one snapshot with its manifest and required environment, URLs and MCPs. |
863
- | `ghostdock snapshots list [flags]` | List the snapshots an organization can boot sandboxes from. |
864
- | `ghostdock snapshots update-manifest <snapshot-id> --manifest <object> [flags]` | Replace a snapshot’s manifest (URLs, environment, MCPs). |
865
-
866
- #### tools
867
-
868
- | Command | What it does |
869
- | --- | --- |
870
- | `ghostdock tools` | List available agent tools. |
871
-
872
- #### whoami
873
-
874
- | Command | What it does |
875
- | --- | --- |
876
- | `ghostdock whoami` | Show the account this CLI is currently authenticated as. |
877
- <!-- generated:command-index:end -->
878
-
879
- ## CLI settings
880
-
881
- Environment variables read by the CLI process itself. For an organization's environment variables
882
- and secrets, see [`ghostdock env`](#ghostdock-env).
883
-
884
- | Variable | Purpose | Default |
885
- | ------------------------------- | ------------------------------------------------------------- | --------------------------------- |
886
- | `GHOSTDOCK_BASE_URL` | API origin the CLI talks to. Override for local dev / self-hosted instances. | Local/dev builds default to `http://localhost:3000`. npm-published builds default to the production API origin baked at publish time. Override with `--base-url` or this env var. |
887
- | `GHOSTDOCK_ORG` | Organization (id or slug) for commands run without `--org`. Takes precedence over the default from `organizations use`. | unset |
888
- | `XDG_CONFIG_HOME` | Base directory for the CLI's per-machine state (`ghostdock/credentials.json`, `ghostdock/settings.json`, `ghostdock/network/`, `ghostdock/docker/`). | `~/.config` (native Windows: `%APPDATA%`) |
889
- | `GHOSTDOCK_CREDENTIALS_PATH` | Absolute path to the credentials file, overriding the default. `settings.json` (the default organization) sits in the same directory, so each credentials file keeps its own default — handy for a second account. | `~/.config/ghostdock/credentials.json` |
890
-
891
- Example for local development against a Nuxt dev server:
892
-
893
- ```bash
894
- ghostdock --base-url http://localhost:3000 login --wait
895
- # or
896
- GHOSTDOCK_BASE_URL=http://localhost:3000 ghostdock login --wait
897
- ```
898
-
899
- ## Credentials file
900
-
901
- Credentials are stored per machine as JSON in `~/.config/ghostdock/credentials.json`
902
- (`$XDG_CONFIG_HOME/ghostdock/` when that is set, `%APPDATA%\ghostdock\` on native Windows; WSL
903
- counts as Linux), with file permissions restricted to the owner (`0600`). `GHOSTDOCK_CREDENTIALS_PATH`
904
- points the CLI at another file, e.g. for a second account. The file looks like this:
905
-
906
- ```json
907
- {
908
- "accessToken": "ext_at_...",
909
- "refreshToken": "ext_rt_...",
910
- "accessExpiresAt": "2026-07-30T12:00:00.000Z"
911
- }
912
- ```
913
-
914
- Access tokens are short-lived (1 hour); the CLI refreshes them automatically using the refresh token
915
- (30-day rolling expiry) whenever a request gets a `401`. If both tokens are invalid or revoked (e.g.
916
- after `ghostdock logout` from another session), re-run `ghostdock login`.
917
-
918
- ## Exit codes
919
-
920
- - `0` — success (including the default `login` after only printing the URL — approval is still
921
- pending, that's expected).
922
- - `1` — failure: not logged in, session expired and unrefreshable, login denied/expired/timed out,
923
- a missing/invalid tool flag, or a tool invocation error (e.g. not a member of the organization).