@rebasepro/cli 0.23.0 → 0.24.1-canary.g56af4a4

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 (158) hide show
  1. package/README.md +19 -3
  2. package/bin/rebase.js +4 -1
  3. package/dist/agent-setup-B31F00DC.js +324 -0
  4. package/dist/agent-setup-B31F00DC.js.map +1 -0
  5. package/dist/api-keys-BPBi5nOF.js +524 -0
  6. package/dist/api-keys-BPBi5nOF.js.map +1 -0
  7. package/dist/apps-CPXNElX4.js +256 -0
  8. package/dist/apps-CPXNElX4.js.map +1 -0
  9. package/dist/args-BnmsEXvu.js +109 -0
  10. package/dist/args-BnmsEXvu.js.map +1 -0
  11. package/dist/atlas-dev-database-DTMuEScS.js +62 -0
  12. package/dist/atlas-dev-database-DTMuEScS.js.map +1 -0
  13. package/dist/auth-DvY94ZuL.js +395 -0
  14. package/dist/auth-DvY94ZuL.js.map +1 -0
  15. package/dist/branch-pointer-DIhKbQLp.js +2 -0
  16. package/dist/build-CFwUx-Ff.js +336 -0
  17. package/dist/build-CFwUx-Ff.js.map +1 -0
  18. package/dist/bundle-BQhP_xiA.js +1617 -0
  19. package/dist/bundle-BQhP_xiA.js.map +1 -0
  20. package/dist/bundle.d.ts +6 -2
  21. package/dist/cli.d.ts +23 -2
  22. package/dist/cloud-CkTr-yt0.js +9640 -0
  23. package/dist/cloud-CkTr-yt0.js.map +1 -0
  24. package/dist/collection-drift-BKj_BoMq.js +106 -0
  25. package/dist/collection-drift-BKj_BoMq.js.map +1 -0
  26. package/dist/commands/__test_support__/parser-specs.d.ts +13 -0
  27. package/dist/commands/agent-setup.d.ts +116 -0
  28. package/dist/commands/api-keys.d.ts +86 -23
  29. package/dist/commands/apps.d.ts +17 -0
  30. package/dist/commands/auth.d.ts +7 -0
  31. package/dist/commands/build.d.ts +5 -1
  32. package/dist/commands/cloud/auth.d.ts +4 -3
  33. package/dist/commands/cloud/bundle-deploy.d.ts +45 -0
  34. package/dist/commands/cloud/context.d.ts +44 -5
  35. package/dist/commands/cloud/cron.d.ts +53 -0
  36. package/dist/commands/cloud/debug.d.ts +134 -0
  37. package/dist/commands/cloud/index.d.ts +89 -12
  38. package/dist/commands/cloud/token-capabilities.d.ts +76 -0
  39. package/dist/commands/cloud/tokens.d.ts +23 -0
  40. package/dist/commands/db.d.ts +52 -25
  41. package/dist/commands/dev.d.ts +181 -7
  42. package/dist/commands/doctor.d.ts +5 -0
  43. package/dist/commands/generate_sdk.d.ts +29 -2
  44. package/dist/commands/init.d.ts +57 -14
  45. package/dist/commands/schema.d.ts +6 -0
  46. package/dist/commands/skills.d.ts +126 -7
  47. package/dist/commands/start.d.ts +29 -0
  48. package/dist/commands/storage.d.ts +46 -0
  49. package/dist/consent-BWHaYx5p.js +76 -0
  50. package/dist/consent-BWHaYx5p.js.map +1 -0
  51. package/dist/context-BqhRydBg.js +1234 -0
  52. package/dist/context-BqhRydBg.js.map +1 -0
  53. package/dist/daemon-DBn-shxX.js +2 -0
  54. package/dist/{daemon-entry-LTFKtpHy.js → daemon-entry-Da-D3rmH.js} +3 -4
  55. package/dist/daemon-entry-Da-D3rmH.js.map +1 -0
  56. package/dist/db-CMpBK3sv.js +1252 -0
  57. package/dist/db-CMpBK3sv.js.map +1 -0
  58. package/dist/derive-RPIsAVO4.js +474 -0
  59. package/dist/derive-RPIsAVO4.js.map +1 -0
  60. package/dist/dev-C9P5Yp9k.js +1593 -0
  61. package/dist/dev-C9P5Yp9k.js.map +1 -0
  62. package/dist/dev-db/atlas-dev-database.d.ts +32 -0
  63. package/dist/dev-db/daemon-entry.d.ts +13 -0
  64. package/dist/dev-db/daemon.d.ts +10 -0
  65. package/dist/dev-db/prepare.d.ts +10 -0
  66. package/dist/dev-preflight-N1evJL3S.js +2 -0
  67. package/dist/doctor-DYs-NqFI.js +771 -0
  68. package/dist/doctor-DYs-NqFI.js.map +1 -0
  69. package/dist/eject-BT6t37D0.js +335 -0
  70. package/dist/eject-BT6t37D0.js.map +1 -0
  71. package/dist/fold-static-C1EtHlfV.js +201 -0
  72. package/dist/fold-static-C1EtHlfV.js.map +1 -0
  73. package/dist/fold-static.d.ts +26 -3
  74. package/dist/function-portability-BIvlvR9q.js +265 -0
  75. package/dist/function-portability-BIvlvR9q.js.map +1 -0
  76. package/dist/generate_sdk-UV635zSe.js +477 -0
  77. package/dist/generate_sdk-UV635zSe.js.map +1 -0
  78. package/dist/index.es.js +189 -22095
  79. package/dist/index.es.js.map +1 -1
  80. package/dist/init-fXeBcxuN.js +1042 -0
  81. package/dist/init-fXeBcxuN.js.map +1 -0
  82. package/dist/manifest-DzlC60WX.js +871 -0
  83. package/dist/manifest-DzlC60WX.js.map +1 -0
  84. package/dist/manifest.d.ts +41 -1
  85. package/dist/normalize-imports-CmVdE9iZ.js +100 -0
  86. package/dist/normalize-imports-CmVdE9iZ.js.map +1 -0
  87. package/dist/package-manager-DSEOwTqM.js +193 -0
  88. package/dist/package-manager-DSEOwTqM.js.map +1 -0
  89. package/dist/path-flags-DUBuI2i1.js +77 -0
  90. package/dist/path-flags-DUBuI2i1.js.map +1 -0
  91. package/dist/precompress.d.ts +17 -0
  92. package/dist/prepare-Btn9Ewbn.js +1052 -0
  93. package/dist/prepare-Btn9Ewbn.js.map +1 -0
  94. package/dist/{project-3WCbrrfW.js → project-Wp2zoyeN.js} +34 -184
  95. package/dist/project-Wp2zoyeN.js.map +1 -0
  96. package/dist/resolve-CJLkfFV0.js +2 -0
  97. package/dist/resources-DT1COn_6.js +161 -0
  98. package/dist/resources-DT1COn_6.js.map +1 -0
  99. package/dist/schema-BDBWvCHu.js +125 -0
  100. package/dist/schema-BDBWvCHu.js.map +1 -0
  101. package/dist/skills-DTFibT1m.js +642 -0
  102. package/dist/skills-DTFibT1m.js.map +1 -0
  103. package/dist/start-rU2e3Kp5.js +228 -0
  104. package/dist/start-rU2e3Kp5.js.map +1 -0
  105. package/dist/{state-C59Elrnt.js → state-Do7ZJYkF.js} +49 -4
  106. package/dist/state-Do7ZJYkF.js.map +1 -0
  107. package/dist/status-BR9oyi-y.js +351 -0
  108. package/dist/status-BR9oyi-y.js.map +1 -0
  109. package/dist/storage-DyvrSTH3.js +303 -0
  110. package/dist/storage-DyvrSTH3.js.map +1 -0
  111. package/dist/telemetry-CAWNCugs.js +338 -0
  112. package/dist/telemetry-CAWNCugs.js.map +1 -0
  113. package/dist/telemetry-DbLqGIBW.js +129 -0
  114. package/dist/telemetry-DbLqGIBW.js.map +1 -0
  115. package/dist/unknown-command-DNwDcX3w.js +98 -0
  116. package/dist/unknown-command-DNwDcX3w.js.map +1 -0
  117. package/dist/upgrade-D-5-Od96.js +1265 -0
  118. package/dist/upgrade-D-5-Od96.js.map +1 -0
  119. package/dist/upgrade.d.ts +14 -2
  120. package/dist/utils/path-flags.d.ts +18 -0
  121. package/dist/utils/project.d.ts +16 -0
  122. package/dist/version-Buyyo1ut.js +58 -0
  123. package/dist/version-Buyyo1ut.js.map +1 -0
  124. package/package.json +7 -7
  125. package/templates/eject/backend/src/env.ts +1 -1
  126. package/templates/eject/backend/src/index.ts +23 -2
  127. package/templates/overlays/baas/ai-instructions.md +1 -1
  128. package/templates/overlays/baas/config/storage.ts +5 -3
  129. package/templates/template/.cursorrules +1 -1
  130. package/templates/template/.env.example +10 -6
  131. package/templates/template/.github/copilot-instructions.md +1 -1
  132. package/templates/template/.mcp.json +2 -2
  133. package/templates/template/.windsurfrules +1 -1
  134. package/templates/template/AGENTS.md +1 -1
  135. package/templates/template/CLAUDE.md +1 -1
  136. package/templates/template/README.md +11 -12
  137. package/templates/template/ai-instructions.md +5 -4
  138. package/templates/template/backend/functions/hello.ts +8 -0
  139. package/templates/template/backend/package.json +1 -1
  140. package/templates/template/config/storage.ts +5 -3
  141. package/templates/template/docker-compose.yml +6 -6
  142. package/templates/template/frontend/vite.config.ts +11 -3
  143. package/templates/template/gitignore +6 -1
  144. package/templates/template/package.json +4 -3
  145. package/templates/template/scripts/example.ts +6 -4
  146. package/dist/branch-pointer-dBiClJ0p.js +0 -111
  147. package/dist/branch-pointer-dBiClJ0p.js.map +0 -1
  148. package/dist/constraints-DKGbNfUW.js +0 -48
  149. package/dist/constraints-DKGbNfUW.js.map +0 -1
  150. package/dist/daemon-DR9Tk0La.js +0 -355
  151. package/dist/daemon-DR9Tk0La.js.map +0 -1
  152. package/dist/daemon-entry-LTFKtpHy.js.map +0 -1
  153. package/dist/dev-preflight-CNLl4rdo.js +0 -367
  154. package/dist/dev-preflight-CNLl4rdo.js.map +0 -1
  155. package/dist/project-3WCbrrfW.js.map +0 -1
  156. package/dist/resolve-BAeRUBhg.js +0 -74
  157. package/dist/resolve-BAeRUBhg.js.map +0 -1
  158. package/dist/state-C59Elrnt.js.map +0 -1
