@astrale-os/adapter-cloudflare 0.3.1 → 0.4.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.
Files changed (63) hide show
  1. package/LICENSE +202 -0
  2. package/package.json +4 -4
  3. package/template/.agents/skills/astrale-cli/SKILL.md +633 -0
  4. package/template/.domain-studio/comments.json +4 -0
  5. package/template/.env.example +3 -6
  6. package/template/CLAUDE.md +8 -6
  7. package/template/README.md +28 -20
  8. package/template/client/__tests__/app.test.tsx +39 -248
  9. package/template/client/__tests__/harness.ts +0 -47
  10. package/template/client/__tests__/shell.test.ts +46 -0
  11. package/template/client/package.json +1 -1
  12. package/template/client/src/app.tsx +6 -8
  13. package/template/client/src/shell/index.ts +1 -0
  14. package/template/client/src/shell/transformers.ts +36 -33
  15. package/template/client/src/shell/use-node.ts +21 -13
  16. package/template/client/src/ui/index.ts +4 -7
  17. package/template/core/README.md +23 -0
  18. package/template/deps.ts +10 -9
  19. package/template/domain.ts +11 -9
  20. package/template/env.ts +3 -5
  21. package/template/functions/index.ts +14 -37
  22. package/template/icons.ts +25 -0
  23. package/template/integrations/README.md +22 -0
  24. package/template/package.json +3 -3
  25. package/template/runtime/index.ts +25 -72
  26. package/template/schema/index.ts +10 -10
  27. package/template/tsconfig.json +1 -0
  28. package/template/views/index.ts +15 -12
  29. package/template/client/__tests__/kernel.test.ts +0 -77
  30. package/template/client/__tests__/seam.test.tsx +0 -115
  31. package/template/client/src/status/components/StatusCard.tsx +0 -160
  32. package/template/client/src/status/components/index.ts +0 -1
  33. package/template/client/src/status/hooks/index.ts +0 -3
  34. package/template/client/src/status/hooks/useCheck.mutation.ts +0 -16
  35. package/template/client/src/status/hooks/useCheckable.query.ts +0 -72
  36. package/template/client/src/status/index.ts +0 -7
  37. package/template/client/src/status/status.api.ts +0 -29
  38. package/template/client/src/status/status.mappers.ts +0 -102
  39. package/template/client/src/status/status.types.ts +0 -26
  40. package/template/client/src/ui/StatusBadge.tsx +0 -31
  41. package/template/client/src/views/status.tsx +0 -28
  42. package/template/core/monitor/health.ts +0 -34
  43. package/template/core/monitor/index.ts +0 -9
  44. package/template/core/monitor/keys.ts +0 -41
  45. package/template/core/monitor/node.ts +0 -63
  46. package/template/integrations/prober/http.ts +0 -32
  47. package/template/integrations/prober/mock.ts +0 -18
  48. package/template/integrations/prober/port.ts +0 -26
  49. package/template/integrations/prober/registry.ts +0 -65
  50. package/template/pnpm-lock.yaml +0 -2780
  51. package/template/runtime/monitoring/index.ts +0 -8
  52. package/template/runtime/monitoring/monitor/check.ts +0 -29
  53. package/template/runtime/monitoring/monitor/index.ts +0 -10
  54. package/template/runtime/monitoring/monitor/seed.ts +0 -104
  55. package/template/runtime/monitoring/monitor/watch.ts +0 -31
  56. package/template/runtime/monitoring/page/add.ts +0 -21
  57. package/template/runtime/monitoring/page/check.ts +0 -50
  58. package/template/runtime/monitoring/page/create.ts +0 -24
  59. package/template/runtime/monitoring/page/index.ts +0 -9
  60. package/template/runtime/shared.ts +0 -21
  61. package/template/schema/monitor.ts +0 -92
  62. package/template/views/status-page.ts +0 -16
  63. package/template/views/welcome.ts +0 -35
