@lunora/cli 1.0.0-alpha.39 → 1.0.0-alpha.391

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 (133) hide show
  1. package/LICENSE.md +33 -0
  2. package/README.md +1 -1
  3. package/dist/bin.mjs +2 -10
  4. package/dist/index.d.mts +1019 -374
  5. package/dist/index.d.ts +1019 -374
  6. package/dist/index.mjs +1 -19
  7. package/dist/packem_chunks/dispatch.mjs +1 -0
  8. package/dist/packem_chunks/handler.mjs +1 -160
  9. package/dist/packem_chunks/handler10.mjs +1 -16
  10. package/dist/packem_chunks/handler11.mjs +1 -22
  11. package/dist/packem_chunks/handler12.mjs +1 -192
  12. package/dist/packem_chunks/handler13.mjs +3 -131
  13. package/dist/packem_chunks/handler14.mjs +1 -65
  14. package/dist/packem_chunks/handler15.mjs +1 -58
  15. package/dist/packem_chunks/handler16.mjs +1 -80
  16. package/dist/packem_chunks/handler17.mjs +7 -43
  17. package/dist/packem_chunks/handler18.mjs +1 -105
  18. package/dist/packem_chunks/handler19.mjs +1 -170
  19. package/dist/packem_chunks/handler2.mjs +1 -114
  20. package/dist/packem_chunks/handler20.mjs +3 -94
  21. package/dist/packem_chunks/handler21.mjs +3 -94
  22. package/dist/packem_chunks/handler22.mjs +1 -0
  23. package/dist/packem_chunks/handler23.mjs +2 -0
  24. package/dist/packem_chunks/handler24.mjs +2 -0
  25. package/dist/packem_chunks/handler25.mjs +99 -0
  26. package/dist/packem_chunks/handler26.mjs +9 -0
  27. package/dist/packem_chunks/handler27.mjs +1 -0
  28. package/dist/packem_chunks/handler3.mjs +1 -204
  29. package/dist/packem_chunks/handler4.mjs +3 -33
  30. package/dist/packem_chunks/handler5.mjs +1 -49
  31. package/dist/packem_chunks/handler6.mjs +1 -91
  32. package/dist/packem_chunks/handler7.mjs +1 -42
  33. package/dist/packem_chunks/handler8.mjs +2 -174
  34. package/dist/packem_chunks/handler9.mjs +1 -315
  35. package/dist/packem_chunks/runCodegenCommand.mjs +4 -52
  36. package/dist/packem_chunks/runDeployCommand.mjs +11 -594
  37. package/dist/packem_chunks/runDevCommand.mjs +2 -0
  38. package/dist/packem_chunks/runInitCommand.mjs +164 -1432
  39. package/dist/packem_chunks/runResetCommand.mjs +1 -41
  40. package/dist/packem_chunks/runRpcCommand.mjs +1 -68
  41. package/dist/packem_shared/COMMANDS-JClcR9JT.mjs +1 -0
  42. package/dist/packem_shared/DEFAULT_IMPORT_BATCH_SIZE-CyIsI3S1.mjs +1 -0
  43. package/dist/packem_shared/EXIT_CODE-D_XCixv8.mjs +1 -0
  44. package/dist/packem_shared/admin-token-VdUnvnKW.mjs +1 -0
  45. package/dist/packem_shared/admin-url-DJB8P6Jh.mjs +1 -0
  46. package/dist/packem_shared/binding-manifest-file-CQ1eQYy1.mjs +2 -0
  47. package/dist/packem_shared/buildRegistryIndex-Dc8D8AR6.mjs +1 -0
  48. package/dist/packem_shared/cap-error-body-YBKO32BF.mjs +1 -0
  49. package/dist/packem_shared/catalog-CahzmDLV.mjs +1 -0
  50. package/dist/packem_shared/cli-DwEpuZm9.mjs +2 -0
  51. package/dist/packem_shared/cli-manifest-CRet0egA.mjs +1 -0
  52. package/dist/packem_shared/cloudflare-credentials-BVmZnDZk.mjs +1 -0
  53. package/dist/packem_shared/codegen-error-AmH54ofi.mjs +3 -0
  54. package/dist/packem_shared/command-CAXl2A1S.mjs +1 -0
  55. package/dist/packem_shared/commands-DgUDxkA8.mjs +13 -0
  56. package/dist/packem_shared/createLogger-Cl18I8AX.mjs +2 -0
  57. package/dist/packem_shared/createRecordingSpawner-Ch7zuQQE.mjs +1 -0
  58. package/dist/packem_shared/deploy-target-DCWwiuAe.mjs +1 -0
  59. package/dist/packem_shared/diffSnapshots-htqNZT8Q.mjs +7 -0
  60. package/dist/packem_shared/docker-AqLAkOyY.mjs +1 -0
  61. package/dist/packem_shared/health-probe-Bw9JFfIy.mjs +1 -0
  62. package/dist/packem_shared/import-BRM1hs7j.mjs +12 -0
  63. package/dist/packem_shared/index-oHZBGBwB.mjs +1 -0
  64. package/dist/packem_shared/insertSchemaExtension-DuiV6cba.mjs +8 -0
  65. package/dist/packem_shared/lint-ignore-report-DKZagpqk.mjs +2 -0
  66. package/dist/packem_shared/mcp-config-file-CcDTeXIq.mjs +2 -0
  67. package/dist/packem_shared/open-url-EnKy--w-.mjs +1 -0
  68. package/dist/packem_shared/output-format-B4eQHi5y.mjs +2 -0
  69. package/dist/packem_shared/parseManifest-CwPTKdtS.mjs +1 -0
  70. package/dist/packem_shared/path-containment-CgxYZggb.mjs +1 -0
  71. package/dist/packem_shared/plan-Dl57T11P.mjs +5 -0
  72. package/dist/packem_shared/planDevCommand-D8sm56hO.mjs +1 -0
  73. package/dist/packem_shared/platform-diagnostics-Cn2g6Jh-.mjs +4 -0
  74. package/dist/packem_shared/prompt-cancelled-BvsNxg_Q.mjs +1 -0
  75. package/dist/packem_shared/render-lunora-error-C3OJY5wk.mjs +2 -0
  76. package/dist/packem_shared/resolve-BrsV4Qyc.mjs +5 -0
  77. package/dist/packem_shared/resolve-target-C_ZloTvd.mjs +1 -0
  78. package/dist/packem_shared/runAddCommand-DTvfp4h2.mjs +1 -0
  79. package/dist/packem_shared/runExportCommand-slAq5BCF.mjs +5 -0
  80. package/dist/packem_shared/runMigrateGenerateCommand-BwemPIOz.mjs +11 -0
  81. package/dist/packem_shared/schemaIrToSnapshot-BHuNOfgs.mjs +1 -0
  82. package/dist/packem_shared/secret-key-6bCftsxj.mjs +1 -0
  83. package/dist/packem_shared/shared-D-zCOmgY.mjs +1 -0
  84. package/dist/packem_shared/storage-DWhTX8eS.mjs +1 -0
  85. package/dist/packem_shared/tui-prompts-B3YwUhGw.mjs +4 -0
  86. package/dist/packem_shared/variables-CPYyJtsL.mjs +1 -0
  87. package/dist/packem_shared/wrangler-name-Dsk5K1f-.mjs +1 -0
  88. package/dist/packem_shared/wrangler-secrets-3chIVv3H.mjs +1 -0
  89. package/package.json +39 -19
  90. package/skills/README.md +35 -17
  91. package/skills/lunora/SKILL.md +154 -64
  92. package/skills/lunora-create-package/SKILL.md +97 -84
  93. package/skills/lunora-deploy/SKILL.md +175 -105
  94. package/skills/lunora-functions/SKILL.md +362 -56
  95. package/skills/lunora-migration-helper/SKILL.md +162 -137
  96. package/skills/lunora-performance-audit/SKILL.md +137 -95
  97. package/skills/lunora-quickstart/SKILL.md +137 -136
  98. package/skills/lunora-realtime/SKILL.md +140 -99
  99. package/skills/lunora-setup-auth/SKILL.md +162 -102
  100. package/skills/lunora-setup-hyperdrive/SKILL.md +114 -97
  101. package/skills/lunora-setup-hyperdrive-global/SKILL.md +93 -90
  102. package/skills/lunora-setup-mail/SKILL.md +85 -113
  103. package/skills/lunora-setup-scheduler/SKILL.md +132 -96
  104. package/skills/lunora-setup-storage/SKILL.md +189 -95
  105. package/dist/packem_chunks/planDevCommand.mjs +0 -541
  106. package/dist/packem_chunks/runMigrateGenerateCommand.mjs +0 -397
  107. package/dist/packem_shared/COMMANDS-B0ftFD_3.mjs +0 -948
  108. package/dist/packem_shared/DEFAULT_IMPORT_BATCH_SIZE-Ck-2bU08.mjs +0 -244
  109. package/dist/packem_shared/admin-url-4UzT-CI4.mjs +0 -19
  110. package/dist/packem_shared/api-spec-CtA6ilu4.mjs +0 -13
  111. package/dist/packem_shared/buildRegistryIndex-BcYe607_.mjs +0 -38
  112. package/dist/packem_shared/codegen-error-DJG-ghs_.mjs +0 -31
  113. package/dist/packem_shared/command-D3lB_4Az.mjs +0 -19
  114. package/dist/packem_shared/commands-B-gR09Z_.mjs +0 -845
  115. package/dist/packem_shared/createLogger-B40gPzQo.mjs +0 -78
  116. package/dist/packem_shared/createRecordingSpawner-DxI3mebw.mjs +0 -43
  117. package/dist/packem_shared/detect-package-manager-DYp7n3mJ.mjs +0 -61
  118. package/dist/packem_shared/diffSnapshots-BeDvvNiF.mjs +0 -161
  119. package/dist/packem_shared/docker-hMQ97KSQ.mjs +0 -21
  120. package/dist/packem_shared/insertSchemaExtension-DAqbfr9Z.mjs +0 -64
  121. package/dist/packem_shared/open-url-Dfq6fAyT.mjs +0 -41
  122. package/dist/packem_shared/output-format-wUvAN6AL.mjs +0 -17
  123. package/dist/packem_shared/parseArgs-YXFuKdEk.mjs +0 -56
  124. package/dist/packem_shared/parseManifest--vZf2FY1.mjs +0 -94
  125. package/dist/packem_shared/prompt-cancelled-APzX1Im-.mjs +0 -9
  126. package/dist/packem_shared/resolve-target-qbsJ_5sF.mjs +0 -16
  127. package/dist/packem_shared/runAddCommand-bnY6-HKb.mjs +0 -4
  128. package/dist/packem_shared/schema-drift-gate-BtBt0as0.mjs +0 -79
  129. package/dist/packem_shared/schemaIrToSnapshot-DdsljJT-.mjs +0 -43
  130. package/dist/packem_shared/storage-BIsph-Vk.mjs +0 -84
  131. package/dist/packem_shared/tui-prompts-BjEN8XgP.mjs +0 -658
  132. package/dist/packem_shared/wrangler-name-cy4yhm9j.mjs +0 -12
  133. package/dist/packem_shared/wrangler-secrets-P2_ZUR-k.mjs +0 -47
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lunora/cli",
3
- "version": "1.0.0-alpha.39",
4
- "description": "The Lunora CLI: init, dev, deploy, codegen, run, reset, and migrate commands",
3
+ "version": "1.0.0-alpha.391",
4
+ "description": "The Lunora CLI: init, dev, deploy, codegen, migrate, seed, doctor, insights, logs, registry, and the rest of the project commands",
5
5
  "keywords": [
6
6
  "agent-skills",
7
7
  "cli",
@@ -51,27 +51,47 @@
51
51
  "access": "public"
52
52
  },
