@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
@@ -0,0 +1,106 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { DEFAULT_DATA_SOURCE_KEY, getDataSourceCapabilities } from "@rebasepro/types";
4
+ //#region src/utils/collection-drift.ts
5
+ /**
6
+ * Which edits under `config/collections` can put the *SQL* schema out of date.
7
+ *
8
+ * `rebase dev` watches that directory and, on any change, either tells the
9
+ * developer to run `rebase schema generate` / `rebase db push` or runs them.
10
+ * The watcher is recursive and knows nothing about what it is watching, so it
11
+ * said that about every file under the directory — including a
12
+ * `collections/firestore/exercises.ts`, whose documents live in Firestore and
13
+ * for which there is no Drizzle schema to regenerate and no database to push
14
+ * to. Advice that is wrong on every edit is advice a developer learns to
15
+ * ignore, which is worse than none: the same box is the only warning for the
16
+ * Postgres collection next to it, where it is real.
17
+ *
18
+ * Two independent reasons a change cannot affect the SQL schema, both checked
19
+ * here:
20
+ *
21
+ * 1. **The loader would never read the file.** `loadCollectionsFromDirectory`
22
+ * reads the top level of the collections directory only — no recursion, no
23
+ * `index`, no tests, no declarations. A file it does not read cannot change
24
+ * what it returns, and the watcher must not claim otherwise.
25
+ * 2. **Every collection in it is served by another engine.** A Firestore or
26
+ * MongoDB collection has no table, no migration and no policies.
27
+ *
28
+ * The engine check reads the source text rather than importing the module: the
29
+ * CLI runs as plain Node and cannot evaluate a project's TypeScript, and a
30
+ * watcher must answer in the time between two keystrokes. Anything it cannot
31
+ * read confidently counts as SQL-affecting — a spurious warning is a nuisance,
32
+ * a suppressed one hides real drift.
33
+ */
34
+ /**
35
+ * Would `loadCollectionsFromDirectory` load this file?
36
+ *
37
+ * Mirrors that loader's own `isCollectionFile` plus its flat (non-recursive)
38
+ * scan. `relativePath` is relative to the collections directory, as `fs.watch`
39
+ * reports it.
40
+ */
41
+ function isLoadedCollectionFile(relativePath) {
42
+ const normalized = relativePath.split(path.sep).join("/");
43
+ if (normalized.includes("/")) return false;
44
+ const file = normalized;
45
+ if (!file.endsWith(".ts") && !file.endsWith(".js")) return false;
46
+ if (file.startsWith(".")) return false;
47
+ if (file.includes(".test.")) return false;
48
+ if (file.endsWith(".d.ts")) return false;
49
+ if (file === "index.ts" || file === "index.js") return false;
50
+ return true;
51
+ }
52
+ var ENGINE_LITERAL = /\bengine\s*:\s*["'`]([^"'`]+)["'`]/g;
53
+ var DATA_SOURCE_LITERAL = /\bdataSource\s*:\s*["'`]([^"'`]+)["'`]/g;
54
+ /**
55
+ * Drop comments, so a `// engine: "firestore"` in a docblock cannot silence a
56
+ * warning about the Postgres collection the file actually declares.
57
+ *
58
+ * Deliberately naive — it does not understand strings, so a `//` inside one
59
+ * (a URL in a default value) eats the rest of that line. That only ever removes
60
+ * text, and removing an engine literal makes this file *more* likely to warn,
61
+ * which is the side to be wrong on.
62
+ */
63
+ function stripComments(source) {
64
+ return source.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/\/\/[^\n]*/g, " ");
65
+ }
66
+ function literals(source, pattern) {
67
+ const found = [];
68
+ for (const match of source.matchAll(pattern)) found.push(match[1]);
69
+ return found;
70
+ }
71
+ /**
72
+ * Does this collection source declare anything a SQL toolchain would own?
73
+ *
74
+ * The fallback order matches `resolveDataSource`: an explicit `engine` wins,
75
+ * and a collection that only names a `dataSource` is resolved as if the key
76
+ * were the engine — which is what that function does when no registry is
77
+ * available, and the CLI has none. An engine nobody recognises counts as
78
+ * relational, for the reason `isRelationalCollection` gives.
79
+ *
80
+ * A file declaring several collections is SQL-affecting if *any* of them is.
81
+ */
82
+ function declaresRelationalCollection(rawSource) {
83
+ const source = stripComments(rawSource);
84
+ const engines = literals(source, ENGINE_LITERAL);
85
+ const declared = engines.length > 0 ? engines : literals(source, DATA_SOURCE_LITERAL).filter((key) => key !== DEFAULT_DATA_SOURCE_KEY);
86
+ if (declared.length === 0) return true;
87
+ return declared.some((engine) => getDataSourceCapabilities(engine).supportsRelations);
88
+ }
89
+ /**
90
+ * Can this edit have changed the generated SQL schema?
91
+ *
92
+ * Answers `true` when it cannot tell — an unreadable file is a reason to warn,
93
+ * not a reason to go quiet.
94
+ */
95
+ function affectsSqlSchema(collectionsDir, relativePath) {
96
+ if (!isLoadedCollectionFile(relativePath)) return false;
97
+ try {
98
+ return declaresRelationalCollection(fs.readFileSync(path.join(collectionsDir, relativePath), "utf8"));
99
+ } catch {
100
+ return true;
101
+ }
102
+ }
103
+ //#endregion
104
+ export { isLoadedCollectionFile as n, affectsSqlSchema as t };
105
+
106
+ //# sourceMappingURL=collection-drift-BKj_BoMq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collection-drift-BKj_BoMq.js","names":[],"sources":["../src/utils/collection-drift.ts"],"sourcesContent":["/**\n * Which edits under `config/collections` can put the *SQL* schema out of date.\n *\n * `rebase dev` watches that directory and, on any change, either tells the\n * developer to run `rebase schema generate` / `rebase db push` or runs them.\n * The watcher is recursive and knows nothing about what it is watching, so it\n * said that about every file under the directory — including a\n * `collections/firestore/exercises.ts`, whose documents live in Firestore and\n * for which there is no Drizzle schema to regenerate and no database to push\n * to. Advice that is wrong on every edit is advice a developer learns to\n * ignore, which is worse than none: the same box is the only warning for the\n * Postgres collection next to it, where it is real.\n *\n * Two independent reasons a change cannot affect the SQL schema, both checked\n * here:\n *\n * 1. **The loader would never read the file.** `loadCollectionsFromDirectory`\n * reads the top level of the collections directory only — no recursion, no\n * `index`, no tests, no declarations. A file it does not read cannot change\n * what it returns, and the watcher must not claim otherwise.\n * 2. **Every collection in it is served by another engine.** A Firestore or\n * MongoDB collection has no table, no migration and no policies.\n *\n * The engine check reads the source text rather than importing the module: the\n * CLI runs as plain Node and cannot evaluate a project's TypeScript, and a\n * watcher must answer in the time between two keystrokes. Anything it cannot\n * read confidently counts as SQL-affecting — a spurious warning is a nuisance,\n * a suppressed one hides real drift.\n */\nimport fs from \"fs\";\nimport path from \"path\";\nimport { DEFAULT_DATA_SOURCE_KEY, getDataSourceCapabilities } from \"@rebasepro/types\";\n\n/**\n * Would `loadCollectionsFromDirectory` load this file?\n *\n * Mirrors that loader's own `isCollectionFile` plus its flat (non-recursive)\n * scan. `relativePath` is relative to the collections directory, as `fs.watch`\n * reports it.\n */\nexport function isLoadedCollectionFile(relativePath: string): boolean {\n const normalized = relativePath.split(path.sep).join(\"/\");\n // A nested path is a subdirectory, which the loader does not descend into.\n if (normalized.includes(\"/\")) return false;\n\n const file = normalized;\n if (!file.endsWith(\".ts\") && !file.endsWith(\".js\")) return false;\n if (file.startsWith(\".\")) return false;\n if (file.includes(\".test.\")) return false;\n if (file.endsWith(\".d.ts\")) return false;\n // The directory's own module: defaults live there, not a collection.\n if (file === \"index.ts\" || file === \"index.js\") return false;\n return true;\n}\n\nconst ENGINE_LITERAL = /\\bengine\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/g;\nconst DATA_SOURCE_LITERAL = /\\bdataSource\\s*:\\s*[\"'`]([^\"'`]+)[\"'`]/g;\n\n/**\n * Drop comments, so a `// engine: \"firestore\"` in a docblock cannot silence a\n * warning about the Postgres collection the file actually declares.\n *\n * Deliberately naive — it does not understand strings, so a `//` inside one\n * (a URL in a default value) eats the rest of that line. That only ever removes\n * text, and removing an engine literal makes this file *more* likely to warn,\n * which is the side to be wrong on.\n */\nfunction stripComments(source: string): string {\n return source.replace(/\\/\\*[\\s\\S]*?\\*\\//g, \" \").replace(/\\/\\/[^\\n]*/g, \" \");\n}\n\nfunction literals(source: string, pattern: RegExp): string[] {\n const found: string[] = [];\n for (const match of source.matchAll(pattern)) found.push(match[1]);\n return found;\n}\n\n/**\n * Does this collection source declare anything a SQL toolchain would own?\n *\n * The fallback order matches `resolveDataSource`: an explicit `engine` wins,\n * and a collection that only names a `dataSource` is resolved as if the key\n * were the engine — which is what that function does when no registry is\n * available, and the CLI has none. An engine nobody recognises counts as\n * relational, for the reason `isRelationalCollection` gives.\n *\n * A file declaring several collections is SQL-affecting if *any* of them is.\n */\nexport function declaresRelationalCollection(rawSource: string): boolean {\n const source = stripComments(rawSource);\n const engines = literals(source, ENGINE_LITERAL);\n const declared = engines.length > 0\n ? engines\n : literals(source, DATA_SOURCE_LITERAL).filter(key => key !== DEFAULT_DATA_SOURCE_KEY);\n\n if (declared.length === 0) return true;\n return declared.some(engine => getDataSourceCapabilities(engine).supportsRelations);\n}\n\n/**\n * Can this edit have changed the generated SQL schema?\n *\n * Answers `true` when it cannot tell — an unreadable file is a reason to warn,\n * not a reason to go quiet.\n */\nexport function affectsSqlSchema(collectionsDir: string, relativePath: string): boolean {\n if (!isLoadedCollectionFile(relativePath)) return false;\n try {\n return declaresRelationalCollection(\n fs.readFileSync(path.join(collectionsDir, relativePath), \"utf8\")\n );\n } catch {\n // Deleted between the event and the read, or unreadable. Both leave the\n // schema genuinely in question.\n return true;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,uBAAuB,cAA+B;CAClE,MAAM,aAAa,aAAa,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,GAAG;CAExD,IAAI,WAAW,SAAS,GAAG,GAAG,OAAO;CAErC,MAAM,OAAO;CACb,IAAI,CAAC,KAAK,SAAS,KAAK,KAAK,CAAC,KAAK,SAAS,KAAK,GAAG,OAAO;CAC3D,IAAI,KAAK,WAAW,GAAG,GAAG,OAAO;CACjC,IAAI,KAAK,SAAS,QAAQ,GAAG,OAAO;CACpC,IAAI,KAAK,SAAS,OAAO,GAAG,OAAO;CAEnC,IAAI,SAAS,cAAc,SAAS,YAAY,OAAO;CACvD,OAAO;AACX;AAEA,IAAM,iBAAiB;AACvB,IAAM,sBAAsB;;;;;;;;;;AAW5B,SAAS,cAAc,QAAwB;CAC3C,OAAO,OAAO,QAAQ,qBAAqB,GAAG,CAAC,CAAC,QAAQ,eAAe,GAAG;AAC9E;AAEA,SAAS,SAAS,QAAgB,SAA2B;CACzD,MAAM,QAAkB,CAAC;CACzB,KAAK,MAAM,SAAS,OAAO,SAAS,OAAO,GAAG,MAAM,KAAK,MAAM,EAAE;CACjE,OAAO;AACX;;;;;;;;;;;;AAaA,SAAgB,6BAA6B,WAA4B;CACrE,MAAM,SAAS,cAAc,SAAS;CACtC,MAAM,UAAU,SAAS,QAAQ,cAAc;CAC/C,MAAM,WAAW,QAAQ,SAAS,IAC5B,UACA,SAAS,QAAQ,mBAAmB,CAAC,CAAC,QAAO,QAAO,QAAQ,uBAAuB;CAEzF,IAAI,SAAS,WAAW,GAAG,OAAO;CAClC,OAAO,SAAS,MAAK,WAAU,0BAA0B,MAAM,CAAC,CAAC,iBAAiB;AACtF;;;;;;;AAQA,SAAgB,iBAAiB,gBAAwB,cAA+B;CACpF,IAAI,CAAC,uBAAuB,YAAY,GAAG,OAAO;CAClD,IAAI;EACA,OAAO,6BACH,GAAG,aAAa,KAAK,KAAK,gBAAgB,YAAY,GAAG,MAAM,CACnE;CACJ,QAAQ;EAGJ,OAAO;CACX;AACJ"}
@@ -0,0 +1,13 @@
1
+ export interface ParsedCommandSpec {
2
+ /** The command words, as the call names them: `"build"`, `"skills install"`. */
3
+ command: string;
4
+ /** Canonical long flags: the value is a type, not another flag's name. */
5
+ flags: string[];
6
+ /** Every spelling the parser accepts, aliases and short flags included. */
7
+ accepted: string[];
8
+ file: string;
9
+ }
10
+ /** The parser calls in one file. Throws on a call it cannot read, so a new shape fails loudly. */
11
+ export declare function parsedCommands(file: string): ParsedCommandSpec[];
12
+ /** Every parser call under `src/` that the dispatch reaches: `cli.ts` and the command modules. */
13
+ export declare function allParsedCommands(commandsDir: string): ParsedCommandSpec[];
@@ -0,0 +1,116 @@
1
+ import { type AgentKey, type LoadedSkill } from "./skills.js";
2
+ import { type PackageManager } from "../utils/package-manager.js";
3
+ /** The name the server is registered under, in every config. */
4
+ export declare const MCP_SERVER_NAME = "rebase";
5
+ /** The MCP server's package: a devDependency of the project, pinned with the rest. */
6
+ export declare const MCP_PACKAGE = "@rebasepro/mcp";
7
+ /** The bin {@link MCP_PACKAGE} declares. */
8
+ export declare const MCP_BIN = "rebase-mcp";
9
+ /** The command an assistant spawns, and its arguments. */
10
+ export interface McpLaunch {
11
+ command: string;
12
+ args: string[];
13
+ }
14
+ /**
15
+ * How an assistant starts the Rebase MCP server: the project's own copy, through
16
+ * the project's package manager.
17
+ *
18
+ * Not `npx -y @rebasepro/mcp`, which fetched the newest release on every first
19
+ * start. The server drives the project's own CLI (`pnpm exec rebase …`) and calls
20
+ * the project's own backend (`/api/admin/schema/plan`, …), whose versions the
21
+ * lockfile pins — so a server from the registry ran ahead of both, at every
22
+ * start, and downloaded before it could answer. `@rebasepro/mcp` is a
23
+ * devDependency of the scaffold, pinned to the CLI's version like every other
24
+ * `@rebasepro` package, and this runs that copy.
25
+ *
26
+ * `npx --no`, not `npx`: an assistant spawns the server with no TTY, and npx
27
+ * then assumes "yes" and installs a missing package from the registry under the
28
+ * name it was given. `--no` makes a missing install an error instead.
29
+ */
30
+ export declare function mcpLaunch(pm: PackageManager): McpLaunch;
31
+ /** What writing one MCP config did. */
32
+ export type McpWriteStatus =
33
+ /** The file was created, or the server was added beside the ones in it. */
34
+ "added"
35
+ /** A `rebase` server was already there. It is left exactly as it was. */
36
+ | "present"
37
+ /** The file exists but is not something this can edit without losing data. */
38
+ | "unreadable";
39
+ export interface McpWriteResult {
40
+ /** Project-relative path of the config file. */
41
+ file: string;
42
+ status: McpWriteStatus;
43
+ }
44
+ /**
45
+ * The Codex block, as TOML. Appended rather than merged: there is no TOML
46
+ * parser here, and an append keeps every byte already in the file.
47
+ */
48
+ export declare function renderCodexServer(projectDir: string, launch: McpLaunch): string;
49
+ /**
50
+ * Register the Rebase MCP server in the agent's project-level config, started
51
+ * through the project's package manager (see {@link mcpLaunch}).
52
+ *
53
+ * Returns null for an agent with no project-level config to write.
54
+ */
55
+ export declare function writeMcpConfig(agentKey: AgentKey, projectDir: string, pm?: PackageManager): McpWriteResult | null;
56
+ /** What making sure the project depends on the MCP server did. */
57
+ export type McpDependencyStatus =
58
+ /** Added to `devDependencies`, at this CLI's version: an install is due. */
59
+ "added"
60
+ /** Already a dependency. Left at the version the project chose. */
61
+ | "present"
62
+ /** No `package.json`, or one that is not plain JSON: left alone. */
63
+ | "unreadable";
64
+ /**
65
+ * Make the project depend on {@link MCP_PACKAGE}, which the config written by
66
+ * {@link writeMcpConfig} runs from the project's own install.
67
+ *
68
+ * Pinned to this CLI's version, as `rebase init` pins every `@rebasepro`
69
+ * package; a project that already lists it keeps its own choice.
70
+ */
71
+ export declare function ensureMcpDependency(projectDir: string): McpDependencyStatus;
72
+ /**
73
+ * Point the scaffold's `.mcp.json` at the project's package manager.
74
+ *
75
+ * The template ships the pnpm spelling (`pnpm exec rebase-mcp`); an npm project
76
+ * has no pnpm to run it with. Only the entry the template wrote is rewritten.
77
+ */
78
+ export declare function retargetScaffoldMcpConfig(projectDir: string, pm: PackageManager): void;
79
+ /**
80
+ * Whether the agent's project-level config already registers the Rebase
81
+ * server: `null` for an agent that has no such config, `false` when the file
82
+ * is missing or does not name it. Reads only — for the hint `rebase skills
83
+ * install` prints when it was not asked to write one.
84
+ */
85
+ export declare function mcpServerRegistered(agentKey: AgentKey, projectDir: string): boolean | null;
86
+ /** What `configureAgents` did for one agent. */
87
+ export interface AgentSetupResult {
88
+ agent: AgentKey;
89
+ /** Skills written, or null when the bundle could not be loaded. */
90
+ skills: number | null;
91
+ /** An earlier agent in the same run that already wrote the skills directory. */
92
+ sharedWith?: AgentKey;
93
+ mcp: McpWriteResult | null;
94
+ }
95
+ /**
96
+ * Install the skills and register the MCP server for each agent.
97
+ *
98
+ * Never throws for a missing skills bundle — the scaffold it runs inside must
99
+ * not fail over its assistants — and reports it as `skills: null` instead.
100
+ */
101
+ export declare function configureAgents(agents: readonly AgentKey[], projectDir: string, load?: () => LoadedSkill[], pm?: PackageManager): {
102
+ results: AgentSetupResult[];
103
+ skillsError?: string;
104
+ mcpDependency?: McpDependencyStatus;
105
+ };
106
+ /** The line to print when {@link ensureMcpDependency} changed or could not change the manifest. */
107
+ export declare function mcpDependencyNote(status: McpDependencyStatus | undefined, pm: PackageManager): string | undefined;
108
+ /** One line per agent, for the scaffold's output. */
109
+ export declare function printAgentSetup({ results, skillsError, mcpDependency }: ReturnType<typeof configureAgents>, pm?: PackageManager): void;
110
+ /**
111
+ * Ask whether to set up AI agents, then which, pre-ticking what is installed.
112
+ *
113
+ * Interactive only; the caller has already refused a non-TTY. Returns [] when
114
+ * the developer says no or unticks everything.
115
+ */
116
+ export declare function promptForAgents(home?: string): Promise<AgentKey[]>;
@@ -1,40 +1,94 @@
1
+ import { type ApiKeyMasked, type ScopeSummary } from "@rebasepro/types";
1
2
  /** Everything the switch below dispatches, for the did-you-mean. */
2
- export declare const API_KEYS_SUBCOMMANDS: readonly ["list", "create", "revoke"];
3
+ export declare const API_KEYS_SUBCOMMANDS: readonly ["list", "get", "create", "revoke", "scopes"];
4
+ /** The running backend's URL. Shared with `rebase storage`. */
5
+ export declare function resolveBaseUrl(env: Record<string, string>, projectRoot?: string): string;
6
+ /**
7
+ * What to print when a request fails: the server's error code and message,
8
+ * which is what says why — `SCOPE_EXCEEDS_CREATOR`, `INVALID_SCOPES`,
9
+ * `ROLE_EXCEEDS_CREATOR`, `KEY_MANAGEMENT_SCOPE` — and a hint where one helps.
10
+ *
11
+ * Exported so its tests can read the lines without a server.
12
+ */
13
+ export declare function describeFailure(action: string, error: unknown, baseUrl: string): string[];
3
14
  export declare function apiKeysCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
15
+ /**
16
+ * The lines that describe one key: what it is, what it may do and whom it
17
+ * runs as.
18
+ *
19
+ * A service key runs as the RLS role `service` plus its own `roles`; a
20
+ * personal key runs as its owner's roles as they are when it is used, so it
21
+ * has none of its own to show.
22
+ *
23
+ * Exported so its tests can read the lines without a server.
24
+ */
25
+ export declare function describeKey(key: ApiKeyMasked, now?: Date): string[];
26
+ /** The flags `rebase api-keys list` takes: none of its own. */
27
+ export declare const LIST_KEYS_FLAGS: {};
28
+ /** The flags `rebase api-keys get` takes. */
29
+ export declare const GET_KEY_FLAGS: {
30
+ readonly "--id": StringConstructor;
31
+ };
32
+ /**
33
+ * Which key this invocation names, as a positional or as `--id`.
34
+ *
35
+ * Exported so its tests can drive the real parser rather than a copy of it.
36
+ */
37
+ export declare function resolveGetKeyArgs(rawArgs: string[]): {
38
+ id?: string;
39
+ };
4
40
  /** The flags `rebase api-keys create` takes. */
5
41
  export declare const CREATE_KEY_FLAGS: {
6
- readonly "--name": StringConstructor;
7
- readonly "--permissions": StringConstructor;
8
- readonly "--full-access": BooleanConstructor;
9
- readonly "--admin": BooleanConstructor;
10
- readonly "--rate-limit": NumberConstructor;
11
- readonly "--expires": StringConstructor;
12
- readonly "-n": "--name";
42
+ "--name": StringConstructor;
43
+ "--scopes": [StringConstructor];
44
+ "--full-access": BooleanConstructor;
45
+ "--roles": [StringConstructor];
46
+ "--rate-limit": NumberConstructor;
47
+ "--expires-in": StringConstructor;
48
+ "--expires-at": StringConstructor;
49
+ "-n": string;
13
50
  };
51
+ /**
52
+ * Options `create` refuses by name, each with the flag that does that job.
53
+ *
54
+ * Checked before the line is parsed: the strict parser would answer them
55
+ * "unknown option", which does not say what to type instead.
56
+ */
57
+ export declare const RETIRED_CREATE_OPTIONS: Readonly<Record<string, string>>;
58
+ /** What `rebase api-keys create` was asked to mint. */
59
+ export interface CreateKeyPlan {
60
+ name: string;
61
+ /** The scopes named with `--scopes`, or `"held"` for `--full-access`. */
62
+ scopes: string[] | "held";
63
+ /** RLS roles beside `service`. */
64
+ roles: string[];
65
+ rate_limit: number | null;
66
+ expires_at: string | null;
67
+ }
14
68
  /**
15
69
  * What this invocation asks to be created.
16
70
  *
17
71
  * The name may be given either way — `--name "My Key"` or as the single
18
72
  * positional — and under the old permissive parse an undeclared flag became
19
73
  * that positional: `rebase api-keys create --debug --full-access` created a
20
- * key called `--debug` with read/write/delete on every collection, and
21
- * `--debug` is what the CLI prints after every failure as the thing to re-run
22
- * with. Strict parsing makes the flag an error instead of a name.
74
+ * key called `--debug` with access to everything, and `--debug` is what the
75
+ * CLI prints after every failure as the thing to re-run with. Strict parsing
76
+ * makes the flag an error instead of a name.
77
+ *
78
+ * What the key may do has to be asked for by name — `--scopes` or
79
+ * `--full-access` — never defaulted: a forgotten flag must not mint a key that
80
+ * reaches everything.
23
81
  *
24
82
  * Exported so its tests can drive the real parser rather than a copy of it.
25
83
  */
26
- export declare function resolveCreateKeyArgs(rawArgs: string[]): {
27
- flags: import("arg").Result<{
28
- readonly "--name": StringConstructor;
29
- readonly "--permissions": StringConstructor;
30
- readonly "--full-access": BooleanConstructor;
31
- readonly "--admin": BooleanConstructor;
32
- readonly "--rate-limit": NumberConstructor;
33
- readonly "--expires": StringConstructor;
34
- readonly "-n": "--name";
35
- }>;
36
- name: string;
37
- };
84
+ export declare function resolveCreateKeyArgs(rawArgs: string[], now?: Date): CreateKeyPlan;
85
+ /**
86
+ * The scopes `--full-access` puts on a key: every one the caller holds, less
87
+ * key management, which no key may hold.
88
+ *
89
+ * Exported so its tests can check the subtraction without a server.
90
+ */
91
+ export declare function grantableScopes(held: readonly string[]): string[];
38
92
  /** The flags `rebase api-keys revoke` takes. */
39
93
  export declare const REVOKE_KEY_FLAGS: {
40
94
  readonly "--id": StringConstructor;
@@ -52,3 +106,12 @@ export declare const REVOKE_KEY_FLAGS: {
52
106
  export declare function resolveRevokeKeyArgs(rawArgs: string[]): {
53
107
  id?: string;
54
108
  };
109
+ /** The flags `rebase api-keys scopes` takes: none of its own. */
110
+ export declare const SCOPES_LIST_FLAGS: {};
111
+ /**
112
+ * The scope catalogue as printed lines: one section per plane, each scope with
113
+ * its label and what its target names, marked when the caller holds it.
114
+ *
115
+ * Exported so its tests can read the lines without a server.
116
+ */
117
+ export declare function describeScopes(scopes: readonly ScopeSummary[], held: readonly string[]): string[];
@@ -1,3 +1,20 @@
1
+ import type { RebaseAppConfig } from "@rebasepro/types";
2
+ import { loadManifest } from "../manifest.js";
1
3
  /** Everything the switch below dispatches, for the did-you-mean. */
2
4
  export declare const APPS_SUBCOMMANDS: readonly ["list", "init", "config"];
3
5
  export declare function appsCommand(subcommand: string | undefined, rawArgs?: string[]): Promise<void>;
6
+ /**
7
+ * One app's line in `rebase apps list`.
8
+ *
9
+ * A static app shows its full address — the https URL when its `path` gives it
10
+ * a hostname — and the CMS as the address a browser would open. `CMS at /` on
11
+ * an app that lives on `admin.example.com` reads as the project's own root,
12
+ * which is the one place that CMS is not.
13
+ */
14
+ export declare function describeApp(name: string, app: RebaseAppConfig): string;
15
+ /**
16
+ * Whether `rebase build` folds this static app into the backend bundle, which
17
+ * then serves it on the API's own origin: a managed backend, and an app with
18
+ * built output to fold. The same predicate the build folds by.
19
+ */
20
+ export declare function servedByBackend(manifest: ReturnType<typeof loadManifest>["manifest"], appName: string): boolean;
@@ -80,6 +80,13 @@ export declare function generatePassword(): string;
80
80
  * The script the direct-database fallback runs under the project's own tsx, so
81
81
  * it resolves the project's `@rebasepro/server-postgres` and schema.
82
82
  *
83
+ * It ends the account's sessions in the transaction that sets the password,
84
+ * as every door through the API does (`replaceUserPassword`): the refresh
85
+ * tokens and outstanding reset links go, and `tokens_valid_after` voids the
86
+ * access tokens already handed out. An operator resetting a phished account
87
+ * with the backend down is the case this exists for, and a reset that left the
88
+ * attacker's refresh token minting access tokens did not recover anything.
89
+ *
83
90
  * It exits 0 only when a row was updated: a missing user and a thrown error are
84
91
  * both exit 1. `echoPassword` prints the new password, for a generated one.
85
92
  *
@@ -39,7 +39,11 @@ export declare function buildCommand(rawArgs?: string[]): Promise<void>;
39
39
  * with its JSON error.
40
40
  */
41
41
  export declare function buildAssetApp(projectRoot: string, name: string, app: RebaseAppConfig, runtimeRange: string, outOverride?: string,
42
- /** `quietStdout`: every line, the build command's included, goes to stderr. See `toolStdio`. */
42
+ /**
43
+ * `quietStdout`: every line, the build command's included, goes to stderr. See `toolStdio`.
44
+ * `builtApps`: the static apps already built in this run (see `FoldOptions.builtApps`).
45
+ */
43
46
  options?: {
44
47
  quietStdout?: boolean;
48
+ builtApps?: Set<string>;
45
49
  }): Promise<string | undefined>;
@@ -20,9 +20,10 @@ export declare const LOGIN_FLAGS: {
20
20
  * neither is something this CLI can redact after the fact — the same reasoning
21
21
  * `rls-check` states for its connection string, which carries one too.
22
22
  *
23
- * There is no machine token yet, so CI genuinely does need a human's password;
24
- * `REBASE_CLOUD_PASSWORD` is how a secret store hands it over without it
25
- * appearing on a command line.
23
+ * CI should not need a password at all: `rebase cloud tokens create` mints a
24
+ * token narrowed to one project, and `REBASE_TOKEN` hands it to every cloud
25
+ * command. Where a login is still wanted, `REBASE_CLOUD_PASSWORD` is how a
26
+ * secret store hands the password over without it appearing on a command line.
26
27
  */
27
28
  export declare const PASSWORD_ENV = "REBASE_CLOUD_PASSWORD";
28
29
  export declare const EMAIL_ENV = "REBASE_CLOUD_EMAIL";
@@ -126,3 +126,48 @@ export declare function declaredAppsFrom(manifest: {
126
126
  } | null | undefined): DeclaredApp[];
127
127
  /** Upload a bundle archive; returns the control-plane bundle id. */
128
128
  export declare function uploadBundle(url: string, token: string, projectId: string, tarPath: string): Promise<string>;
129
+ /** One DNS record a hostname needs, as the control plane lists it. */
130
+ export interface DeployHostRecord {
131
+ type: string;
132
+ name: string;
133
+ values: string[];
134
+ }
135
+ /**
136
+ * A hostname an app in this deploy is declared on, as the deploy found it.
137
+ *
138
+ * The control plane registers each one on the project as it deploys — an app
139
+ * whose `path` is `https://admin.example.com` needs that host on the project
140
+ * before anything can route it — and a new one starts `pending`, because it is
141
+ * served only once its DNS is published and verified. `records` is what to
142
+ * publish, present for a pending host.
143
+ */
144
+ export interface DeployHost {
145
+ host: string;
146
+ status: "verified" | "pending";
147
+ records?: DeployHostRecord[];
148
+ }
149
+ /**
150
+ * The `hosts` a deploy response carries, read defensively.
151
+ *
152
+ * `undefined` when there is no such field, which is what a control plane that
153
+ * predates host-routed apps answers: the caller then leaves `hosts` out of its
154
+ * own output rather than reporting an empty set nobody looked for. An entry
155
+ * with no hostname is dropped, and any status but `verified` is pending — the
156
+ * same rule `cloud domains` reads rows by, because an unreadable status must
157
+ * not print as live.
158
+ */
159
+ export declare function deployHostsFrom(response: unknown): DeployHost[] | undefined;
160
+ /**
161
+ * What to tell somebody whose deploy declared a hostname that is not live yet.
162
+ *
163
+ * A deploy that succeeds with an app on a hostname nobody can reach reads as a
164
+ * broken deploy, so each pending host gets its own block: that it is registered
165
+ * but waiting, the records to create, and the command that finishes the job.
166
+ * The records come from the control plane, never composed here — A or CNAME
167
+ * depends on apex-vs-subdomain and on the ingress behind the project, which
168
+ * the CLI cannot know. Plain text: the caller colours it.
169
+ */
170
+ export declare function pendingHostNotices(hosts: DeployHost[]): Array<{
171
+ headline: string;
172
+ details: string[];
173
+ }>;
@@ -59,6 +59,24 @@ export type CloudClient = ReturnType<typeof createRebaseClient>;
59
59
  * by `requireClient`.
60
60
  */
61
61
  export declare function createCloudClient(url: string): CloudClient;
62
+ /**
63
+ * The environment variable that authenticates the cloud family with a token
64
+ * instead of a `cloud login` session — for CI and agents, which have no
65
+ * terminal to log in at and should not hold a person's password.
66
+ */
67
+ export declare const TOKEN_ENV = "REBASE_TOKEN";
68
+ /** `REBASE_TOKEN`, trimmed, or undefined when it is unset or blank. */
69
+ export declare function envToken(): string | undefined;
70
+ /**
71
+ * A client that sends `token` as its bearer and nothing else.
72
+ *
73
+ * No session: the token is not refreshed, and the credentials file is neither
74
+ * read nor written — a CI job's token must not become, or replace, the login
75
+ * of whoever owns the machine. A 401 is answered by {@link explainRefusedToken}
76
+ * rather than by the SDK's session refresh, because there is no session to
77
+ * refresh and "log in again" is the wrong remedy for a token.
78
+ */
79
+ export declare function createTokenClient(url: string, token: string): CloudClient;
62
80
  /** The half of a client that holds its session — all {@link freshAccessToken} reads. */
63
81
  export interface SessionHolder {
64
82
  auth: {
@@ -81,17 +99,36 @@ export interface SessionHolder {
81
99
  * token read once at the start of a command that runs for longer than it
82
100
  * lives — a deploy's build, a `db connect` left open — is refused by the time
83
101
  * it is used, so it is read here at the moment it is sent.
102
+ *
103
+ * A client built from `REBASE_TOKEN` has no session; its token is returned
104
+ * as it is, since there is nothing to refresh it with.
84
105
  */
85
106
  export declare function freshAccessToken(client: SessionHolder): Promise<string>;
86
107
  /**
87
- * Return an authenticated client for the resolved host, refreshing the access
88
- * token if it is close to expiry. Exits with a helpful message when there is no
89
- * usable session (never logged in, or the refresh token was revoked).
108
+ * Return an authenticated client for the resolved host.
109
+ *
110
+ * With `REBASE_TOKEN` set, that token is the credential for every request and
111
+ * the stored login is not consulted at all. Otherwise it is the `cloud login`
112
+ * session — see {@link requireSessionClient}.
90
113
  */
91
114
  export declare function requireClient(rawArgs: string[]): Promise<{
92
115
  client: CloudClient;
93
116
  url: string;
94
117
  }>;
118
+ /**
119
+ * Return a client holding the `cloud login` session for the resolved host,
120
+ * refreshing the access token if it is close to expiry, whether or not
121
+ * `REBASE_TOKEN` is set. Exits with a helpful message when there is no usable
122
+ * session (never logged in, or the refresh token was revoked).
123
+ *
124
+ * For the commands a token cannot run — minting and revoking tokens: a key that
125
+ * could mint keys could mint its own successor, so the control plane refuses
126
+ * every key on those routes.
127
+ */
128
+ export declare function requireSessionClient(rawArgs: string[]): Promise<{
129
+ client: CloudClient;
130
+ url: string;
131
+ }>;
95
132
  /** One place a deploy can actually land, as the control plane describes it. */
96
133
  export interface DeployTarget {
97
134
  clusterId?: string | null;
@@ -192,8 +229,10 @@ export declare function removeLink(cwd?: string): boolean;
192
229
  * positional.
193
230
  *
194
231
  * Only genuinely global flags belong here. Group-specific ones (`--bucket`,
195
- * `--region`, …) are declared by the handler that owns them and always follow
196
- * the group, so they cannot shift the group or action.
232
+ * `--region`, …) are declared by the handler that owns them. They can still
233
+ * precede the action — or stand in for it, on a group with a default — so the
234
+ * dispatcher also declares every one that takes a value: `CLOUD_VALUE_FLAGS`
235
+ * in `index.ts`.
197
236
  *
198
237
  * `-p` is `--project` in eighteen places and `--password` in `login`. That
199
238
  * ambiguity does not matter to the one caller that reads this spec: it resolves
@@ -0,0 +1,53 @@
1
+ import { type CloudClient } from "./context.js";
2
+ /** The control-plane function that mints runtime tokens. */
3
+ export declare const RUNTIME_TOKEN_FUNCTION = "runtime-token";
4
+ /** The one scope these commands ask the platform for. */
5
+ export declare const CRON_READ_SCOPE = "cron:read";
6
+ /** What `runtime-token` answers. */
7
+ export interface RuntimeTokenResponse {
8
+ /** `rpt_…` — the bearer the runtime accepts. */
9
+ token: string;
10
+ /** ISO timestamp; past it the runtime refuses the token. */
11
+ expiresAt?: string;
12
+ /** What the token was granted, which may be narrower than what was asked. */
13
+ scopes?: string[];
14
+ }
15
+ /**
16
+ * A 404 that is about the route, not the project: the JSON envelope a Rebase
17
+ * backend answers for an unmatched path, or the bare one a router answers
18
+ * before that handler exists.
19
+ */
20
+ export declare function isMissingRoute(message: string | undefined): boolean;
21
+ /**
22
+ * Ask the control plane for a token the project's runtime will accept.
23
+ *
24
+ * A missing route means this control plane has no `runtime-token` function
25
+ * yet, which is a different fix from "no such project" and is said so.
26
+ */
27
+ export declare function mintRuntimeToken(client: CloudClient, projectId: string, scopes: string[]): Promise<RuntimeTokenResponse>;
28
+ /**
29
+ * GET a path on the runtime with a platform token, and refuse — with what it
30
+ * means for this command — anything but a 2xx.
31
+ *
32
+ * `notFound` words the 404, which means different things per route: no cron
33
+ * surface at all on the list, no such job on its logs.
34
+ */
35
+ export declare function runtimeGet<T>(origin: string, path: string, token: string, notFound: {
36
+ message: string;
37
+ hint?: string;
38
+ code: string;
39
+ }): Promise<T>;
40
+ /** `2026-10-05T10:31:00.000Z` → `2026-10-05 10:31:00Z`, or `—`. */
41
+ export declare function shortTime(iso: string | undefined): string;
42
+ /** Milliseconds as `850ms`, `2.4s` or `3m 10s`. */
43
+ export declare function shortDuration(ms: number | undefined): string;
44
+ /** The flags `cron list` parses — the help page lists exactly these. */
45
+ export declare const CRON_LIST_FLAGS: {
46
+ "--host": StringConstructor;
47
+ };
48
+ /** The flags `cron logs` parses — the help page lists exactly these. */
49
+ export declare const CRON_LOGS_FLAGS: {
50
+ "--limit": NumberConstructor;
51
+ "--host": StringConstructor;
52
+ };
53
+ export declare function cronCommand(action: string | undefined, rawArgs: string[]): Promise<void>;