@@ -1,3 +1,4 @@
1
+ import { type AppAddress, type RebaseProjectManifest } from "@rebasepro/types";
1
2
  import { type PreparedDatabase } from "../dev-db/prepare.js";
2
3
  /**
3
4
  * The line the watcher prints when it is about to run the entry again.
@@ -29,6 +30,21 @@ import { type PreparedDatabase } from "../dev-db/prepare.js";
29
30
  * Exported so `dev-crash-marker.test.ts` can hold the running tsx to it.
30
31
  */
31
32
  export declare const WATCHER_RESTART_MARKER: RegExp;
33
+ /**
34
+ * Calls `onLine` with each line a child process writes to `stream`.
35
+ *
36
+ * A pipe hands over whatever has been written so far, so one line can arrive
37
+ * in two chunks. Split chunk by chunk, "Server running at http://localhost:3001"
38
+ * could read as two fragments that neither matched, and `rebase dev` then
39
+ * never announced the backend or started the admin panel. So the piece after
40
+ * the last newline is held for the next chunk, decoded as UTF-8 across chunk
41
+ * boundaries. A held piece is handed over at the end of the stream, or after
42
+ * `idleFlushMs` with nothing more written, so a prompt or a progress line
43
+ * still shows when it is written.
44
+ *
45
+ * Exported for its test.
46
+ */
47
+ export declare function forEachOutputLine(stream: NodeJS.ReadableStream | null | undefined, onLine: (line: string) => void, idleFlushMs?: number): void;
32
48
  /**
33
49
  * The corrected banner line, when the backend says it moved port.
34
50
  *
@@ -65,15 +81,50 @@ export declare function portMovedNotice(line: string): {
65
81
  *
66
82
  * @param projectRoot Absolute path the relative entries are resolved against.
67
83
  * @param paths The `REBASE_DEV_*` map from {@link devRuntimeEnv}.
68
- * @param includeConfig Whether `config/` is watched here. It is only when
69
- * auto-generation is off; with `--generate` a dedicated
70
- * watcher already regenerates the schema and SDK, and tsx
71
- * restarts on the files that produces.
72
84
  */