53
53
  "dependencies": {
54
- "@bomb.sh/tab": "0.0.17",
55
- "@lunora/codegen": "1.0.0-alpha.17",
56
- "@lunora/config": "1.0.0-alpha.28",
57
- "@lunora/container": "1.0.0-alpha.5",
58
- "@lunora/d1": "1.0.0-alpha.9",
59
- "@lunora/seed": "1.0.0-alpha.7",
60
- "@visulima/cerebro": "3.0.0-alpha.32",
61
- "@visulima/error": "6.0.0-alpha.34",
62
- "@visulima/fs": "5.0.0-alpha.32",
63
- "@visulima/pail": "4.0.0-alpha.22",
64
- "@visulima/path": "3.0.0-alpha.13",
65
- "@visulima/spinner": "1.0.0-alpha.4",
66
- "@visulima/tui": "1.0.0-alpha.26",
67
- "cfonts": "^3.3.1",
68
- "giget": "3.3.0",
54
+ "@bomb.sh/tab": "0.0.22",
55
+ "@lunora/advisor": "1.0.0-alpha.211",
56
+ "@lunora/bindings": "1.0.0-alpha.108",
57
+ "@lunora/codegen": "1.0.0-alpha.297",
58
+ "@lunora/config": "1.0.0-alpha.345",
59
+ "@lunora/container": "1.0.0-alpha.74",
60
+ "@lunora/d1": "1.0.0-alpha.175",
61
+ "@lunora/errors": ">=1.0.0-alpha.51 <2.0.0-0",
62
+ "@lunora/mcp": "1.0.0-alpha.235",
63
+ "@lunora/runtime": "1.0.0-alpha.195",
64
+ "@lunora/seed": "1.0.0-alpha.214",
65
+ "@visulima/cerebro": "3.1.2",
66
+ "@visulima/error": "6.1.0",
67
+ "@visulima/fs": "6.0.29",
68
+ "@visulima/pail": "5.0.0",
69
+ "@visulima/path": "4.0.0",
70
+ "@visulima/spinner": "1.0.1",
71
+ "@visulima/tui": "4.0.29",
72
+ "@visulima/tui-kit": "1.0.32",
73
+ "adm-zip": "0.6.1",
74
+ "csv-parse": "7.0.3",
75
+ "giget": "3.3.1",
69
76
  "jsonc-parser": "^3.3.1",
70
- "magic-string": "^0.30.21",
71
- "react": "^19.2.7",
77
+ "magic-string": "^1.4.2",
78
+ "react": "^19.3.0",
72
79
  "react-reconciler": "^0.33.0",
80
+ "smol-toml": "1.9.0",
73
81
  "ts-morph": "^28.0.0"
74
82
  },