@@ -0,0 +1,633 @@
1
+ ---
2
+ name: astrale-cli
3
+ description: Reference for the Astrale CLI (binary `astrale`, package `@astrale-os/cli`) - CLI setup, command composition, graph exploration and querying, kernel calls, instance bookmarks and admin-provisioned instances, identity management, delegation tokens, browser sessions, output behavior, debugging, and local storage.
4
+ ---
5
+
6
+ # Astrale CLI
7
+
8
+ `astrale` is the CLI for connecting to Astrale kernels. It authenticates,
9
+ selects an instance, calls kernel operations, inspects graph nodes, mints
10
+ delegation tokens, and prepares authenticated browser sessions for agents.
11
+
12
+ The command surface lives in the code. Use `astrale --help` and
13
+ `astrale <cmd> --help` as the source of truth for commands, flags, defaults,
14
+ and examples. This skill should only hold cross-cutting model details and
15
+ common recipes that help compose those commands correctly.
16
+
17
+ - Binary: `astrale`
18
+ - npm package: `@astrale-os/cli`
19
+ - Runtime: Bun
20
+ - Framework: Commander.js
21
+ - Dev entrypoint: `bun cli/bin/astrale.ts <command>`
22
+
23
+ ## Command Surface
24
+
25
+ Current top-level commands:
26
+
27
+ ```bash
28
+ astrale whoami
29
+ astrale use <name>
30
+ astrale update
31
+ astrale call <path> [params...]
32
+ astrale token
33
+ astrale get <path>
34
+ astrale mutate
35
+ astrale ls [path]
36
+ astrale describe <path>
37
+ astrale query [paths...]
38
+ astrale logs [--service <name>]
39
+ astrale status
40
+ astrale browser
41
+ astrale instance ...
42
+ astrale domain ...
43
+ astrale admin ...
44
+ astrale identity ...
45
+ astrale auth ...
46
+ astrale idp ...
47
+ ```
48
+
49
+ Command groups:
50
+
51
+ | Group | Commands |
52
+ |---|---|
53
+ | Kernel | `call`, `token`, `get`, `mutate`, `ls`, `describe`, `query`, `logs` |
54
+ | Context | `status`, `whoami`, `use` |
55
+ | Management | `admin`, `instance`, `domain`, `identity`, `auth`, `idp`, `update` |
56
+ | Agent | `browser` |
57
+
58
+ `get`, `query`, and `mutate` are the graph door commands: `get` is a
59
+ single-node point read, `query` is a structured multi-root read, and both lower
60
+ to `function.get` today. `query` is the door a future true query syscall will
61
+ back. `mutate` writes a batch patch (`function.mutate`). `ls` and `describe`
62
+ remain `function.get` presets. The old per-node syscalls (`::get`,
63
+ `::createNode`, `::link`, …) are gone.
64
+
65
+ Shared kernel options are merged onto kernel-touching commands at registration
66
+ time: `--format`, `--json`, `--raw`, `--url`, `-i/--instance`, `--timeout`,
67
+ `--as`, `--creds`, and `--debug`. Check `astrale <cmd> --help` before relying
68
+ on an option for a specific command.
69
+
70
+ ## Path Syntax
71
+
72
+ Clients address graph entities and operations with Paths.
73
+
74
+ | Form | Grammar | Use when |
75
+ |---|---|---|
76
+ | Absolute path | `/domain`, `/domain/class.Name`, `/domain/interface.Name` | Domain, Class namespace, or Interface namespace |
77
+ | Static method | `/:domain:class.Name:method` or `/domain/class.Name/method` | Class-level or interface-level operation |
78
+ | Instance method | `<nodePath>::method` or `@id::method` | Operation on a node instance |
79
+ | Id reference | `@nodeId` | Reference a node by UID |
80
+ | Self reference | `@self` | CLI-side shorthand for the active caller node |
81
+
82
+ Load-bearing rules:
83
+
84
+ - Keep the `class.` or `interface.` prefix in namespace segments:
85
+ `/:host.astrale.ai:class.KernelInstance:list`, not
86
+ `/:host.astrale.ai:KernelInstance:list`.
87
+ - Static methods declared on an Interface are reached through the declaring
88
+ interface namespace, not through a concrete Class namespace.
89
+ - Instance dispatch uses double colon `::`; single colon is for domain-path
90
+ static method syntax.
91
+ - Prefer the domain-path form `/:domain:class.Name:method` for static calls
92
+ when possible. It resolves by domain membership rather than tree layout.
93
+ - `@<id>` takes a graph node UUID only — `@<slug>` is NOT_FOUND. And a
94
+ permission error naming a node that "should exist" often means the node
95
+ does NOT exist (missing targets surface as permission denied, not
96
+ NOT_FOUND) — verify with `astrale get <path>` before chasing grants.
97
+
98
+ Examples:
99
+
100
+ ```bash
101
+ astrale call /:blog.acme.com:class.Author:list
102
+ astrale call /:blog.acme.com:interface.NoteOps:createNote title=Hello
103
+ astrale call /blog.acme.com/alice::deactivate
104
+ astrale call @f00d...::deactivate
105
+ ```
106
+
107
+ ### @self
108
+
109
+ `@self` is a CLI-side literal expanded before a call is signed and sent. It
110
+ resolves to the active identity's registered node id on the target instance.
111
+ The kernel receives the concrete `@<nodeId>` value.
112
+
113
+ Supported positions:
114
+
115
+ - Path head: `@self`, `@self::method`, `@self/child`
116
+ - Param value head: `key=@self`, `key=@self::method`
117
+
118
+ Not expanded:
119
+
120
+ - `--url`
121
+ - `--data`
122
+ - stdin JSON
123
+ - substrings such as `prefix@self`
124
+ - comma lists such as `@self,@other`
125
+
126
+ For JSON payloads, resolve manually before building the payload.
127
+
128
+ ```bash
129
+ astrale describe @self
130
+ astrale call @self::deactivate
131
+ astrale call /:d:class.X:m owner=@self
132
+ ```
133
+
134
+ For IdP-backed identities (`astrale auth login`), `@self` just works: the CLI
135
+ verifies the caller through the bound auth surface (`auth.whoami()`), caches
136
+ the node id as a registration, and refreshes that cache when it changes (for
137
+ example after a managed instance is deleted and recreated under the same slug).
138
+ Smoke the active identity with the same public flow:
139
+
140
+ ```bash
141
+ astrale get @self --json
142
+ ```
143
+
144
+ For key-backed identities, refresh a deleted or stale `@self` registration with
145
+ `astrale identity register <name> -i <instance>`.
146
+
147
+ ## Instances
148
+
149
+ `astrale instance` manages admin-provisioned instances and local bookmarks.
150
+
151
+ Use:
152
+
153
+ ```bash
154
+ astrale instance create my-app
155
+ astrale instance status my-app
156
+ astrale instance use my-app
157
+ astrale instance active
158
+ astrale instance bookmark staging --url https://kernel.example.com
159
+ astrale instance forget staging
160
+ ```
161
+
162
+ Important distinctions:
163
+
164
+ - `instance use` changes the active target instance.
165
+ - `instance active` shows the active target instance.
166
+ - `instance bookmark` records an existing remote kernel URL locally.
167
+ - `instance forget` removes a local bookmark only.
168
+ - `instance delete` is destructive for admin-managed instances.
169
+ - In scripts, prefer explicit `-i <instance>` over relying on ambient active
170
+ instance state.
171
+
172
+ ## Domain Dev Workflow
173
+
174
+ **The `astrale` CLI is connect-only — it does not build, run, or deploy
175
+ domains.** The `astrale domain` group manages the admin catalog and installs a
176
+ running domain onto an instance (`list`, `publish`, `install`); it does NOT
177
+ build or run domains. `astrale domain list` shows the published catalog (add
178
+ `--check` to probe each URL's reachability, `--default-only` for the
179
+ install-on-every-instance set, `-q` to pipe install URLs). Building, running,
180
+ and deploying live in two separate tools:
181
+
182
+ - **`create-astrale-domain`** scaffolds a new standalone domain project
183
+ (`pnpm create astrale-domain <slug>`), writing an `astrale.config.ts`.
184
+ - **`astrale-domain`** (the `@astrale-os/sdk` bin, behind the project's
185
+ `pnpm dev` / `pnpm prod` scripts) runs `dev | prod | deploy <env> | build`.
186
+
187
+ Domains are **installed by URL or catalog origin**, never from a file (there is
188
+ no committed `spec.json`). `astrale domain install` has two modes:
189
+
190
+ - **default (via admin)** — `astrale domain install <origin|url> -i <slug>`
191
+ installs a PUBLISHED domain through the admin control plane
192
+ (`DomainEntry.install`), addressed by its catalog `origin` (the unique
193
+ registry key) or `url`. Run it bare to pick from the catalog interactively.
194
+ The target instance is the active one or `-i <slug>` and **must be
195
+ admin-managed** (otherwise it fails loudly and points you at `--direct`).
196
+ - **`--direct`** — `astrale domain install <url> --direct` installs a url
197
+ straight onto the instance kernel (`Domain.install`), bypassing the
198
+ catalog. Works on ANY instance you can authenticate to (managed, bookmarked,
199
+ or local), using your own authority, and is the only mode that runs the
200
+ identity-override consent gate. Use it for dev/local instances and
201
+ freshly-deployed, not-yet-published domains.
202
+
203
+ With the **managed (`astrale`) adapter**, `pnpm prod` publishes the bundle
204
+ through the platform on the configured instance in one step. The service serves at
205
+ `https://<name>-<hash>.svc.<region>.astrale.ai` (the CLI session is the auth).
206
+ Every time you re-deploy, you must then re-install the domain.
207
+
208
+ For authoring domains end-to-end (schema, handlers, external APIs, deploys),
209
+ load the **astrale-domain** skill; for graph-level schema surgery on a live
210
+ kernel, **astrale-live-domain-edit**.
211
+
212
+ ## Auth And Credentials
213
+
214
+ Keep the auth model simple:
215
+
216
+ - `astrale auth login` authenticates with an IdP and stores an IdP-backed local
217
+ identity/session.
218
+ - `astrale identity create <name>` creates a local key-backed identity.
219
+ - `astrale identity register <name> -i <instance>` registers that identity with
220
+ a target instance.
221
+ - `astrale use <name>` switches the active identity or active instance when the
222
+ name is unambiguous. Use `--identity` or `--instance` when it is ambiguous.
223
+ - `--as <identity>` makes a kernel command call as that identity.
224
+ - `--creds <token>` sends an already minted credential and skips normal signing.
225
+
226
+ Useful checks:
227
+
228
+ ```bash
229
+ astrale status
230
+ astrale whoami
231
+ astrale auth status
232
+ astrale identity list
233
+ astrale identity whoami
234
+ ```
235
+
236
+ `astrale auth token --raw` prints a cached IdP provider token for shell use.
237
+ That is different from `astrale token`, which mints a delegation token for
238
+ kernel/worker calls.
239
+
240
+ ### Session lifetime and refresh
241
+
242
+ IdP sessions refresh themselves: every kernel command silently exchanges the
243
+ refresh token when the cached access token is stale, and concurrent `astrale`
244
+ processes serialize that exchange on a per-identity file lock (refresh tokens
245
+ are single-use — the lock is what makes parallel agent-driven commands safe).
246
+ One `astrale auth login` should therefore last until the IdP itself ends the
247
+ session. Access tokens are also cached **per audience**, so alternating
248
+ commands between instances does not burn a refresh per flip.
249
+
250
+ Refresh failures come in two distinct flavors — read the error before
251
+ re-authenticating:
252
+
253
+ - "could not be refreshed … run: astrale auth login" — the grant is dead
254
+ (IdP session ended, idle/absolute timeout, logout elsewhere). Re-login is
255
+ the only fix.
256
+ - "Could not reach the IdP … retry the command" — transient network/IdP
257
+ outage. The cached session is still valid; do NOT re-login, just retry.
258
+
259
+ ### Agent auth
260
+
261
+ An agent driving the CLI needs no special flow: it shares `~/.astrale`, so one
262
+ human `astrale auth login` is enough and every subsequent command (including
263
+ parallel ones) self-refreshes. For fully headless setups with no human login,
264
+ use a key-backed identity — `astrale identity create <name>` then
265
+ `astrale identity register <name> -i <instance>` — which signs locally and
266
+ never expires; or hand the agent a TTL-bound delegation token minted with
267
+ `astrale token` and passed via `--creds`.
268
+
269
+ ## Delegation Tokens
270
+
271
+ `astrale token` mints a delegation token for the active instance and identity.
272
+ Use it when another process, script, or worker needs to call with delegated
273
+ authority.
274
+
275
+ Common flow:
276
+
277
+ ```bash
278
+ export TOKEN=$(astrale token --audience workspace.astrale.ai --raw)
279
+ astrale call /:workspace.astrale.ai:class.App:available \
280
+ --creds "$TOKEN" \
281
+ --json
282
+ ```
283
+
284
+ Notes:
285
+
286
+ - Default TTL is 3600 seconds.
287
+ - `--audience <aud>` should match the receiving service or worker expectation.
288
+ - `--for <identity>` is an alias for `--as <identity>`.
289
+ - Use `--raw` when assigning the token to an environment variable.
290
+ - Use `--json` when a machine should parse token metadata.
291
+
292
+ ## Graph Exploration
293
+
294
+ Use these commands for graph inspection:
295
+
296
+ ```bash
297
+ astrale ls /
298
+ astrale get /some/path
299
+ astrale query / --depth 1
300
+ astrale query --cypher 'MATCH (n) RETURN n LIMIT 5'
301
+ astrale describe /some/path
302
+ astrale call <path> --describe
303
+ ```
304
+
305
+ `get` is a point read: exactly one path or `@id`, flat node output, and an
306
+ opaque missing-or-masked error. Richer reads live on `query`. Positional
307
+ `query` roots build the CLI's structured QueryASTInput and lower through
308
+ `function.get` today; a future true query syscall can back the same door.
309
+
310
+ - **Multi-root / subtree** — `query` takes one or more roots:
311
+ `astrale query /a /b @c`. `--depth 0..5` fetches descendants
312
+ (0 = just the roots). `ls` is a depth-1 preset; `ls -R` is depth 5
313
+ reassembled into a tree client-side; `describe` is depth 1.
314
+ - **Children / edge selectors** — `--children <json>` and `--edges <json>`
315
+ are symmetric. `--children` is `{ classes?, limit?, cursor?, order? }`
316
+ (shapes the depth-1 children page; needs `--depth ≥ 1`). `--edges` is
317
+ `{ as?, classes?, direction?: in|out|both, limit?, cursor?, order? }` or a
318
+ JSON array of such selectors (each aliased by `as`) to include incident edges.
319
+ - **Cypher escape hatch** — `query --cypher '<query>'` calls the kernel's
320
+ read-only Cypher endpoint.
321
+ - **Soft-root visibility** — a structured read NEVER 403s: unreadable or
322
+ missing roots (and descendants) are omitted. Fewer nodes than expected = a
323
+ visibility/existence gap, not an operation permission error.
324
+ - **Cursors** — when a children/edge page overflows, per-root cursors land in
325
+ `.next`; on a TTY `query` prints a dim `more: …` footer with the flag to
326
+ page on.
327
+
328
+ ```bash
329
+ astrale get /kernel.astrale.ai/class.Root
330
+ astrale query /a /b --edges '{"direction":"both"}'
331
+ astrale query / --depth 1
332
+ astrale query /kernel.astrale.ai --depth 2 \
333
+ --children '{"classes":["/:kernel.astrale.ai:class.Folder"]}'
334
+ astrale query --cypher 'MATCH (n) RETURN count(n) AS total'
335
+ ```
336
+
337
+ Admin host records are exposed by the concrete provider class, not by the
338
+ provider-neutral `Host` interface:
339
+
340
+ ```bash
341
+ astrale call /:admin.astrale.ai:class.ScalewayVPS:list -i admin --json
342
+ astrale call /:admin.astrale.ai:class.ScalewayVPS:list --describe -i admin
343
+ ```
344
+
345
+ Gotchas:
346
+
347
+ - `query --cypher` is read-only; the kernel rejects write keywords such as
348
+ `CREATE`, `DELETE`, `SET`, `MERGE`, `REMOVE`, and `DETACH`.
349
+ - `describe` can return large properties such as serialized schemas. Pipe to
350
+ `jq` or use command-specific flags when available.
351
+ - `ls` has list-specific output controls such as `-q/--quiet`, `--count`, and
352
+ `-l/--long`; `--filter <kind>` is a client-side post-filter on child KIND or
353
+ label. For a server-side class filter use `query --depth 1 --children`.
354
+ - For operation schemas, prefer `astrale call <path> --describe` before
355
+ executing a call you are unsure about.
356
+ - **`class.<Name>` materializes as a `Folder` node** (kind `Folder`, name
357
+ prefixed `class.`) whose children are the class's callable Functions. There
358
+ is no `Class` node at that tree position — the Class definition lives inside
359
+ the Domain's serialized `schema` prop. So `--filter Class` returns zero; use
360
+ `--filter Folder`, or descend into `class.<X>` and filter on `Function`.
361
+
362
+ ## Batch Writes
363
+
364
+ `astrale mutate` applies a **PatchData** patch through `function.mutate` — one
365
+ atomic, all-or-nothing write. Patch source ladder (highest wins), mirroring
366
+ `call`: `--data <json>` > `--file <path>` > piped stdin.
367
+
368
+ ```json
369
+ {
370
+ "nodes": {
371
+ "create": [{ "class": "/:d:class.X", "at": "/d/x", "props": {} }],
372
+ "update": [{ "class": "/:d:class.X", "path": "/d/x", "props": {} }],
373
+ "delete": [{ "class": "/:d:class.X", "path": "/d/x" }]
374
+ },
375
+ "edges": {
376
+ "create": [{ "class": "/:d:class.e", "source": "/a", "target": "/b", "props": {} }],
377
+ "delete": [{ "class": "/:d:class.e", "source": "/a", "target": "/b" }]
378
+ }
379
+ }
380
+ ```
381
+
382
+ Every arm is optional (defaults to `[]`). The result is the minted id maps:
383
+ `createdNodes` (`at` path → node id) and `createdEdges`
384
+ (`class|source|slug|target` tuple → edge id); `--json` emits it raw.
385
+
386
+ - **`--dry`** validates locally against the kernel's `patchDataSchema` and prints
387
+ the normalized form — no round-trip. Catches a malformed patch before sending.
388
+ - **Per-arm authorization** — a `create` needs `USE` on the class and `EDIT` on
389
+ the parent; an `update`/`delete` needs `EDIT` on the target. Any denied arm
390
+ fails the WHOLE patch (no partial apply).
391
+ - **`delete`** is leaf-only per arm — to remove a subtree, include every
392
+ descendant in the `delete` arm.
393
+
394
+ ```bash
395
+ astrale mutate --data '{"nodes":{"create":[{"class":"/:blog.acme.com:class.Author","at":"/blog.acme.com/authors/ada","props":{}}]}}'
396
+ astrale mutate --file patch.json
397
+ astrale mutate --file patch.json --dry
398
+ echo '{"nodes":{"delete":[{"class":"/:d:class.X","path":"/d/x"}]}}' | astrale mutate
399
+ ```
400
+
401
+ ## Output / TTY Behavior
402
+
403
+ Output is selected from stdout shape and flags:
404
+
405
+ - TTY default: human-readable output, usually YAML for objects and tables for
406
+ lists.
407
+ - Pipe, redirect, `--json`, or `--raw`: machine-oriented output.
408
+ - `--json`: always valid JSON for tools like `jq`.
409
+ - `--raw`: unwrap scalars for shell assignment and write raw bytes for binary
410
+ responses.
411
+ - `--format yaml|json`: explicit structured output where supported.
412
+ - `call --output <file>` writes binary/raw output to a file.
413
+ - Piped stdin is read by `astrale call` and `astrale mutate`; stdin on a TTY is
414
+ ignored.
415
+ - `--data` takes precedence over stdin and `key=value` params.
416
+ - `key=value` values are auto-coerced: `true`/`false`/`null`, numeric strings
417
+ → numbers, `{…}`/`[…]` → parsed JSON; everything else stays a string. To
418
+ force a digits-only STRING (or pass nested values), use `--data`.
419
+ - **Big payloads go through stdin** — argv caps around 128 KB, so multi-MB
420
+ JSON (e.g. a base64 bundle) must be piped:
421
+ `echo "$PAYLOAD_JSON" | astrale call <path> --json`.
422
+
423
+ ### `get` output shapes
424
+
425
+ `get` always returns the **flat node** projection `{ id, class, path, props }`
426
+ for exactly one root — the stable shape scripts and Studio parse, with `props`
427
+ keyed by fully-qualified keys (`<domain>:class.X.property.name`). `-l` keeps
428
+ `__labels`/`classId`.
429
+
430
+ `query` always returns the full `GraphData { nodes, edges, aliases }` envelope
431
+ plus `.roots` and any `.next` cursors. Use it for multi-root reads, subtree
432
+ expansion, edge expansion, cursor paging, and `--cypher`.
433
+ `mutate` prints the minted id maps (tables on a TTY, raw
434
+ `{ createdNodes, createdEdges }` under `--json`).
435
+
436
+ Examples:
437
+
438
+ ```bash
439
+ astrale ls / --json | jq .
440
+ TOKEN=$(astrale token --audience workspace.astrale.ai --raw)
441
+ astrale call /:d:class.Asset:render id=123 --output asset.png
442
+ astrale call /:d:class.X:m -d '{"name":"alice"}'
443
+ ```
444
+
445
+ ## Driving The GUI
446
+
447
+ Use `astrale browser` to prepare an authenticated GUI browser session that an
448
+ agent can drive with `agent-browser`.
449
+
450
+ Install once:
451
+
452
+ ```bash
453
+ npm install -g agent-browser && agent-browser install
454
+ npx skills add vercel-labs/agent-browser
455
+ ```
456
+
457
+ Connect and verify:
458
+
459
+ ```bash
460
+ astrale browser
461
+ astrale browser --check
462
+ astrale browser --login
463
+ astrale browser --cdp 9222
464
+ ```
465
+
466
+ After `astrale browser` connects, it prints the exact `agent-browser --profile`
467
+ command to use. Driving the page is agent-browser's job:
468
+
469
+ ```bash
470
+ agent-browser --profile <dir> snapshot
471
+ agent-browser --profile <dir> open <url>
472
+ agent-browser --profile <dir> click @e3
473
+ agent-browser --profile <dir> eval '<js>'
474
+ ```
475
+
476
+ The GUI session uses an httpOnly cookie. There is no token-injection shortcut;
477
+ the persistent browser profile is the session boundary.
478
+
479
+ ## Debugging And Common Errors
480
+
481
+ Start with local context:
482
+
483
+ ```bash
484
+ astrale status
485
+ astrale admin status
486
+ astrale instance active
487
+ astrale auth status
488
+ astrale whoami
489
+ ```
490
+
491
+ Use diagnostics:
492
+
493
+ - Add `--debug` to kernel commands for full error diagnostics — including
494
+ the server-side cause chain (`data.cause`), which shows the ROOT failure
495
+ inside wrapped errors (e.g. what actually failed under a
496
+ `Delegation mint failed` or `KERNEL_ERROR`).
497
+ - Use global `--log-level debug` for verbose CLI logging.
498
+ - Use global `--log-format json` when an agent or script should parse logs.
499
+ - Use `--json` or `--raw` for structured command output.
500
+ - Use `--ci` and `--no-prompt` in non-interactive automation.
501
+ - Use `--timeout <ms>` when a kernel call is valid but slow.
502
+ - `astrale logs -i <instance>` defaults to tailing the kernel EVENT JOURNAL
503
+ (the `function.journal` syscall): SEQ/TIME/TOPIC/PRINCIPAL on a TTY, the raw
504
+ `JournalEntry[]` under `--json`. Filter with `--topic <glob>` (':'-segmented,
505
+ `*` one segment / `**` zero-or-more, e.g. `op:*:failed`), `--principal <id>`,
506
+ `--since`/`--until` (epoch-ms or ISO-8601), `--limit <n>` (default 200), and
507
+ `--follow` (client-side poll, tailing by `--cursor`).
508
+ - Use `astrale logs --service <slug> [--tail N]` to tail a MANAGED SERVICE's
509
+ runtime logs instead — console output, 5xx accesses, and uncaught exception
510
+ stacks (the readable side of `internal error; reference = …` responses). The
511
+ slug is the first label of the service's `…svc.<region>.astrale.ai` URL (also
512
+ accepts the full URL). In-memory, last ~500 lines, resets on runtime
513
+ restart; services deployed before log capture need one redeploy.
514
+
515
+ Common error classes and first checks:
516
+
517
+ | Error shape | First check |
518
+ |---|---|
519
+ | Connection error | `astrale status`; verify the instance URL and network path |
520
+ | Authentication error | `astrale auth status`, `astrale whoami`, active identity |
521
+ | Permission denied (call) | Does the named node actually exist (`astrale get`)? Then active identity and target operation permissions |
522
+ | `get`/`ls` returns fewer nodes than expected | NOT a 403 — a graph read never denies; unreadable/missing roots+descendants are omitted by soft-root visibility. Check the node exists and you hold `READ`, not the operation grant |
523
+ | `mutate` fails whole patch | Per-arm authz: a `create` needs `USE` on the class + `EDIT` on the parent; `update`/`delete` needs `EDIT` on the target. `--dry` first to rule out a malformed patch |
524
+ | Not found | `get` errors NOT_FOUND only when NO root resolves; else path spelling, active instance, installed domain |
525
+ | Validation error | `astrale call <path> --describe`; for a patch, `astrale mutate --dry` |
526
+ | Timeout | Target availability and `--timeout <ms>` |
527
+
528
+ If a command fails only in a script, compare TTY vs non-TTY behavior and pass
529
+ explicit `--json`, `--raw`, `-i <instance>`, and `--as <identity>` as needed.
530
+
531
+ ## Reporting DX Issues
532
+
533
+ Astrale runs an in-graph issue tracker in the admin control plane (the `Issue`
534
+ class on the admin domain). **You — the agent driving this CLI — file issues
535
+ automatically** whenever working with Astrale costs you friction. This is the
536
+ primary feedback channel; treat filing as part of the task, not an interruption.
537
+
538
+ File an issue when you hit:
539
+
540
+ - **friction** (`kind=friction`) — time lost to misdirection, an unclear or
541
+ surprising API, a missing/confusing error, or **stale docs or skills** (a
542
+ `SKILL.md` / doc that contradicted reality).
543
+ - **bug** (`kind=bug`) — something broke, behaved unexpectedly, or forced a
544
+ workaround. Say so in the title when it was blocking.
545
+ - **feature** (`kind=feature`) — a capability that should exist and would have
546
+ unblocked you.
547
+
548
+ **Dedup first** — list open issues and comment instead of duplicating:
549
+
550
+ ```bash
551
+ astrale call /:admin.astrale.ai:class.Issue:list status=open -i admin --json
552
+ # if one matches, add to it instead of filing a new one:
553
+ astrale call /:admin.astrale.ai:class.Issue:comment -i admin \
554
+ id=<issue-id> body="Hit this too during a domain deploy — same schemaHash mismatch."
555
+ ```
556
+
557
+ **Otherwise file it** (one issue per distinct problem):
558
+
559
+ ```bash
560
+ astrale call /:admin.astrale.ai:class.Issue:report -i admin \
561
+ kind=bug \
562
+ title="managed deploy stuck on old schemaHash after pnpm prod" \
563
+ tags='["deploy","cli"]' \
564
+ instance=<your-instance-slug> \
565
+ command="pnpm prod" \
566
+ body="pnpm prod builds and uploads, but the managed service never pivots to the
567
+ new schemaHash — /meta keeps returning the old hash until the service is removed
568
+ and recreated. Expected the redeploy to swap the version."
569
+ ```
570
+
571
+ Attach context to make it actionable, but **strip secrets** from `trace` (no
572
+ tokens, credentials, private keys, cookies):
573
+
574
+ ```bash
575
+ ... trace="$(astrale logs --service <slug> --tail 40)"
576
+ ```
577
+
578
+ Fields: `kind` ∈ {bug, friction, feature}; `tags` are area slugs — prefer the
579
+ common set (`cli`, `sdk`, `kernel`, `adapter`, `deploy`, `install`,
580
+ `permissions`, `views`, `domain-authoring`, `docs`, `skill`, `provisioning`) and
581
+ add a new one only when none fit; `instance` is your instance slug (omit for
582
+ docs/skill issues). The reporter's email is recorded automatically from the
583
+ `email` claim on your credential — do NOT pass it yourself (there is no such
584
+ param; it must not be guessed or falsified). `report` returns `{ id, status }`.
585
+
586
+ Rules:
587
+
588
+ - Best-effort and non-blocking: if `report` fails, note it and keep working —
589
+ never let filing an issue derail the user's task.
590
+ - Be specific: exact command, exact error, what you expected. A vague issue is
591
+ noise; a reproducible one gets fixed.
592
+ - Tell the user you filed it (mention the returned id) so they can follow up.
593
+ - Triage and status changes are admin-only — you file and comment; admins
594
+ resolve.
595
+
596
+ ## Storage
597
+
598
+ CLI state lives under `ASTRALE_HOME` when set, otherwise `~/.astrale`.
599
+
600
+ Core paths:
601
+
602
+ ```text
603
+ ~/.astrale/
604
+ config.json CLI and admin config
605
+ install.json Script-install metadata for `astrale update`
606
+ instances.json Active instance and local instance records
607
+ identities.json Active identity and identity metadata
608
+ idps/ IdP provider metadata
609
+ idp-sessions/ Cached IdP sessions
610
+ keys/ Local identity keypairs
611
+ data/ Local data directory used by local adapters
612
+ browser.json Last connected GUI browser session
613
+ browser/<host>/ Persistent browser profile for GUI auth
614
+ ```
615
+
616
+ Optional overrides:
617
+
618
+ - `ASTRALE_HOME`: root for CLI state.
619
+ - `ASTRALE_KEYS_DIR`: keypair directory.
620
+ - `ASTRALE_DATA_DIR`: data directory.
621
+
622
+ Keep storage references centralized in this section. Other sections should
623
+ describe behavior, not repeat file locations.
624
+
625
+ ## Source Map
626
+
627
+ - Entry: `cli/bin/astrale.ts`
628
+ - Program and help wiring: `cli/src/program.ts`
629
+ - Command registration helpers: `cli/src/registry.ts`, `cli/src/command.ts`
630
+ - Commands: `cli/src/commands/`
631
+ - Shared output, auth, browser, paths, and local helpers: `cli/src/lib/`
632
+ - Kernel command plumbing and error formatting: `cli/src/kernel/`
633
+ - Tests for help and command behavior: `cli/src/commands/__tests__/`
@@ -0,0 +1,4 @@
1
+ {
2
+ "schemaVersion": "",
3
+ "comments": []
4
+ }
@@ -3,10 +3,7 @@
3
3
  # injected into the local runtime in dev, pushed to the Worker secret store in