73
85
  export declare function devWatchIncludes(projectRoot: string, paths: {
74
86
  REBASE_DEV_FUNCTIONS?: string;
75
87
  REBASE_DEV_CRONS?: string;
76
- }, includeConfig: boolean): string[];
88
+ }): string[];
89
+ /**
90
+ * The file dev writes to restart the backend, or `null` when tsx would not see it.
91
+ *
92
+ * Outside the project, so nothing appears in the developer's tree, and keyed by
93
+ * the project so two `rebase dev`s never restart each other. tsx ignores every
94
+ * path with a dot-named segment (its built-in `**\/.*\/**`), so a trigger under
95
+ * `.rebase/` — or under a TMPDIR inside a dot directory — would never fire; in
96
+ * that case there is no trigger and {@link devWatchArgs} leaves the
97
+ * collections to tsx, as before.
98
+ */
99
+ export declare function devRestartTrigger(projectRoot: string): string | null;
100
+ /**
101
+ * The `tsx watch` argument list for the backend (unquoted).
102
+ *
103
+ * One save of a collection file must restart the backend once. The runtime
104
+ * `import()`s the collections, so tsx tracks them as dependencies and used to
105
+ * restart the moment a file was saved — before dev had regenerated
106
+ * `schema.generated.ts`. That boot warned "schema.generated.ts no longer
107
+ * describes the database … Run `rebase schema generate`", telling the reader to
108
+ * run what dev was running at that moment, and the regeneration then rewrote
109
+ * the file and restarted the backend a second time. So tsx is told to leave the
110
+ * collections directory alone (`--exclude` wins over its dependency tracking),
111
+ * and dev restarts the backend itself, once, after the regeneration — through
112
+ * `restartTrigger`, which tsx watches.
113
+ *
114
+ * Every included directory also gets tsx's own default ignores, made absolute.
115
+ * tsx resolves those defaults (`**\/node_modules/**`, `**\/.*`, …) against its
116
+ * cwd, which is `backend/`, so they never reached `config/`, a sibling: chokidar
117
+ * walked `config/node_modules` — following symlinks — before tsx spawned the
118
+ * backend at all, and kept every file in it watched. In the monorepo's example
119
+ * app that was 17 s before the first backend line and 1,400 open files, and any
120
+ * install (or another checkout's Vite build writing `.vite-temp` deep inside
121
+ * that tree) restarted the backend. A `.DS_Store` or an editor swap file in
122
+ * `config/` restarted it too.
123
+ */
124
+ export declare function devWatchArgs(projectRoot: string, paths: {
125
+ REBASE_DEV_FUNCTIONS?: string;
126
+ REBASE_DEV_CRONS?: string;
127
+ }, entryTarget: string, restartTrigger: string | null): string[];
77
128
  /** Well-known filename the backend writes its actual port to. */
78
129
  export declare const DEV_PORT_FILENAME = ".rebase-dev-port";
79
130
  /**
@@ -138,6 +189,53 @@ export declare function resolveStartPort(projectRoot: string, explicitPort?: num
138
189
  * Exported for its test.
139
190
  */
140
191
  export declare function databaseEndpoint(url: string | null | undefined): string | null;