83
+ "peerDependencies": {
84
+ "mysql2": "*",
85
+ "pg": "*"
86
+ },
87
+ "peerDependenciesMeta": {
88
+ "mysql2": {
89
+ "optional": true
90
+ },
91
+ "pg": {
92
+ "optional": true
93
+ }
94
+ },
75
95
  "engines": {
76
96
  "node": "^22.15.0 || >=24.11.0"
77
97
  }
package/skills/README.md CHANGED
@@ -9,21 +9,39 @@ framework correctly. They ship inside `@lunora/cli` and are discovered by the
9
9
  Each skill is a `SKILL.md` with YAML frontmatter (`name`, `description`) in its
10
10
  own directory:
11
11
 
12
- | Skill | Use for |
13
- | -------------------------- | --------------------------------------------------------------------------- |
14
- | `lunora` | Router — start here, then switch to the matching skill below. |
15
- | `lunora-quickstart` | `lunora init` / adding Lunora to an app + first round-trip. |
16
- | `lunora-functions` | Core authoring rules — schema, validators, query/mutation/action, `ctx.db`. |
17
- | `lunora-realtime` | Client reactivity — live hooks, optimistic updates, `@lunora/db`. |
18
- | `lunora-setup-auth` | Authentication via `lunora registry add auth` (+ providers). |
19
- | `lunora-setup-mail` | Transactional email via `lunora registry add mail` — `sendEmail` actions. |
20
- | `lunora-setup-storage` | R2 file storage via `lunora registry add storage` — signed upload/download. |
21
- | `lunora-setup-scheduler` | Deferred (`ctx.scheduler`) + cron jobs (`lunora registry add crons`). |
22
- | `lunora-create-package` | Building a reusable registry item or `@lunora/*` package. |
23
- | `lunora-migration-helper` | Schema/data migrations, `.global()` D1 flow, the drift gate. |
24
- | `lunora-deploy` | Deploying to Cloudflare — wrangler bindings, secrets, the gate. |
25
- | `lunora-performance-audit` | Scans, indexes, OCC write conflicts, sharding/`.global()`. |
12
+ | Skill | Use for |
13
+ | -------------------------------- | ---------------------------------------------------------------------------- |
14
+ | `lunora` | Router — start here, then switch to the matching skill below. |
15
+ | `lunora-quickstart` | `lunora init` / adding Lunora to an app + first round-trip. |
16
+ | `lunora-functions` | Core authoring rules — schema, validators, query/mutation/action, `ctx.db`. |
17
+ | `lunora-realtime` | Client reactivity — live hooks, optimistic updates, `@lunora/db`. |
18
+ | `lunora-setup-auth` | Authentication via `lunora registry add auth` (+ providers). |
19
+ | `lunora-setup-mail` | Transactional email via `lunora registry add mail` — `sendEmail` actions. |
20
+ | `lunora-setup-storage` | R2 file storage via `lunora registry add storage` — signed upload/download. |
21
+ | `lunora-setup-scheduler` | Deferred (`ctx.scheduler`) + cron jobs (`lunora registry add crons`). |
22
+ | `lunora-setup-hyperdrive` | Existing Postgres/MySQL from an action — `ctx.sql`, non-reactive. |
23
+ | `lunora-setup-hyperdrive-global` | Postgres/MySQL as a reactive `.global()` backend; D1 → Hyperdrive migration. |
24
+ | `lunora-create-package` | Building a reusable registry item or `@lunora/*` package. |
25
+ | `lunora-migration-helper` | Schema/data migrations, `.global()` DDL flow, the drift gate. |
26
+ | `lunora-deploy` | Deploying to Cloudflare — wrangler bindings, secrets, the gate. |
27
+ | `lunora-performance-audit` | `lunora insights`, scans, indexes, OCC conflicts, sharding/`.global()`. |
26
28
 