4
4
  # prod. These files are gitignored — copy this to `.env.dev` and fill in.
5
5
  #
6
- # EXAMPLE_API_KEY=sk-...
6
+ # Add one line per secret your handlers read (they arrive as typed fields on
7
+ # `Env` — see `env.ts`). For example:
7
8
  #
8
- # ── Prober (the example external-API integration) ──────────────────────────
9
- # The scaffold probes monitor targets with a real, KEYLESS HTTP request by
10
- # default (no secret needed). These knobs are optional config, not secrets:
11
- # PROBER=http # `http` (default) | `mock` (offline/deterministic)
12
- # PROBE_TIMEOUT_MS=10000
9
+ # EXAMPLE_API_KEY=sk-...
@@ -1,7 +1,9 @@
1
1
  # astrale-domain
2
2
 
3
- A standalone Astrale domain. The authoring guide is not in this repo — it's the
4
- `astrale-domain` agent skill. Load it before changing the schema or handlers.
3
+ A standalone Astrale domain a **blank skeleton**: every folder is wired and
4
+ ready, with no classes, views, or integrations yet. The authoring guide is not in
5
+ this repo — it's the `astrale-domain` agent skill. Load it before changing the
6
+ schema or handlers.
5
7
 
6
8
  ## Agent skills
7
9
 
@@ -18,7 +20,7 @@ and this project's `@astrale-os/*` dependencies.
18
20
 
19
21
  ## Orientation
20
22
 
21
- See `README.md` for the project layout (`schema/`, `core/`, `integrations/`,
22
- `runtime/`, `views/`, `functions/`, `client/`), the dev/deploy loop, and the
23
- signing-identity note. `domain.ts` is the one place the domain contract is
24
- declared.
23
+ See `README.md` for the project layout (`schema/`, `icons.ts`, `core/`,
24
+ `integrations/`, `runtime/`, `views/`, `functions/`, `client/`), the dev/deploy
25
+ loop, and the signing-identity note. `domain.ts` is the one place the domain
26
+ contract is declared.