192
+ /**
193
+ * What the start banner needs to know about a project's static apps.
194
+ *
195
+ * `rebase dev` runs one frontend: Vite in `frontend/`, at the root of its own
196
+ * localhost port, whatever path or hostname the manifest declares for it. So an
197
+ * app's local address and its deployed one are different things, and for an app
198
+ * with a hostname of its own they share nothing at all — appending its address
199
+ * to the local URL would print `http://localhost:5173https://admin.example.com`.
200
+ */
201
+ export interface DevStaticShape {
202
+ declaresStaticApp: boolean;
203
+ /** The declared app whose `root` is the `frontend/` that `rebase dev` runs, if one is. */
204
+ served?: {
205
+ appName: string;
206
+ address: AppAddress;
207
+ };
208
+ /** Where the CMS is, when an app declares one. */
209
+ cms?: {
210
+ appName: string;
211
+ /** Always a path. */
212
+ path: string;
213
+ /** The serving app's hostname, when its `path` names one. */
214
+ host?: string;
215
+ /** Whether the app serving it is the one `rebase dev` runs, so it has a local address. */
216
+ servedLocally: boolean;
217
+ };
218
+ }
219
+ /**
220
+ * Read {@link DevStaticShape} out of a loaded manifest. Exported for its test.
221
+ *
222
+ * Which declared app is running is decided by its `root` being `frontend/`,
223
+ * because that directory is what `startFrontend` launches and nothing else is.
224
+ * When no declared app has that root, which app serves the CMS cannot be told,
225
+ * and it is read as the frontend that does run — what the banner has always
226
+ * assumed, and right for every project `rebase init` scaffolds.
227
+ */
228
+ export declare function devStaticShape(manifest: RebaseProjectManifest, projectRoot: string, frontendDir: string | null): DevStaticShape;
229
+ /**
230
+ * The banner's lines for a project with a frontend. Exported for its test.
231
+ *
232
+ * Every address is printed whole, once: the local one Vite answers on, and —
233
+ * for an app with a hostname — the https URL it answers on once deployed, on a
234
+ * line of its own beneath it. A CMS in an app `rebase dev` does not run gets its
235
+ * deployed address and a note saying so, rather than a localhost URL that the
236
+ * running frontend's SPA fallback would answer with the wrong app.
237
+ */
238
+ export declare function appBannerLines(frontendUrl: string, api: string, shape: DevStaticShape): Array<[string, string]>;
141
239
  /**
142
240
  * The `↳ Database =` line: which database, why it was chosen, and where it is.
143
241
  *
@@ -206,7 +304,6 @@ export declare const DEV_FLAGS: {
206
304
  readonly "--backend-only": BooleanConstructor;
207
305
  readonly "--frontend-only": BooleanConstructor;
208
306
  readonly "--port": NumberConstructor;
209
- readonly "--generate": BooleanConstructor;
210
307
  /**
211
308
  * Point this run at a database of your own, ahead of everything else.
212
309
  *
@@ -220,9 +317,23 @@ export declare const DEV_FLAGS: {
220
317
  readonly "-b": "--backend-only";
221
318
  readonly "-f": "--frontend-only";
222
319
  readonly "-P": "--port";
223
- readonly "-g": "--generate";
224
320
  readonly "--no-db": BooleanConstructor;
225
321
  };
322
+ /** What {@link ensureGeneratedSchema} did at startup. */
323
+ export type SchemaGeneration = "generated" | "skipped" | "failed";
324
+ /**
325
+ * Whether dev must still run the driver's `schema stale --fix` before the
326
+ * backend boots.
327
+ *
328
+ * Not after a regeneration that succeeded: that wrote `schema.generated.ts`
329
+ * from these collections with this driver, moments earlier, and `stale`
330
+ * compares the file against the same generator — it can only answer "nothing
331
+ * stale", and it cost a driver process (~0.6 s) on every start. The repair it
332
+ * exists for, a library upgrade that changed what the generator derives, is
333
+ * exactly what the regeneration already did. When generation was skipped or
334
+ * failed, the preflight is the remaining safety net and still runs.
335
+ */
336
+ export declare function needsStaleSchemaPreflight(generation: SchemaGeneration): boolean;
226
337
  /**
227
338
  * One variable's value out of `.env` text, or undefined when it has none.
228
339
  *
@@ -251,4 +362,67 @@ export declare function readEnvValue(envText: string, key: string): string | und
251
362
  * it is invisible in any assertion about the push's *outcome*.
252
363
  */
253
364
  export declare function schemaPushArgv(databaseUrl: string | undefined): string[];
365
+ /**
366
+ * Start-up's independent halves, overlapped rather than run one after another.
367
+ *
368
+ * `rebase dev` used to regenerate the schema and the SDK, then derive the
369
+ * resource graph (every collection evaluated again, in this process), then
370
+ * start the managed database and wait for it — about a second when it was not
371
+ * already running — and only then spawn the backend. None of the three reads
372
+ * what another writes: the generators read `config/` and write
373
+ * `backend/src/schema.generated.ts` and `generated/sdk/`; the derivation reads
374
+ * `config/resources.ts` and the collections; the database needs neither, and
375
+ * `schema generate` never connects to one. So `database` starts first and is
376
+ * collected last.
377
+ *
378
+ * `preflight` is the exception, and the reason this is not one `Promise.all`:
379
+ * on the `--docker` path it pushes the schema the generators have just written,
380
+ * so it still runs after them.
381
+ *
382
+ * A database that fails to start is reported where it always was — after the
383
+ * generators' and the preflight's output — rather than ahead of it, and it is
384
+ * never an unhandled rejection while they run.
385
+ *
386
+ * Exported for its test.
387
+ */
388
+ export declare function overlapDevStartup<T>(steps: {
389
+ generate: () => Promise<SchemaGeneration>;
390
+ preflight: () => Promise<void>;
391
+ /** Resolve and, for the managed database, start it. `null` when this run starts none. */
392
+ database: (() => Promise<T>) | null;
393
+ }): Promise<{
394
+ schemaGeneration: SchemaGeneration;
395
+ database: T | null;
396
+ }>;
397
+ /**
398
+ * Whether the admin panel can start beside the backend instead of after it.
399
+ *
400
+ * Vite has to be told the backend's URL when it starts (`VITE_API_URL`), and
401
+ * the backend's port is only certain once it has bound — so the admin panel
402
+ * used to wait for "Server running at", and the time to it was the backend's
403
+ * whole boot plus Vite's start. It can start beside the backend whenever the
404
+ * port the backend will bind is known in advance:
405
+ *
406
+ * - **named with `--port`**: the server binds it or refuses to start, never
407
+ * walks past it (`REBASE_DEV_PORT_EXPLICIT`), and `pinnedPortRefusal` has
408
+ * already checked that nothing answers there;
409
+ * - **free, and the port the backend tries first**: the server tries the port
410
+ * its last run landed on before the one it is given (`.rebase-dev-port`), so
411
+ * a remembered port must be this one — the "kept from the last run" rung —
412
+ * or absent, which it is after every clean exit, and the derived port is
413
+ * then the one tried. A port something already answers on would make the
414
+ * backend move, so that case keeps the old order.
415
+ *
416
+ * Nothing here can rule out another process taking the port in the second the
417
+ * backend boots, so `devCommand` still compares the announced port with the
418
+ * one Vite was given and restarts the admin panel when they differ.
419
+ *
420
+ * Exported for its test.
421
+ */
422
+ export declare function frontendCanStartWithBackend(options: {
423
+ projectRoot: string;
424
+ port: number;
425
+ pinned: boolean;
426
+ probe?: (host: string, port: number) => Promise<boolean>;
427
+ }): Promise<boolean>;
254
428
  export declare function devCommand(rawArgs: string[]): Promise<void>;