27
- These are mirrored into `.agents/skills/` and `.claude/skills/` (via symlinks)
28
- so agents working inside this repo pick them up directly. The source of truth
29
- lives here so the published `@lunora/cli` tarball carries them.
29
+ These are mirrored (via symlinks) into `.agents/skills/` and `.claude/skills/`,
30
+ so agents working inside this repo pick them up directly, and into
31
+ `plugins/lunora/skills/`, the payload of the Claude Code / Codex plugin. The
32
+ source of truth lives here so the published `@lunora/cli` tarball carries them —
33
+ `lunora rules install` copies this directory into a consumer project.
34
+
35
+ **Adding a skill?** Create it here, then mirror it through all three hops:
36
+
37
+ ```bash
38
+ ln -s ../../packages/cli/skills/<name> .agents/skills/<name>
39
+ ln -s ../../.agents/skills/<name> .claude/skills/<name>
40
+ ln -s ../../../packages/cli/skills/<name> plugins/lunora/skills/<name>
41
+ ```
42
+
43
+ `scripts/check-skill-mirrors.js` (run on every `pnpm install`) fails if a mirror
44
+ is missing, dangling, or has become a real directory — a copied directory keeps
45
+ resolving while it silently drifts from the source, so it is treated as an
46
+ error rather than a warning. Forget a hop and it prints the exact `ln -s` for
47
+ the one you missed, so `pnpm install` is the shortest path to the right command.
@@ -1,83 +1,173 @@
1
1
  ---
2
2
  name: lunora
3
- description: Routes general Lunora requests to the right project skill. Use when the user
4
- asks which Lunora skill to use, or gives an underspecified task for a Lunora
5
- app (a type-safe, real-time backend on Cloudflare Workers + Durable Objects
6
- with a Vite-first DX).
3
+ description: Routes general Lunora requests to the right Lunora skill and gives the
4
+ shared mental model (codegen loop, generated `api`/`internal` references,
5
+ review commands, add-on capabilities, the `@lunora/mcp` server). Use when the
6
+ user asks which Lunora skill to use, gives an underspecified task in a project
7
+ with a `lunora/` directory or `lunorash`/`@lunora/*` dependencies, asks to
8
+ review or audit Lunora code, asks about an add-on without its own skill
9
+ (queues, workflows, agents, AI, flags, payments, notifications), or wants to
10
+ expose a deployment to an AI agent over MCP.
7
11
  ---
8
12
 
9
13
  # Lunora
10
14
 
11
- Use this as the routing skill for Lunora work in this repo.
15
+ Lunora is a type-safe, real-time backend on Cloudflare Workers + Durable
16
+ Objects. Functions are chainable `query` / `mutation` / `action` builders; state
17
+ lives in one `ShardDO` per app by default (SQLite, OCC, hibernated WebSocket
18
+ subscriptions). `.shardBy(key)` partitions a table across many DOs and
19
+ `.global()` replicates it to D1 (or Postgres/MySQL over Hyperdrive) for
20
+ cross-region reads. Codegen produces the types the client and server share.
12
21
 
13
- Lunora exposes a Convex-style functional API (`defineSchema`, `query`,
14
- `mutation`, `action`) on top of Cloudflare Workers and Durable Objects. State
15
- lives in a per-app `ShardDO` (SQLite, OCC, hibernated WebSocket subscriptions)
16
- by default; `.shardBy(key)` partitions it across many DOs and `.global()`
17
- replicates a table to D1 for low-latency cross-region reads. A Vite plugin
18
- drives codegen and end-to-end type sync.
22
+ If a project-level `AGENTS.md` / `CLAUDE.md` exists, read it first; it overrides
23
+ these defaults. If a more specific Lunora skill matches, switch to it.
19
24
 
20
- If a more specific Lunora skill clearly matches the request, use that instead.
21
-
22
- ## Start Here
23
-
24
- Before writing or changing any `lunora/` code, make sure the generated types are
25
- current — they are the contract the client and server share.
25
+ ## The feedback loop
26
26
 
27
27
  ```bash
28
- lunora codegen
28
+ lunora codegen # regenerate lunora/_generated/ from lunora/schema.ts + function files
29
+ lunora verify # wrangler config + codegen dry-run + tsc --noEmit; writes nothing
29
30
  ```
30
31
 
31
- This regenerates `lunora/_generated/` (`api.ts`, `server.ts`, `dataModel.ts`,
32
- `shard.ts`, `openapi.ts`, …) from `lunora/schema.ts` and your function files. The
33
- output typechecks your schema and functions, so it doubles as the agent's main
34
- feedback loop after each edit. Commit `lunora/_generated/` — it is part of the
35
- source tree, not a build artifact to gitignore.
36
-
37
- If a project-level `AGENTS.md` / `CLAUDE.md` exists, read it first — it overrides
38
- these defaults.
32
+ `lunora codegen` writes `lunora/_generated/` (`api.ts`, `internal.ts`,
33
+ `server.ts`, `dataModel.ts`, `shard.ts`, `app.ts`, `openapi.ts`, …; it prints
34
+ the exact list) and reports schema advisories and platform diagnostics. It does
35
+ not run `tsc`, so use `lunora verify` as the check that the code you wrote is
36
+ done. Its `tsc --noEmit` step runs only when the project has a `tsconfig.json`
37
+ (otherwise it warns and skips) and is turned off by `--no-typecheck`. `lunora dev` re-runs codegen on save, and `lunora deploy` runs it too.
38
+ Scaffolded projects gitignore `lunora/_generated/`; never hand-edit it.
39
39
 
40
- ## Route to the Right Skill
41
-
42
- After codegen is green, use the most specific Lunora skill for the task:
40
+ ## Route to the right skill
43
41
 
44
42
  - New project, or adding Lunora to an existing app: `lunora-quickstart`
45
43
  - Writing or reviewing schema + functions (the core authoring rules):
46
44
  `lunora-functions`
