ghostdock 0.0.7 → 0.0.8

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/package.json CHANGED
@@ -1,15 +1,14 @@
1
1
  {
2
2
  "name": "ghostdock",
3
3
  "description": "Ghostdock CLI — device login and agent tool invocation from the command line",
4
- "version": "0.0.7",
4
+ "version": "0.0.8",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "ghostdock": "dist/index.js",
8
8
  "gdock": "dist/index.js"
9
9
  },
10
10
  "files": [
11
- "dist",
12
- "CLI.md"
11
+ "dist"
13
12
  ],
14
13
  "repository": {
15
14
  "type": "git",
@@ -20,8 +19,9 @@
20
19
  },
21
20
  "scripts": {
22
21
  "sync-catalog": "bun run scripts/sync-catalog.ts",
22
+ "sync-reference": "bun run scripts/sync-reference.ts",
23
23
  "needs-publish": "bun run scripts/needs-publish.ts",
24
- "prebuild": "bun run sync-catalog",
24
+ "prebuild": "bun run sync-catalog && bun run sync-reference",
25
25
  "build": "bun run scripts/build.ts",
26
26
  "dev": "bun run src/index.ts",
27
27
  "pretest": "bun run sync-catalog",
package/CLI.md DELETED
@@ -1,468 +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
- `gdock` is a short name for the same CLI: `npx gdock …`, or `gdock …` after a
25
- global install. Help and hints use whichever name you typed.
26
-
27
- Inside this monorepo (for development), run from the repo root or `packages/cli`:
28
-
29
- ```bash
30
- bun run --cwd packages/cli build # bundles src/index.ts -> dist/index.js
31
- bun run --cwd packages/cli dev -- --help # run from source without building
32
- ```
33
-
34
- ## Global flags
35
-
36
- ```
37
- ghostdock --version
38
- ghostdock --base-url <url> <command>
39
- ```
40
-
41
- - `--version` / `-v` — print CLI version and exit
42
- - `--base-url <url>` — API origin for this invocation (wins over `GHOSTDOCK_BASE_URL`)
43
-
44
- ## Commands
45
-
46
- ```
47
- ghostdock login Sign in and store a device access token for this CLI
48
- ghostdock logout Revoke the device session and remove stored credentials
49
- ghostdock whoami Show the account this CLI is currently authenticated as
50
- ghostdock tools List available agent tools
51
- ghostdock skills List and read Agent Skills (same catalog as MCP)
52
- ghostdock env Manage organization environment variables and secrets
53
- ghostdock sandbox_upload Upload local files or directories to a sandbox
54
- ghostdock sandbox_create Create a sandbox from a Dockerfile or Compose directory (or ZIP)
55
- ghostdock publish_static Publish a local directory or ZIP to the CDN
56
- ghostdock publish_auto Inspect local source and publish (CDN or sandbox)
57
- ```
58
-
59
- Every tool in the catalog (e.g. `list_organizations`, `list_published_apps`) is also registered as its
60
- own top-level command — see **Invoking a tool** below.
61
-
62
- Run `ghostdock <command> --help` for the full flag list of any command.
63
-
64
- ### `ghostdock login`
65
-
66
- Ghostdock uses a device-authorization flow: no password is ever typed into the terminal.
67
-
68
- **Default (print-and-exit) — best when a human is present to click the link:**
69
-
70
- ```bash
71
- ghostdock login
72
- ```
73
-
74
- This prints a URL to open in a browser and exits `0` immediately — it does not prompt for input or
75
- poll for approval. Approve the request in the browser, then complete login with
76
- **`ghostdock login --code <paste-code>`**, redeeming the one-time code from the browser's
77
- "Having trouble? Show code" link (see below).
78
-
79
- Each `login` invocation starts a **new** device session. A later `login --wait` does **not** resume
80
- polling for a prior plain `login`. To block until approval, run **`ghostdock login --wait` up
81
- front** instead of plain `login`.
82
-
83
- **`--wait` — poll until approved:**
84
-
85
- ```bash
86
- ghostdock login --wait
87
- # or with a custom timeout (seconds, default 300):
88
- ghostdock login --wait --timeout 120
89
- ```
90
-
91
- Prints the same URL, then polls the server every few seconds until the login is approved, denied,
92
- or the timeout elapses. Exits `0` on success, non-zero otherwise.
93
-
94
- **`--code` — paste-code fallback:**
95
-
96
- If the CLI can't poll (e.g. it's running in a sandbox with no long-lived process, or the browser
97
- approval happened on a different machine), the browser's "Having trouble? Show code" link reveals a
98
- short one-time code. Redeem it directly:
99
-
100
- ```bash
101
- ghostdock login --code <paste-code>
102
- ```
103
-
104
- On success, credentials are written and the command exits `0`. If the code hasn't been approved
105
- yet, it exits `1` — approve it in the browser first.
106
-
107
- ### `ghostdock logout`
108
-
109
- ```bash
110
- ghostdock logout
111
- ```
112
-
113
- Revokes the device session on the server (best-effort — still clears local credentials even if the
114
- server call fails, e.g. when offline) and deletes the local credentials file.
115
-
116
- ### `ghostdock whoami`
117
-
118
- ```bash
119
- ghostdock whoami
120
- ```
121
-
122
- Prints the identity behind the stored access token as JSON (`{ "userId": ..., "baseUrl": ... }`).
123
- Transparently refreshes an expired access token using the stored refresh token before failing.
124
- Exits `1` with a message if not logged in or the session can't be refreshed.
125
-
126
- ### `ghostdock tools`
127
-
128
- Lists the tool catalog for the authenticated account:
129
-
130
- ```bash
131
- ghostdock tools # name + description, one per line
132
- ghostdock tools --json # the full catalog (including each tool's JSON Schema) as JSON
133
- ```
134
-
135
- Requires login — prints a hint and exits `1` if there's no valid session.
136
-
137
- ### `ghostdock skills`
138
-
139
- Lists and reads **Agent Skills** for the authenticated account — the same catalog MCP
140
- clients discover at `skill://index.json` (SEP-2640 / Agent Skills discovery 0.2.0).
141
- Prefer resources. `list_skills` and `read_skill` are MCP fallbacks for clients that
142
- cannot use `resources/list` and `resources/read` — skip them if those work.
143
-
144
- ```bash
145
- ghostdock skills # name, description, and skill:// URI, one skill per block
146
- ghostdock skills --json # official discovery index ($schema + skills[])
147
- ghostdock skills get skill://github/SKILL.md # print SKILL.md
148
- ghostdock skills get github # same, by name
149
- ghostdock skills get org_1/release-notes # organization skill
150
- ```
151
-
152
- `--json` on `get` prints `{ uri, name, description, markdown }`. If the same name exists
153
- in more than one organization, pass the `skill://` URI from the index.
154
-
155
- Requires login — prints a hint and exits `1` if there's no valid session.
156
-
157
- ### Invoking a tool
158
-
159
- Every catalog tool is its own top-level command, named after the tool, with one `--flag` per
160
- schema property (`organizationId` -> `--organization-id`). Run `ghostdock <tool-name> --help` to
161
- see a tool's flags and which are required. Output is the tool's JSON result on stdout; nothing is
162
- printed on stderr on success.
163
-
164
- ```bash
165
- ghostdock list_organizations
166
- # {"organizations": [{"id": "org_123", "name": "Acme", "slug": "acme"}]}
167
-
168
- ghostdock list_published_apps --organization-id org_123
169
- # {"apps": [{"id": "app_1", "url": "https://acme.example.app", "title": "Acme App", "publishedAt": "..."}]}
170
- ```
171
-
172
- Number/boolean flags are parsed from their string form; array/object flags take a raw JSON string
173
- (e.g. `--tags '["a","b"]'`). Requires login — prints a hint and exits `1` if there's no valid
174
- session, or the server's error message (e.g. "Not a member of this organization") on a `4xx`.
175
-
176
- The tool list embedded in the CLI binary is generated at build time from the server's tool catalog
177
- (`bun run sync-catalog` in `packages/cli`), so `--help` and flag parsing work offline; invoking a
178
- tool still requires a network call and a valid session.
179
-
180
- ### Sandbox tools
181
-
182
- Use sandbox tools to publish and manage public static sites. Each sandbox serves its preview on port
183
- `8080`; the platform automatically stops idle sandboxes and deletes stopped sandboxes unless you
184
- override the intervals with `--auto-stop-interval-minutes` and
185
- `--auto-delete-interval-minutes`. `--auto-restart` defaults to `false`, so wake-on-visit is off for
186
- new sandboxes unless you set it.
187
-
188
- | Tool | Purpose |
189
- | --- | --- |
190
- | `create_sandbox` | Create a sandbox (idle-stop + 14-day auto-delete by default). Dockerfile and Compose restart automatically after idle-stop. Inline Dockerfile text and inline Compose files only — a directory or ZIP (COPY/ADD, Compose build files) is `sandbox_create`. For bun-dev, pass an OCI `--source type=image` then `set_sandbox_boot`. |
191
- | `list_sandboxes` | List an organization's sandboxes. |
192
- | `upload_files` | Upload a small set of inline files or a base64-encoded ZIP. |
193
- | `list_files` | List files in a sandbox directory (`path` defaults to `/workspace`). |
194
- | `read_file` | Read a file from a sandbox (utf8 text, or base64 for small binaries). |
195
- | `list_urls` | List sandbox URLs for a sandbox. |
196
- | `create_url` | Expose a port as a sandbox URL (idempotent by port; `autoWake` and `public` default to false). |
197
- | `update_url` | Update a URL's port, autoWake, and/or public. |
198
- | `delete_url` | Delete a URL exposure. |
199
- | `list_mcps` | List MCP exposures configured for a sandbox (name, port, path, autoWake). |
200
- | `create_mcp` | Expose an MCP server running in a sandbox (idempotent by name; path defaults to `/mcp`). |
201
- | `update_mcp` | Update an MCP exposure's name, port, path, and/or autoWake. |
202
- | `delete_mcp` | Delete an MCP exposure. |
203
- | `list_sandbox_tools` | List tools exposed by MCP servers configured on a sandbox. |
204
- | `call_sandbox_tool` | Call a tool on a sandbox MCP server. |
205
- | `get_ssh_access` | Return temporary SSH credentials (60 minutes); idle auto-stop still applies. |
206
- | `revoke_ssh_access` | Revoke active SSH credentials for a sandbox. |
207
- | `run_command` | Run a shell command, waiting up to 120 seconds before returning handles for polling; idle auto-stop still applies. Sessions do not survive idle-stop — use Dockerfile/Compose or `set_sandbox_boot`. |
208
- | `set_sandbox_boot` | Register a bun-dev (or similar) command that starts now and after idle-stop. On Compose it runs after the stack; on a Dockerfile it replaces CMD. For host-only, create from `--source type=image`. |
209
- | `get_command` | Get a shell command's status and exit code. |
210
- | `get_command_logs` | Get paginated stdout and stderr for a shell command. |
211
- | `kill_command` | Interrupt a running shell command. |
212
- | `create_shell_session` | Create a sticky shell session that preserves cwd and environment between commands. |
213
- | `close_shell_session` | Close a sticky shell session. |
214
- | `update_sandbox` | Update the display name or idle-stop / auto-delete intervals (omit = no change; `null` = platform default). |
215
- | `wake_sandbox` | Start a stopped sandbox, or reset the idle-stop countdown if already running. |
216
- | `get_sandbox_status` | Get status, lifecycle deadlines, and optional features (tcp_bridge) without starting or touching activity. |
217
- | `stop_sandbox` | Stop a sandbox without deleting its files. |
218
- | `delete_sandbox` | Permanently delete a sandbox and its files. |
219
- | `publish_static` | Publish a static file set or ZIP to the CDN and return a durable `{adjective}-{adjective}-{noun}.static…` URL (does not create a sandbox). |
220
- | `publish_auto` | Inspect source (folder or ZIP) with the deploy agent and publish — CDN when pre-built static, otherwise a DeploymentSpec rendered to `Dockerfile.deploy` + `compose.deploy.yaml` and run with Compose. First deploy and replay use the same execute path. Same lifecycle flags as `create_sandbox`; minted URL defaults to public + auto-wake. Detected tests always run on Compose execution and are reported; `--require-verify` makes a failure `verify_failed` instead of deploying. On failure, inspect the kept sandbox and re-invoke with `--spec` to verify a DeploymentSpec on a clean box. Every terminal outcome stores the upload and returns authenticated `fileUrls`. Needs a usable compose-capable sandbox provider: with none, a call that plans fails with a not-configured error before planning, even for pre-built static files (use `publish_static` for those). |
221
- | `list_projects` | List first-class Projects (name, live URL, latest attempt). Distinct from `list_published_apps`. |
222
- | `get_project` | Get one project: name, slug, latest attempt, live deploy. |
223
- | `create_project` | Create an empty project (name only). No deploy until `publish_auto` ships source to this `projectId`. |
224
- | `update_project` | Rename a project. Pass `displayName` null or empty to clear the name. |
225
- | `list_project_deployments` | List ship attempts for a project, newest first. |
226
- | `get_project_deployment` | Get one deployment by id, including authenticated `fileUrls` when blobs were stored. |
227
- | `redeploy_project` | Ship stored source again. Omit `--deployment-id` to retry the last attempt that stored source. Pass `--deployment-id` for that version. Current project env is applied. New deployment row. |
228
- | `get_project_environment` | Get a project's stored environment (local entries, org opt-ins, bindings). Secret values withheld. |
229
- | `set_project_environment_selection` | Full-replace organization environment exports for a project (`environment` names + optional `bindings`). |
230
- | `set_project_environment_entry` | Create or replace one project-local variable or secret, by name (prefer CLI for secret values). |
231
- | `delete_project_environment_entry` | Delete one project-local variable or secret, by name. |
232
- | `unpublish_static` | Take a CDN-published static site offline so its public URL no longer serves files. |
233
- | `get_sandbox_environment` | Get a sandbox's environment: organization entries (selected + exportAs + overriddenByLocal), bindings, local entries, and whether it's running. |
234
- | `set_sandbox_environment_selection` | Full-replace organization exports (`environment` plain names + optional `bindings` remaps; omit bindings to clear remaps). |
235
- | `set_sandbox_environment_entry` | Create or replace one of a sandbox's own (local) variables or secrets, by name (prefer CLI for secret values). |
236
- | `delete_sandbox_environment_entry` | Delete one of a sandbox's own (local) variables or secrets, by name. |
237
-
238
- For example, create a sandbox, then expose a URL:
239
-
240
- ```bash
241
- ghostdock create_sandbox --organization-id org_123 --display-name "Marketing site"
242
- ghostdock create_url --sandbox-id sandbox_123 --port 8080 --auto-wake true --public true
243
- ```
244
-
245
- #### Environment in a sandbox
246
-
247
- A sandbox exports **nothing** by default (unless you boot from an organization snapshot or catalog
248
- image whose manifest supplies defaults). `environment` has three parts: `organization` (plain same-name opt-ins from the
249
- catalogue, see [`ghostdock env`](#ghostdock-env)), `bindings` (slot ← org entry remaps), and `local` (sandbox-only variables/secrets). A local entry overrides an
250
- organization export of the same name. Prefer the CLI when setting secret values so they are not
251
- pasted into the agent conversation.
252
-
253
- ```bash
254
- # At create time, in one call:
255
- ghostdock create_sandbox --organization-id org_123 \
256
- --environment '{"organization":["VITE_API_URL","BUILD_TOKEN"],"bindings":[{"name":"DATABASE_URL","organization":"PROD_DATABASE_URL"}],"local":[{"name":"API_KEY","value":"sk_live","kind":"secret"}]}'
257
-
258
- # Afterwards:
259
- ghostdock get_sandbox_environment --sandbox-id sandbox_123
260
- ghostdock set_sandbox_environment_selection --sandbox-id sandbox_123 --environment '["VITE_API_URL"]' \
261
- --bindings '[{"name":"DATABASE_URL","organization":"PROD_DATABASE_URL"}]'
262
- ghostdock set_sandbox_environment_selection --sandbox-id sandbox_123 --environment '[]' # clears plain + remaps (omit bindings)
263
- ghostdock set_sandbox_environment_entry --sandbox-id sandbox_123 --name API_KEY --value sk_live --kind secret
264
- ghostdock delete_sandbox_environment_entry --sandbox-id sandbox_123 --name API_KEY
265
- ```
266
-
267
- Values arrive as real environment variables, so read them with `process.env` / `$VAR` inside the
268
- sandbox. **Do not pass secrets in `run_command` strings** — the command text is retained and
269
- readable through `get_command_logs`. `get_sandbox_environment` reports every organization entry
270
- (selected + overriddenByLocal) and the sandbox's own local entries; `get_sandbox_status` reports
271
- just the resolved names.
272
-
273
- New shell commands and SSH sessions see a change immediately. Processes already running keep the
274
- values they booted with until restarted (pass `--restart` to `set_sandbox_environment_selection` /
275
- `set_sandbox_environment_entry` / `delete_sandbox_environment_entry` to restart a running sandbox
276
- instead).
277
-
278
- ### Image tools
279
-
280
- Organization image catalog: OCI bookmarks (`add_image`), stored Dockerfiles
281
- (`add_image_dockerfile`), and refs currently in use on sandboxes. `list_images` and `get_image`
282
- cover the same catalog family as those add tools — each org row includes `kind`, a redacted
283
- `manifest` (from `ghostdock.*` Docker/OCI labels), `requiredEnvironment`, and `requiredUrls` (same
284
- shape as snapshots). `create_sandbox` with `--source '{"type":"image","id":"..."}'` boots a catalog
285
- row by id and applies its manifest (URLs + env) like an organization snapshot.
286
-
287
- | Tool | Purpose |
288
- | --- | --- |
289
- | `list_images` | Discovery catalog (not an allowlist): platform bases, bookmarks, Dockerfiles, in-use refs. |
290
- | `get_image` | One catalog row by id (OCI bookmark or Dockerfile from `list_images`). |
291
- | `add_image` | Bookmark an OCI ref; best-effort inspect caches label manifest. |
292
- | `add_image_dockerfile` | Store a Dockerfile; parses `ghostdock.*` LABEL lines into cached manifest. |
293
- | `update_image_dockerfile` | Replace Dockerfile text and re-parse manifest. |
294
- | `remove_image` | Delete a catalog row by id. |
295
-
296
- ```bash
297
- ghostdock list_images --organization-id org_123
298
- ghostdock get_image --organization-id org_123 --image-id img_abc
299
- ghostdock add_image --organization-id org_123 --ref ghcr.io/acme/app:latest --label "Acme app"
300
- ghostdock add_image_dockerfile --organization-id org_123 --name my-stack --dockerfile "$(cat Dockerfile)"
301
- ghostdock create_sandbox --organization-id org_123 \
302
- --source '{"type":"image","id":"img_abc"}' \
303
- --environment '{"local":[{"name":"API_KEY","kind":"secret","value":"sk_test"}]}'
304
- ```
305
-
306
- Booting with `--source '{"type":"dockerfile","content":"..."}'` parses labels inline without
307
- persisting a catalog row. That JSON source is Dockerfile text only: COPY/ADD of local files fails.
308
- `--source '{"type":"compose","files":{"compose.yaml":"..."}}'` boots Docker-in-Docker from those
309
- inline files (must include `docker-compose.yml`/`yaml` or `compose.yml`/`yaml`) and runs
310
- `docker compose up`; `ghostdock.*` service labels become the create-time manifest. A directory or
311
- ZIP — Dockerfile build context, or a Compose project with extra files — is
312
- [`ghostdock sandbox_create`](#ghostdock-sandbox_create), not this command. Any OCI ref may still
313
- be passed as `{ type: "image", ref }` even when it does not appear in `list_images`. Catalog compose
314
- rows still boot via `{ type: "image", id }`.
315
-
316
- ### `ghostdock publish_static`
317
-
318
- Publish a local directory or ZIP to the CDN (durable public URL, no sandbox):
319
-
320
- ```bash
321
- ghostdock publish_static --organization-id org_123 ./dist
322
- ghostdock publish_static --organization-id org_123 --zip ./site.zip
323
- ```
324
-
325
- MCP `publish_static` is for small inline payloads. Use this command for a real directory or large ZIP.
326
-
327
- ### `ghostdock publish_auto`
328
-
329
- Inspect a local source tree and publish (CDN when pre-built static, otherwise Compose from a DeploymentSpec).
330
- Required secrets without values return `awaiting_configuration` instead of a live URL.
331
- Re-invoke with `--environment` (same JSON shape as `create_sandbox`) after configuring.
332
- 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.
333
-
334
- ```bash
335
- ghostdock publish_auto --organization-id org_123 ./app
336
- ghostdock publish_auto --organization-id org_123 --auto-stop-interval-minutes -1 --zip ./app.zip
337
- ghostdock publish_auto --organization-id org_123 --project-id proj_123 ./app
338
- ghostdock publish_auto --organization-id org_123 ./app \
339
- --environment '{"organization":["DATABASE_URL"],"local":[{"name":"API_KEY","value":"sk_live","kind":"secret"}]}'
340
- ghostdock publish_auto --organization-id org_123 ./app --spec '{"version":1,"run":{"kind":"static","outputDir":"."},"env":[]}'
341
- ghostdock publish_auto --organization-id org_123 --require-verify ./app
342
- ghostdock publish_auto --organization-id org_123 --sandbox-provider-id prov_123 ./app
343
- ```
344
-
345
- MCP `publish_auto` is for small inline payloads. Use this command for a real directory or large ZIP.
346
-
347
- ### `ghostdock sandbox_create`
348
-
349
- Create a sandbox from a local Dockerfile or Compose directory. The CLI zips the directory (or sends
350
- `--zip`) and the server builds it. MCP `create_sandbox` stays inline text only.
351
-
352
- ```bash
353
- ghostdock sandbox_create --organization-id org_123 --kind dockerfile ./app
354
- ghostdock sandbox_create --organization-id org_123 --kind compose --zip ./stack.zip
355
- ghostdock sandbox_create --organization-id org_123 --kind dockerfile \
356
- --sandbox-provider-id prov_123 --display-name "API" ./app
357
- ```
358
-
359
- The Dockerfile (`Dockerfile` or `dockerfile`) or a compose file (`docker-compose.yml`/`yaml`,
360
- `compose.yml`/`yaml`) must sit at the directory root, or at the root of the ZIP. A ZIP that wraps
361
- the project in one folder is unwrapped. Pass one directory or `--zip`, not both.
362
-
363
- ### `ghostdock sandbox_upload`
364
-
365
- `upload_files` is convenient for small payloads. For a local directory,
366
- multiple files, or a large ZIP, use the dedicated multipart upload command instead:
367
-
368
- ```bash
369
- ghostdock sandbox_upload --sandbox-id sandbox_123 ./dist
370
- ghostdock sandbox_upload --sandbox-id sandbox_123 ./index.html ./assets
371
- ghostdock sandbox_upload --sandbox-id sandbox_123 --zip ./site.zip
372
- ```
373
-
374
- Each positional path may be a file or directory. Directory contents are uploaded recursively,
375
- preserving their relative paths; a file is uploaded by its basename. A `sandbox_upload` call needs
376
- at least one path or `--zip`. Uploading to a stopped sandbox resumes it automatically.
377
-
378
- ### `ghostdock env`
379
-
380
- Manage the environment variables and secrets an organization offers to its sandboxes and projects.
381
- A sandbox inherits nothing automatically — select the entries it needs on that sandbox.
382
-
383
- ```bash
384
- ghostdock env list --organization org_123
385
- ghostdock env get VITE_API_URL --organization org_123
386
- ghostdock env set VITE_API_URL --organization org_123 --value https://api.example.com
387
- ghostdock env delete VITE_API_URL --organization org_123
388
- ```
389
-
390
- **Variables vs secrets.** A variable is readable by anyone who can see the organization; `env list`
391
- prints its value inline. A secret can be set and replaced but never read back — it shows as
392
- `<secret>` in `env list` and `env get` refuses it. Pass `--secret` to create one:
393
-
394
- ```bash
395
- # Keeps the value out of shell history and the process list
396
- printf %s "$STRIPE_KEY" | ghostdock env set STRIPE_SECRET_KEY --organization org_123 --secret --value-stdin
397
- ```
398
-
399
- `--secret` is only required when creating; updating an existing entry keeps its kind. To convert one,
400
- pass `--kind variable` or `--kind secret` explicitly along with the new value:
401
-
402
- ```bash
403
- ghostdock env set STRIPE_SECRET_KEY --organization org_123 --kind variable --value not-secret-anymore
404
- # Warning: STRIPE_SECRET_KEY was a secret and is now a variable — its value is readable by everyone in the organization.
405
- ```
406
-
407
- Converting never reveals the old secret: `set` always replaces the value, so the value you supply in
408
- that call is the one that becomes readable. The command prints what changed either way.
409
-
410
- `env get` prints the bare value so it can be captured in a shell (`API=$(ghostdock env get
411
- VITE_API_URL --organization org_123)`). It also returns values too large for `env list`, which
412
- withholds anything over 1024 characters rather than truncating it — a printed value is always the
413
- complete value.
414
-
415
- Add `--json` to `list`, `get` or `set` for machine-readable output. These commands wrap the
416
- `list_environment_variables`, `get_environment_variable`, `set_environment_variable` and
417
- `delete_environment_variable` tools, which are also available directly (and over MCP).
418
-
419
- Names must be valid environment variable names, and names the sandbox runtime owns (`PATH`,
420
- `HOME`, anything starting with `GHOSTDOCK_`, …) are rejected. Prefix a name with `VITE_`
421
- only when browser code must read it: Vite inlines those into the published bundle, so a `VITE_`
422
- secret is public.
423
-
424
- ## CLI settings
425
-
426
- Environment variables read by the CLI process itself. For an organization's environment variables
427
- and secrets, see [`ghostdock env`](#ghostdock-env).
428
-
429
- | Variable | Purpose | Default |
430
- | ------------------------------- | ------------------------------------------------------------- | --------------------------------- |
431
- | `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. |
432
- | `GHOSTDOCK_CREDENTIALS_PATH` | Absolute path to the credentials file, overriding the default. | `./.ghostdock/credentials.json` (relative to the current working directory) |
433
-
434
- Example for local development against a Nuxt dev server:
435
-
436
- ```bash
437
- ghostdock --base-url http://localhost:3000 login --wait
438
- # or
439
- GHOSTDOCK_BASE_URL=http://localhost:3000 ghostdock login --wait
440
- ```
441
-
442
- ## Credentials file
443
-
444
- Credentials are stored as JSON at `./.ghostdock/credentials.json` (relative to the directory the
445
- CLI is run from), with file permissions restricted to the owner (`0600`):
446
-
447
- ```json
448
- {
449
- "accessToken": "ext_at_...",
450
- "refreshToken": "ext_rt_...",
451
- "accessExpiresAt": "2026-07-30T12:00:00.000Z"
452
- }
453
- ```
454
-
455
- **Add `.ghostdock/` to your project's `.gitignore`.** These are live tokens — never commit them.
456
- This repository's own `.gitignore` already ignores `.ghostdock/` for local development/testing of
457
- the CLI itself.
458
-
459
- Access tokens are short-lived (1 hour); the CLI refreshes them automatically using the refresh token
460
- (30-day rolling expiry) whenever a request gets a `401`. If both tokens are invalid or revoked (e.g.
461
- after `ghostdock logout` from another session), re-run `ghostdock login`.
462
-
463
- ## Exit codes
464
-
465
- - `0` — success (including the default `login` after only printing the URL — approval is still
466
- pending, that's expected).
467
- - `1` — failure: not logged in, session expired and unrefreshable, login denied/expired/timed out,
468
- a missing/invalid tool flag, or a tool invocation error (e.g. not a member of the organization).