@@ -57,4 +57,9 @@ export declare const DOCTOR_FLAGS: {
57
57
  readonly "--sdk": StringConstructor;
58
58
  readonly "-k": "--sdk";
59
59
  };
60
+ /**
61
+ * The line handed to the driver, every path on it resolved from where the
62
+ * command was run — the driver runs in `backend/`. See `utils/path-flags.ts`.
63
+ */
64
+ export declare function doctorDriverArgs(rawArgs: string[], cwd: string): string[];
60
65
  export declare function doctorCommand(rawArgs: string[]): Promise<void>;
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * CLI command: generate-sdk
3
3
  *
4
- * Reads collection definitions from a specified directory (default: ./config/collections),
5
- * generates a typed TypeScript SDK, and writes it to the output directory (default: ./generated/sdk).
4
+ * Reads every collection file in a directory (default: ./config/collections) —
5
+ * the files the backend serves, not the barrel's list — generates a typed
6
+ * TypeScript SDK, and writes it to the output directory (default: ./generated/sdk).
6
7
  *
7
8
  * Uses jiti for dynamic TypeScript import of collection files.
8
9
  */
@@ -21,8 +22,34 @@ interface GenerateSDKArgs {
21
22
  from?: string;
22
23
  /** Bearer token for the contract endpoint. Falls back to REBASE_SERVICE_KEY. */
23
24
  token?: string;
25
+ /**
26
+ * Also register the generated `Database` for server-side code: write the
27
+ * types and the `Register` augmentation into `config/generated/`. See
28
+ * {@link writeRegistration}.
29
+ */
30
+ register?: boolean;
31
+ /**
32
+ * The directory holding `rebase.json`, where `--register` is remembered.
33
+ * Found from `cwd` when not given.
34
+ */
35
+ projectRoot?: string;
24
36
  help?: boolean;
25
37
  }
38
+ /** What `--register` writes, and what marks a project as having opted in. */
39
+ export declare const REGISTER_FILE = "register.ts";
40
+ /**
41
+ * Where `--register` writes: `generated/` beside the collections directory,
42
+ * which is `config/generated/` in a scaffolded project.
43
+ *
44
+ * Inside `config/` because that is the one directory both compiles of a
45
+ * collection file include: the backend's program (it includes
46
+ * `../config/**`) and the `config` package's own `tsc`. A registration
47
+ * there that imported `../generated/sdk/database.types` pulled a file from
48
+ * outside `config/` into that package's program, which TypeScript refuses
49
+ * (the file is not under its `rootDir`) — so the types are copied in beside
50
+ * the registration rather than imported from the SDK.
51
+ */
52
+ export declare function registrationDir(collectionsDir: string): string;
26
53
  /**
27
54
  * The base URL to show in the printed usage example.
28
55
  *
@@ -1,4 +1,5 @@
1
1
  import type { PackageManager, PMCommands } from "../utils/package-manager.js";
2
+ import { type AgentKey } from "./skills.js";
2
3
  /**
3
4
  * Every scaffolded file that carries a `{{PLACEHOLDER}}`.
4
5
  *
@@ -42,6 +43,10 @@ export interface InitOptions {
42
43
  setupKey?: string;
43
44
  /** Control-plane URL the setup key is redeemed against. */
44
45
  cloudUrl?: string;
46
+ /** AI coding agents to install skills and the MCP server for. */
47
+ agents: AgentKey[];
48
+ /** Whoever reads the closing steps can answer a prompt (a TTY, not --yes). */
49
+ interactive?: boolean;
45
50
  }