47
45
  - Wiring live data into a client (hooks, optimistic updates): `lunora-realtime`
48
- - Authentication setup (email/password, OAuth, magic link, OTP):
49
- `lunora-setup-auth`
50
- - Wiring a prebuilt capability (mail, file storage, scheduled jobs, rate
51
- limiting, vectors, AI, containers, payments, MCP): install it with
52
- `lunora registry add <item>` (see `lunora registry list`). Capabilities with a
53
- dedicated skill: `lunora-setup-mail` (mail), `lunora-setup-storage` (R2 file
54
- storage), `lunora-setup-scheduler` (deferred `ctx.scheduler` + cron jobs). For
55
- the rest, read the item's README after installing.
56
- - Building a reusable capability — a registry item or an `@lunora/*` package:
46
+ - Authentication (email/password, OAuth, magic link, OTP): `lunora-setup-auth`
47
+ - Transactional email: `lunora-setup-mail`
48
+ - R2 file storage (signed upload/download): `lunora-setup-storage`
49
+ - Deferred work (`ctx.scheduler`) and cron jobs: `lunora-setup-scheduler`
50
+ - Querying an existing Postgres/MySQL database from an action (`ctx.sql`,
51
+ non-reactive): `lunora-setup-hyperdrive`
52
+ - Postgres/MySQL as a reactive `.global()` backend, or migrating a D1
53
+ `.global()` dataset onto it: `lunora-setup-hyperdrive-global`
54
+ - Building a reusable capability (registry item or `@lunora/*` package):
57
55
  `lunora-create-package`
58
- - Planning or running a schema/data migration: `lunora-migration-helper`
59
- - Deploying to Cloudflare (wrangler, bindings, secrets, the drift gate):
60
- `lunora-deploy`
61
- - Investigating performance, scan, or write-conflict issues:
62
- `lunora-performance-audit`
63
-
64
- If one of those clearly matches the user's goal, switch to it instead of staying
65
- in this skill.
66
-
67
- ## Core Mental Model
68
-
69
- - **Functions** live in `lunora/*.ts` and are one of `query` (reactive read),
70
- `mutation` (transactional write), or `action` (side effects / `fetch` / no
71
- direct db). `internalQuery` / `internalMutation` / `internalAction` are the
72
- non-public variants.
73
- - **Schema** lives in `lunora/schema.ts` via `defineSchema` + `defineTable`,
74
- with validators from `v.*` (re-exported by `@lunora/server`).
75
- - **Reads go through indexes.** Prefer `ctx.db.query("t").withIndex(...)` over
76
- `.filter(...)`; declare the index with `.index("by_x", ["x"])`.
77
- - **Clients** subscribe over WebSocket. `useQuery`/`useMutation` (React, Vue,
78
- Solid, Svelte) re-render the moment a mutation changes the queried rows.
79
-
80
- ## When Not to Use
81
-
82
- - The user has already named a more specific Lunora workflow.
83
- - Another Lunora skill obviously fits the request better.
56
+ - Schema/data migrations: `lunora-migration-helper`
57
+ - Deploying (wrangler, bindings, secrets, the drift gate): `lunora-deploy`
58
+ - Slow queries, scans, write conflicts: `lunora-performance-audit`
59
+
60
+ ### Reviewing existing `lunora/` code
61
+
62
+ There is no review skill because two commands do the mechanical part. Run them
63
+ before reading code by hand:
64
+
65
+ ```bash
66
+ lunora verify # does it build and typecheck
67
+ lunora advisor # static + runtime lint set, scored per procedure
68
+ ```
69
+
70
+ `lunora advisor` covers RLS coverage, ownership and identity checks, fail-open
71
+ guards, input validators, unindexed reads, non-deterministic calls in queries,
72
+ SQL interpolation and leaked secrets. It prints each finding's lint id and
73
+ category, so read its output rather than guessing rule names. `--entry
74
+ <file>#<export>` inspects one procedure; `--min-score` / `--baseline` gate CI.
75
+ Once it is clean, a by-hand pass against `lunora-functions` is worth the tokens.
76
+
77
+ ## Core mental model
78
+
79
+ - Functions live in `lunora/**/*.ts` and import their builders from the
80
+ generated server module: `query` (reactive read), `mutation` (transactional
81
+ write), `action` (side effects, `fetch`, no direct db). `internalQuery` /
82
+ `internalMutation` / `internalAction` are not callable from clients.
83
+ - Schema lives in `lunora/schema.ts` (`defineSchema` + `defineTable`, validators
84
+ from `v.*`), imported from `lunorash/server` or `@lunora/server`.
85
+ - Function references mirror the folder tree: `lunora/billing/invoices.ts`
86
+ exporting `create` is `api.billing.invoices.create`. Public references come
87
+ from `_generated/api`, internal ones from `_generated/internal` (kept separate
88
+ so client bundles never carry internal names). A reference is a plain
89
+ `{ __lunoraRef: "billing_invoices:create" }` object; there is no `anyApi`
90
+ proxy.
91
+ - Reads go through indexes: declare `.index("by_x", ["x"])` and query with
92
+ `ctx.db.query("t").withIndex("by_x", (q) => q.eq("x", value))`, not
93
+ `.filter(...)`.
94
+ - Clients subscribe over WebSocket; `useQuery` re-renders when a mutation
95
+ changes the queried rows. Subscriptions run under the socket's verified
96
+ identity, so `rls()` and `ctx.auth` apply to live updates too.
97
+
98
+ ## Capabilities without a dedicated skill
99
+
100
+ Most add-ons install as a registry item: `lunora add <feature>` (or
101
+ `lunora registry add <item>`) scaffolds the `lunora/` glue, wrangler bindings
102
+ and `.dev.vars` entries, then prints post-install steps. Browse with
103
+ `lunora registry list`, preview with `lunora registry view <item>`. Read the
104
+ installed item's README and the package's `docs/` for the API.
105
+
106
+ | Goal | Install / package |
107
+ | --------------------------------------------- | ---------------------------------------------------------- |
108
+ | Background jobs on Cloudflare Queues | `lunora add queue` → `@lunora/queue` (`ctx.queues`) |
109
+ | Durable multi-step workflows | `lunora add workflow` → `@lunora/workflow` (`ctx.runStep`) |
110
+ | Durable AI agents (tool loops, HITL, memory) | `@lunora/agent` (`defineAgent`) |
111
+ | Workers AI / RAG | `lunora add ai` → `@lunora/ai` (`ctx.ai`, `defineRag`) |
112
+ | Feature flags (OpenFeature) | `lunora add flags` → `@lunora/flags` (`ctx.flags`) |
113
+ | Payments (Stripe / Polar) | `lunora add payment` → `@lunora/payment` |
114
+ | Agent payments (x402) | `@lunora/x402` |
115
+ | Push / in-app / webhook notifications | `@lunora/notify` (`ctx.notify`, `ctx.push`) |
116
+ | Rate limiting | `lunora add ratelimit` → `@lunora/ratelimit` |
117
+ | Headless browser (action-only) | `lunora add browser` → `@lunora/browser` (`ctx.browser`) |
118
+ | Cloudflare Containers | `@lunora/container` (`defineContainer`, `ctx.containers`) |
119
+ | Presence / who's-here | `lunora add presence` |
120
+ | Cloudflare Access (Zero Trust) identity | `lunora add cloudflare-access` |
121
+ | Backup / restore | `lunora add backup` |
122
+ | Testing (in-memory harness, agent doubles) | `@lunora/testing` (`lunoraTest`) |
123
+ | Deterministic seed data | `@lunora/seed` + `lunora seed` |
124
+ | Local-first replica / offline mirror | `@lunora/replica` |
125
+ | Exposing the deployment to AI agents over MCP | `@lunora/mcp` (below) |
126
+
127
+ Inside the Lunora monorepo, `vis generate lunora-<kind>` scaffolds code:
128
+ `query`, `mutation`, `action`, `http-route`, `table`, `cron`, `container`,
129
+ `workflow`, `queue`, `step`, `agent`, `package`, plus the no-name singletons
130
+ `flags`, `auth-do` and `collections` (`vis generate --list` for the set). Pass
131
+ names as `--name=value`: vis parses `--name foo` as `--name=true` plus a stray
132
+ positional.
133
+
134
+ ## Exposing a deployment over MCP
135
+
136
+ Two entry points:
137
+
138
+ - `lunora mcp install` wires an editor (Claude Code, Cursor, …) to the hosted
139
+ docs server plus this project's dev server; `lunora mcp serve` is the stdio
140
+ server those entries spawn (`--allow-writes`, `--token` opt into more).
141
+ - The `lunora-mcp` binary from `@lunora/mcp` fronts a deployed Worker. It needs
142
+ `LUNORA_URL` and `LUNORA_ADMIN_TOKEN`. Every tool reads admin-gated routes, so
143
+ the token cannot be scoped down; safety comes from the gates below.
144
+
145
+ Always advertised: `lunora_list_functions`, `lunora_list_tables` (`.global()`
146
+ tables with row counts), `lunora_get_function_schema`, `lunora_run_query`
147
+ (read-only), and `lunora_explain_error`, which explains an error `code` or
148
+ message from the catalog compiled into `@lunora/errors` and needs no
149
+ deployment. Use it before guessing what a Lunora error means.
150
+
151
+ Everything else sits behind an env gate that both hides the tool and refuses it
152
+ at dispatch. All default to off; enable one only when the answer to "may a model
153
+ see this?" is yes.
154
+
155
+ - `LUNORA_MCP_ALLOW_WRITES` → `lunora_run_mutation`, `lunora_run_action`.
156
+ - `LUNORA_MCP_ALLOW_OBSERVABILITY` → the five `lunora_get_*` tools (logs,
157
+ issues, advisories, query insights, migration status). Read-only, but they
158
+ return production log lines and error messages, which then reach the model
159
+ provider.
160
+ - `LUNORA_MCP_ALLOW_DATA_READS` → `lunora_find_related`. It returns raw rows
161
+ read through the admin writer, with RLS and column masks bypassed. It is kept
162
+ separate from observability so enabling logs never also hands over rows.
163
+ - `LUNORA_MCP_ALLOW_AGENTS` (with `LUNORA_MCP_AGENTS="name:description;…"`) →
164
+ the `agent_<name>` tools and `lunora_agent_status`.
165
+
166
+ Writes are a two-step handshake. The first `lunora_run_mutation` /
167
+ `lunora_run_action` call does not execute; it returns `status:
168
+ "action_required"` with `proposedAction`, an `actionDigest`, and an `expiresAt`
169
+ ten minutes out. The client shows that to a human, then repeats the call with
170
+ identical `functionPath`, `args` and `shardKey` plus `confirmed: true` and the
171
+ digest. Any edit needs a fresh proposal, and an expired digest is refused. The
172
+ digest proves the write that runs is the one proposed; it does not prove a human
173
+ saw it, so enabling writes means trusting the client to ask.
@@ -1,47 +1,36 @@
1
1
  ---
2
2
  name: lunora-create-package
3
- description: Builds a reusable Lunora capability — either a registry item installed with
4
- `lunora registry add`, or a publishable `@lunora/*` workspace package. Use for
5
- packaging schema + functions + bindings others can drop into their app.
3
+ description: Builds a reusable Lunora capability, either as a registry item that
4
+ `lunora add` / `lunora registry add` copies into an app's `lunora/`, or as a
5
+ publishable `@lunora/*` workspace package in the Lunora monorepo. Use when the
6
+ user wants to package schema + functions + wrangler bindings + env vars for
7
+ other apps, add or edit an item under `registry/<name>/` (`registry.json`),
8
+ run `vis generate lunora-package`, or wire a new `ctx.*` capability into
9
+ codegen.
6
10
  ---
7
11
 
8
12
  # Lunora Create Package
9
13
 
10
- Package a reusable Lunora capability. There are two distribution shapes; pick
11
- based on whether the capability is **copied into the user's `lunora/`** or
12
- **imported as a dependency**.
14
+ Pick the shape by whether the code is copied into the user's `lunora/` or
15
+ imported as a dependency:
13
16
 