46
51
  export interface BuildQuestionsParams {
47
52
  nameArg?: string;
@@ -105,21 +110,59 @@ export declare function printInitHelp(): void;
105
110
  export declare function createRebaseApp(rawArgs: string[]): Promise<void>;
106
111
  /** The flags `rebase init` takes. */
107
112
  export declare const INIT_FLAGS: {
108
- readonly "--git": BooleanConstructor;
109
- readonly "--install": BooleanConstructor;
110
- readonly "--no-install": BooleanConstructor;
111
- readonly "--database-url": StringConstructor;
112
- readonly "--introspect": BooleanConstructor;
113
- readonly "--template": StringConstructor;
114
- readonly "--headless": BooleanConstructor;
115
- readonly "--project": StringConstructor;
116
- readonly "--setup-key": StringConstructor;
117
- readonly "--yes": BooleanConstructor;
118
- readonly "-g": "--git";
119
- readonly "-i": "--install";
120
- readonly "-t": "--template";
121
- readonly "-y": "--yes";
113
+ "--git": BooleanConstructor;
114
+ "--install": BooleanConstructor;
115
+ "--no-install": BooleanConstructor;
116
+ "--database-url": StringConstructor;
117
+ "--introspect": BooleanConstructor;
118
+ "--template": StringConstructor;
119
+ "--headless": BooleanConstructor;
120
+ "--project": StringConstructor;
121
+ "--setup-key": StringConstructor;
122
+ "--agent": [StringConstructor];
123
+ "--yes": BooleanConstructor;
124
+ "-a": string;
125
+ "-g": string;
126
+ "-i": string;
127
+ "-t": string;
128
+ "-y": string;
122
129
  };
130
+ /**
131
+ * The closing "AI Agent Skills" lines, each command one its reader can run.
132
+ *
133
+ * `rebase skills install` with no `--agent` prompts, and refuses without a
134
+ * TTY — so printing it bare at the end of `rebase init --yes`, the agent and
135
+ * CI path, told that reader to run a command that answers "Cannot prompt".
136
+ * Named agents are spelled out (a refresh must not depend on detection, which
137
+ * never finds Copilot); otherwise a TTY reader gets the prompt, anyone else
138
+ * the `--agent` form.
139
+ */
140
+ export declare function agentNextSteps(agents: readonly AgentKey[], interactive: boolean, pm: PMCommands): string[];
141
+ /**
142
+ * What a directory may already hold for `rebase init` to scaffold into it.
143
+ *
144
+ * `git clone` of an empty repository, or `git init`, leaves exactly `.git` —
145
+ * and `rebase init . --yes --git` is the help's own example. Counting every
146
+ * entry as "not empty" refused the one directory that example is most likely
147
+ * to be typed in. The entries here are a repository's metadata, the files
148
+ * operating systems drop into any folder, and a licence: none of them is
149
+ * something the scaffold writes (`init.test.ts` holds the template to that),
150
+ * so tolerating them can never overwrite anything. Everything else is a
151
+ * conflict and is named, never merged into.
152
+ */
153
+ export declare const SCAFFOLD_TOLERATED_ENTRIES: ReadonlySet<string>;
154
+ /** Entries in `dir` the scaffold would overwrite or mix with — `[]` when it may proceed. */
155
+ export declare function scaffoldDirectoryConflicts(dir: string): string[];
156
+ /** The refusal for a directory that already holds files, with the two ways forward. */
157
+ export declare function scaffoldConflictMessage(projectName: string, displayPath: string, conflicts: string[]): string[];
158
+ /**
159
+ * `git init`, or nothing when the directory is already a repository.
160
+ *
161
+ * A cloned repository keeps its branch, its remote and its history: the
162
+ * scaffold is committed on top of what is there. Only a repository this
163
+ * function created is pointed at `main`.
164
+ */
165
+ export declare function initGitRepository(targetDirectory: string): Promise<boolean>;
123
166
  /**
124
167
  * Whether `port` is free — on the wildcard address *and* on both loopback addresses.
125
168
  *
@@ -1,3 +1,9 @@
1
+ /**
2
+ * The line handed to the driver, its paths resolved from where the command was
3
+ * run (the driver runs in `backend/`). `--schema` is left alone: on
4
+ * `introspect` it names a Postgres schema, not a file.
5
+ */
6
+ export declare function schemaDriverArgs(rawArgs: string[], cwd: string): string[];
1
7
  export declare function schemaCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
2
8
  /** Every subcommand the family dispatches — the help table's keys. */
3
9
  export declare const SCHEMA_SUBCOMMANDS: string[];
@@ -18,14 +18,32 @@
18
18
  * A subdirectory layout has no such problem: the rule file already sits beside
19
19
  * its own assets, so `references/x.md` resolves as written and nothing is
20
20
  * loaded until it is opened.
21
+ *
22
+ * `homeMarkers` are the directories under `~` that say the assistant is
23
+ * installed on this machine. They answer a different question from
24
+ * `detectDir`: a fresh scaffold has no `.claude/` of its own, so `rebase init`
25
+ * asks the machine which assistants the developer has and pre-selects those.
26
+ *
27
+ * `mcp` is where the assistant reads a *project-level* MCP server list, and in
28
+ * which shape — see `agent-setup.ts`. `projectDir` is what `REBASE_PROJECT_DIR`
29
+ * is set to: `"."` where the server is spawned in the project, the editor's own
30
+ * workspace variable where it may not be. `null` means there is no project
31
+ * file to write: Windsurf reads only a user-level config, and one entry there
32
+ * cannot name every project on the machine.
21
33
  */
22
- declare const AGENTS: {
34
+ export declare const AGENTS: {
23
35
  readonly cursor: {
24
36
  readonly label: "Cursor";
25
37
  readonly detectDir: ".cursor";
38
+ readonly homeMarkers: readonly [".cursor"];
26
39
  readonly targetDir: ".cursor/rules";
27
40
  readonly flatLayout: true;
28
41
  readonly indexFile: "rebase.mdc";
42
+ readonly mcp: {
43
+ readonly file: ".cursor/mcp.json";
44
+ readonly format: "mcpServers";
45
+ readonly projectDir: "${workspaceFolder}";
46
+ };
29
47
  /** The body is not a rule file here — `indexFile` is. */
30
48
  readonly transformFile: (skillName: string, content: string) => {
31
49
  fileName: string;
@@ -35,8 +53,14 @@ declare const AGENTS: {
35
53
  readonly claude: {
36
54
  readonly label: "Claude Code";
37
55
  readonly detectDir: ".claude";
56
+ readonly homeMarkers: readonly [".claude"];
38
57
  readonly targetDir: ".claude/skills";
39
58
  readonly flatLayout: false;
59
+ readonly mcp: {
60
+ readonly file: ".mcp.json";
61
+ readonly format: "mcpServers";
62
+ readonly projectDir: ".";
63
+ };
40
64
  /** Claude Code uses the standard SKILL.md format in subdirectories. */
41
65
  readonly transformFile: (skillName: string, content: string) => {
42
66
  fileName: string;
@@ -46,9 +70,11 @@ declare const AGENTS: {
46
70
  readonly windsurf: {
47
71
  readonly label: "Windsurf";
48
72
  readonly detectDir: ".windsurf";
73
+ readonly homeMarkers: readonly [".codeium/windsurf", ".windsurf"];
49
74
  readonly targetDir: ".windsurf/rules";
50
75
  readonly flatLayout: true;
51
76
  readonly indexFile: "rebase.md";
77
+ readonly mcp: null;
52
78
  /** The body is not a rule file here — `indexFile` is. */
53
79
  readonly transformFile: (skillName: string, content: string) => {
54
80
  fileName: string;
@@ -58,8 +84,14 @@ declare const AGENTS: {
58
84
  readonly gemini: {
59
85
  readonly label: "Gemini CLI / Antigravity";
60
86
  readonly detectDir: ".agents";
87
+ readonly homeMarkers: readonly [".gemini"];
61
88
  readonly targetDir: ".agents/skills";
62
89
  readonly flatLayout: false;
90
+ readonly mcp: {
91
+ readonly file: ".gemini/settings.json";
92
+ readonly format: "mcpServers";
93
+ readonly projectDir: ".";
94
+ };
63
95
  /** Gemini uses the standard SKILL.md format in subdirectories. */
64
96
  readonly transformFile: (skillName: string, content: string) => {
65
97
  fileName: string;
@@ -69,9 +101,15 @@ declare const AGENTS: {
69
101
  readonly codex: {
70
102
  readonly label: "Codex CLI";
71
103
  readonly detectDir: ".codex";
72
- readonly targetDir: ".codex/skills";
104
+ readonly homeMarkers: readonly [".codex"];
105
+ readonly targetDir: ".agents/skills";
73
106
  readonly flatLayout: false;
74
- /** Codex reads AGENTS.md; the skills sit beside its own config. */
107
+ readonly mcp: {
108
+ readonly file: ".codex/config.toml";
109
+ readonly format: "codexToml";
110
+ readonly projectDir: ".";
111
+ };
112
+ /** Codex uses the standard SKILL.md format in subdirectories. */
75
113
  readonly transformFile: (skillName: string, content: string) => {
76
114
  fileName: string;
77
115
  content: string;
@@ -80,9 +118,15 @@ declare const AGENTS: {
80
118
  readonly kiro: {
81
119
  readonly label: "Kiro";
82
120
  readonly detectDir: ".kiro";
121
+ readonly homeMarkers: readonly [".kiro"];
83
122
  readonly targetDir: ".kiro/steering";
84
123
  readonly flatLayout: true;
85
124
  readonly indexFile: "rebase.md";
125
+ readonly mcp: {
126
+ readonly file: ".kiro/settings/mcp.json";
127
+ readonly format: "mcpServers";
128
+ readonly projectDir: ".";
129
+ };
86
130
  /** The body is not a rule file here — `indexFile` is. */
87
131
  readonly transformFile: (skillName: string, content: string) => {
88
132
  fileName: string;
@@ -92,9 +136,15 @@ declare const AGENTS: {
92
136
  readonly copilot: {
93
137
  readonly label: "GitHub Copilot";
94
138
  readonly detectDir: null;
139
+ readonly homeMarkers: readonly [];
95
140
  readonly targetDir: ".github/instructions";
96
141
  readonly flatLayout: true;
97
142
  readonly indexFile: "rebase.instructions.md";
143
+ readonly mcp: {
144
+ readonly file: ".vscode/mcp.json";
145
+ readonly format: "vscode";
146
+ readonly projectDir: "${workspaceFolder}";
147
+ };
98
148
  /** The body is not a rule file here — `indexFile` is. */
99
149
  readonly transformFile: (skillName: string, content: string) => {
100
150
  fileName: string;
@@ -102,7 +152,11 @@ declare const AGENTS: {
102
152
  };
103
153
  };
104
154
  };
105
- type AgentKey = keyof typeof AGENTS;
155
+ export type AgentKey = keyof typeof AGENTS;
156
+ /** Narrows a string to an agent name, by the table's own keys. */
157
+ export declare function isAgentKey(value: string): value is AgentKey;
158
+ /** Every agent, in table order. */
159
+ export declare const AGENT_KEYS: AgentKey[];
106
160
  export interface LoadedSkill {
107
161
  name: string;
108
162
  /** Absolute path of the skill's source directory. */
@@ -113,6 +167,13 @@ export interface LoadedSkill {
113
167
  }
114
168
  /** Read all skill directories and return their names, content and assets. */
115
169
  export declare function loadSkills(skillsDir: string): LoadedSkill[];
170
+ /**
171
+ * The skills this CLI ships, from its own `@rebasepro/agent-skills`.
172
+ *
173
+ * Throws rather than exiting, so `rebase init` can report a missing bundle as a
174
+ * warning and still finish the scaffold.
175
+ */
176
+ export declare function loadBundledSkills(): LoadedSkill[];
116
177
  /**
117
178
  * The one always-on rule a flat-layout agent gets, in place of every skill.
118
179
  *
@@ -136,11 +197,57 @@ export declare function renderSkillIndex(skills: LoadedSkill[], agentKey: AgentK
136
197
  * guessing, because the wrong guess installs 21 files and reports success.
137
198
  */
138
199
  export declare function detectAgents(projectDir: string): AgentKey[];
200
+ /** What `detectInstalledAgents` found for one assistant. */
201
+ export interface InstalledAgent {
202
+ key: AgentKey;
203
+ label: string;
204
+ /** The home directory checked, as `~/…` — the one found, else the first. */
205
+ marker: string | null;
206
+ found: boolean;
207
+ }
208
+ /**
209
+ * Which assistants are installed on this machine, from their home directories.
210
+ *
211
+ * The question `rebase init` needs answered, and one `detectAgents` cannot: a
212
+ * project that does not exist yet has no `.claude/` in it. What the machine has
213
+ * is only a default — the developer confirms it — so a false positive costs an
214
+ * unticked box, not 21 files nobody asked for.
215
+ */
216
+ export declare function detectInstalledAgents(home?: string): InstalledAgent[];
139
217
  /** Install skills for a specific agent into the project directory. */
140
- export declare function installForAgent(agentKey: AgentKey, skills: LoadedSkill[], projectDir: string): {
218
+ /**
219
+ * The file in each target directory that records what the installer wrote:
220
+ * relative path → sha256 of the bytes written. A dotfile, so no agent loads it
221
+ * as a rule.
222
+ */
223
+ export declare const SKILLS_MANIFEST = ".rebase-skills.json";
224
+ /** What one agent's install did. */
225
+ export interface AgentInstallResult {
141
226
  skills: number;
142
227
  assets: number;
143
- };
228
+ /** Files left as they are because they were edited since the last install (relative to the target dir). */
229
+ kept: string[];
230
+ /** Files of skills the bundle no longer ships, removed because nobody edited them. */
231
+ removed: string[];
232
+ }
233
+ export declare function installForAgent(agentKey: AgentKey, skills: LoadedSkill[], projectDir: string, options?: {
234
+ force?: boolean;
235
+ }): AgentInstallResult;
236
+ /** What `installSkills` did for one agent. */
237
+ export interface SkillsInstallResult extends AgentInstallResult {
238
+ agent: AgentKey;
239
+ /** An earlier agent in the same run that already wrote this directory. */
240
+ sharedWith?: AgentKey;
241
+ }
242
+ /**
243
+ * Install for several agents, writing each target directory once.
244
+ *
245
+ * Gemini and Codex both read `.agents/skills`; installing twice would write the
246
+ * same 21 files twice and report two installs of one directory.
247
+ */
248
+ export declare function installSkills(agents: readonly AgentKey[], skills: LoadedSkill[], projectDir: string, options?: {
249
+ force?: boolean;
250
+ }): SkillsInstallResult[];
144
251
  /** Everything the switch below dispatches, for the did-you-mean. */
145
252
  export declare const SKILLS_SUBCOMMANDS: readonly ["install"];
146
253
  export declare function skillsCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
@@ -150,4 +257,16 @@ export declare function skillsCommand(subcommand: string | undefined, rawArgs: s
150
257
  * given.
151
258
  */
152
259
  export declare function parseAgentFlags(rawArgs: string[]): AgentKey[] | null;
153
- export {};
260
+ /** `rebase skills install`'s whole line: the agents it names, `--mcp` and `--force`. */
261
+ export declare function parseSkillsInstallLine(rawArgs: string[]): {
262
+ agents: AgentKey[] | null;
263
+ mcp: boolean;
264
+ force: boolean;
265
+ };
266
+ /**
267
+ * The agents a list of `--agent` values names, or null when it names none.
268
+ *
269
+ * Shared by `rebase skills install` and `rebase init`, so both accept the same
270
+ * spellings. Throws a UsageError on a name that is not an agent.
271
+ */
272
+ export declare function resolveAgentNames(values: readonly string[]): AgentKey[] | null;
@@ -1 +1,30 @@
1
+ import type { RebaseBundleStatic } from "@rebasepro/types";
2
+ /** The NODE_ENV the runtime will see, and where it comes from. */
3
+ export interface StartNodeEnv {
4
+ value: string | undefined;
5
+ source: "shell" | ".env" | "unset";
6
+ }
7
+ /**
8
+ * What NODE_ENV the server will boot in. The shell wins — dotenv never
9
+ * overrides a variable that is already set — then `.env`.
10
+ */
11
+ export declare function startNodeEnv(projectRoot: string): StartNodeEnv;
12
+ /**
13
+ * The banner for a `rebase start` that is not a production server, or `null`.
14
+ *
15
+ * Not forced to production: the scaffold's `.env` points at a loopback
16
+ * database, which a production boot refuses, so forcing it would break the
17
+ * documented local run. What must not happen is the silence — a command the
18
+ * help called "(production)" booting with the first-registration window open.
19
+ */
20
+ export declare function nonProductionWarning(nodeEnv: StartNodeEnv): string[] | null;
21
+ /**
22
+ * What to say about the apps a bundle serves only on their own hostname.
23
+ *
24
+ * The runtime prints "Server running at http://localhost:<port>", and an app
25
+ * whose `path` names a hostname answers only requests carrying that `Host` —
26
+ * so opening the printed URL showed a 404 for an app that was running fine,
27
+ * and nothing said why. One line per such app, with a command that reaches it.
28
+ */
29
+ export declare function hostRoutedNotice(staticApps: readonly RebaseBundleStatic[], port: string | undefined): string[];
1
30
  export declare function startCommand(rawArgs?: string[]): Promise<void>;