14
- | Shape | Distribution | Use for |
15
- | ----------------- | -------------------------------- | -------------------------------------------------------- |
16
- | **Registry item** | `lunora registry add <name>` | App-owned code (schema/functions) the user edits + wires |
17
- | **Workspace pkg** | `import … from "@lunora/<name>"` | Reusable library code imported as a dependency |
17
+ | Shape | Distribution | Use for |
18
+ | ------------- | -------------------------------- | ------------------------------------------------ |
19
+ | Registry item | `lunora registry add <name>` | App-owned code (schema/functions) the user edits |
20
+ | Workspace pkg | `import … from "@lunora/<name>"` | Library code consumed as a versioned dependency |
18
21
 
19
- Many capabilities use **both**: a thin `@lunora/<name>` package holding the
20
- reusable runtime, plus a registry item that scaffolds the glue (`lunora/<name>/`
21
- files, bindings, env vars) into the user's project. `auth`, `mail`, `ratelimit`,
22
- and `storage` all follow this pattern.
22
+ Many capabilities use both: a `@lunora/<name>` package holds the runtime and a
23
+ registry item scaffolds the glue (files under `lunora/<name>/`, bindings, env
24
+ vars). `auth`, `mail`, `ratelimit` and `storage` follow this pattern.
23
25
 
24
- ## When to Use
26
+ Skip this skill for a one-off feature in a single app (write it in `lunora/`),
27
+ or when the capability already exists (`lunora registry list`).
25
28
 
26
- - Extracting schema + functions you have written into something reusable.
27
- - Authoring a new capability (presence, search, payments, …) for other apps.
28
- - Adding a new item to this repo's `registry/`.
29
+ ## Path A: registry item
29
30
 
30
- ## When Not to Use
31
-
32
- - A one-off feature for a single app — just write it in `lunora/`.
33
- - The capability already exists as a registry item or `@lunora/*` package — use
34
- it (`lunora registry list` to browse).
35
-
36
- ## Path A: Registry Item
37
-
38
- A registry item is a directory under `registry/<name>/` with three files:
39
-
40
- - `registry.json` — the manifest (deps, bindings, env vars, files, requires).
41
- - `index.ts` (and any siblings) — the code copied into the user's project.
42
- - `README.md` — install + configuration docs.
43
-
44
- ### Manifest shape
31
+ An item is a directory `registry/<name>/` holding `registry.json`, the source
32
+ files it copies, and a `README.md`. Validate against
33
+ `registry/schema/registry-item.schema.json`.
45
34
 
46
35
  ```jsonc
47
36
  // registry/<name>/registry.json
@@ -50,80 +39,104 @@ A registry item is a directory under `registry/<name>/` with three files:
50
39
  "name": "<name>",
51
40
  "title": "Human Title",
52
41
  "description": "One-paragraph summary shown in `lunora registry list`.",
53
- "docs": "Post-install steps surfaced to the user after `lunora registry add`.",
54
- "requires": [], // other item names this one depends on
42
+ "docs": "Post-install steps printed after `lunora registry add`.",
43
+ "requires": [], // other items, installed first (e.g. auth-clerk requires auth)
55
44
  "deps": { "@lunora/server": "workspace:*" },
45
+ "devDependencies": {},
56
46
  "bindings": [
57
- // reconciled into wrangler.jsonc
47
+ // structural edits applied to wrangler.jsonc
58
48
  { "path": ["d1_databases"], "value": [{ "binding": "DB", "database_name": "REPLACE_ME-db", "database_id": "<replace-with-d1-create-id>" }] },
59
49
  ],
60
50
  "envVars": [{ "name": "MY_SECRET", "description": "What it is and how to generate it.", "secret": true }],
61
- "files": [{ "from": "index.ts", "to": "lunora/<name>/index.ts", "merge": "create-or-skip" }],
51
+ "files": [
52
+ { "from": "schema.ts", "to": "lunora/<name>/schema.ts", "merge": "schema-extension" },
53
+ { "from": "<name>.ts", "to": "lunora/<name>/index.ts", "merge": "create-or-skip" },
54
+ ],
62
55
  }
63
56
  ```
64
57
 
65
- - `files[].merge` is typically `create-or-skip` (never clobber edited user code);
66
- `bindings` are reconciled into `wrangler.jsonc`; `envVars` are scaffolded into
67
- `.dev.vars` (secret-looking ones get generated values).
68
- - `requires` lets a provider item (e.g. `auth-clerk`) build on a base item
69
- (`auth`). The resolver installs the chain.
70
-
71
- ### Register and validate
72
-
73
- Add an entry to `registry/index.json`, then rebuild and check the index:
58
+ - `files[].merge`: `create-or-skip` writes whole files and never clobbers a file
59
+ the user edited; `schema-extension` AST-merges into `lunora/schema.ts`.
60
+ - `envVars` land in `.dev.vars`. Non-secret vars get their `value`; secrets get
61
+ an empty placeholder plus a `wrangler secret put <NAME>` reminder.
62
+ - `entrypointReexports` (`[{ "module": "_generated/workflows" }]`) injects
63
+ `export * from './lunora/<module>'` into the worker entry of framework
64
+ (class B/C) projects, for items whose generated classes the worker must
65
+ export. No shipped item uses it yet.
66
+ - Function files import builders from `#lunora/_generated/server.js`, the
67
+ module codegen emits in a consumer project. `registry/tsconfig.json` stubs
68
+ that module so the item typechecks here.
69
+ - `deps` ranges are copied verbatim into the user's `package.json`. Use
70
+ `workspace:*` for `@lunora/*` (resolved at publish); any other range must
71
+ admit the version the workspace resolves, or `pnpm install` fails
72
+ (`scripts/check-registry-catalog-ranges.js`).
73
+
74
+ Verify:
74
75
 
75
76
  ```bash
76
- lunora registry build # regenerate registry/index.json
77
- lunora registry build --check # verify the index is up to date (CI)
78
- lunora registry view <name> # preview what `add` would do
79
- lunora registry add <name> # install into the current project
77
+ lunora registry build --from ./registry # regenerate registry/index.json from the item dirs
78
+ lunora registry build --from ./registry --check # CI: index is current
79
+ pnpm run lint:types:registry # tsc over every item (builds packages first)
80
+ pnpm run lint:registry:items # manifest + generated-deps tests
81
+ lunora registry view <name> --from <repo>/registry # preview
82
+ lunora registry add <name> --from <repo>/registry --dry-run # in a scratch app
80
83
  ```
81
84
 
82
- ## Path B: Workspace Package
85
+ `registry/index.json` is generated; do not hand-edit it.
83
86
 
84
- Scaffold a fresh `@lunora/<name>` package with the generator (always use the
85
- `--name=value` form):
87
+ ## Path B: workspace package (Lunora monorepo)
86
88
 
87
89
  ```bash
88
- vis generate lunora-package --name=search --description='Typed full-text search over Lunora tables'
90
+ vis generate lunora-package --name=search --description='Typed full-text search over Lunora tables' --category=add-on
89
91
  ```
90
92
 
91
- This creates `packages/search/` following the repo's package shape: `src/index.ts`,
92
- `__tests__/`, `vitest.config.ts`, `tsconfig.json` (extends `../../tsconfig.base.json`),
93
- `project.json` (vis tags `type:package` + `category:<slug>`), `package.json` (ESM,
94
- `"sideEffects": false`, conditional exports), and `.releaserc.json`.
93
+ Pass every option as `--name=value`; vis reads `--name search` as
94
+ `--name=true` plus a stray positional.
95
+
96
+ This writes `packages/search/` with `package.json` (ESM-only,
97
+ `"sideEffects": false`, catalog versions), `src/index.ts`, `tsconfig.json`,
98
+ `vitest.config.ts`, `packem.config.ts`, `eslint.config.js`,
99
+ `prettier.config.js`, `project.json` (tags `type:package` +
100
+ `category:<category>`), `.releaserc.json` and `README.md`. It does not create
101
+ `__tests__/` or `LICENSE.md`. Then:
95
102
 
96
- ### Repo conventions to honor
103
+ 1. `cp packages/config/LICENSE.md packages/search/LICENSE.md` (packem and
104
+ `files` expect it).
105
+ 2. Add a row to `.agents/docs/packages.md`, and list the directory in one tier
106
+ of `scripts/api-snapshot.js` and the matching tier in `ROADMAP.md`. The
107
+ `pnpm install` postinstall checks (`check-agents-md-packages`,
108
+ `check-roadmap-tiers`) fail until both are done.
109
+ 3. `pnpm install`, then add tests under `__tests__/`.
97
110
 
98
- - **No `.js` extensions** in relative imports (`moduleResolution: "bundler"`).
99
- The lone exception is `@lunora/codegen`'s emitted output.
100
- - **No mixed default + named exports** in one file — named-only when there is
101
- more than one export.
102
- - **Use the dependency catalogs** in `pnpm-workspace.yaml` (`catalog:test`,
103
- `catalog:lint`, …) — never hard-code a version that lives in a catalog.
104
- - Tag `project.json` with `type:package` and a `category:<slug>`.
111
+ Repo conventions: relative imports without `.js`, named exports only (a
112
+ `default` only as a file's sole export), dependency versions via `catalog:*`
113
+ from `pnpm-workspace.yaml`.
105
114
 
106
- Build and test the new package in isolation:
115
+ Verify:
107
116
 
108
117
  ```bash
118
+ pnpm --filter "@lunora/search..." run build
109
119
  pnpm --filter "@lunora/search" run lint:types
110
120
  pnpm --filter "@lunora/search" run test
121
+ pnpm run lint:package-json
122
+ pnpm run api:update # writes api-snapshots/search.api.md from the fresh build; commit it
111
123
  ```
112
124
 
113
- ## Codegen-Wired Capabilities
114
-
115
- If your capability surfaces functions on a context (e.g. `ctx.ai`, `ctx.containers`)
116
- or new generated tables, it must be discoverable by `@lunora/codegen` — codegen
117
- parses `lunora/schema.ts` and the function files. Document any `lunora/*.ts`
118
- declaration the user must add so codegen wires the typed surface.
119
-
120
- ## Checklist
121
-
122
- - [ ] Chose the right shape (registry item, workspace package, or both).
123
- - [ ] Registry item: `registry.json` + `index.ts` + `README.md` authored;
124
- `bindings`/`envVars`/`requires`/`files` correct.
125
- - [ ] `lunora registry build` run; `lunora registry build --check` passes.
126
- - [ ] Workspace package: scaffolded via `vis generate lunora-package`; no `.js`
127
- extensions, no mixed default+named exports, catalog versions used.
128
- - [ ] `lint:types` and `test` pass for the new package.
129
- - [ ] README documents install, bindings, env vars, and any `lunora/` glue.
125
+ ## Wiring a `ctx.*` capability into codegen
126
+
127
+ Codegen decides which `ctx.*` fields exist by detecting usage, so a new
128
+ binding-backed helper is a literal row in `CAPABILITY_ROWS`
129
+ (`packages/codegen/src/capabilities.ts`; `CAPABILITIES` is a read-only view of
130
+ it): its package, `ctx` property, tier
131
+ (`"every"` or `"action"`-only), ctx type fragment, ShardDO binding, and
132
+ `defineApp` method. Rate the feature for every target in the
133
+ `PlatformCapabilities` matrices in `@lunora/platform`
134
+ (`packages/platform/src/capabilities/`) as `native`, `emulated` or
135
+ `unsupported` in the same change. A feature a target leaves unrated is dropped
136
+ from that target's generated surface with a diagnostic. Declaration-gated
137
+ surfaces (flags, notify, containers, workflows, queues, agents) also have their
138
+ own emitters; some of them (flags, notify, containers, workflows) keep a row too,
139
+ for usage probing, so a row and a dedicated emitter can coexist.
140
+
141
+ Document in the README any `lunora/*.ts` declaration the user must add for
142
+ codegen to emit the typed surface.