@rebasepro/cli 0.24.0 → 0.24.1-canary.g19596ef

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 (156) hide show
  1. package/bin/rebase.js +3 -0
  2. package/dist/agent-setup-B31F00DC.js +324 -0
  3. package/dist/agent-setup-B31F00DC.js.map +1 -0
  4. package/dist/api-keys-Bl1I9q7M.js +525 -0
  5. package/dist/api-keys-Bl1I9q7M.js.map +1 -0
  6. package/dist/apps-CNgQJjg5.js +340 -0
  7. package/dist/apps-CNgQJjg5.js.map +1 -0
  8. package/dist/args-BnmsEXvu.js +109 -0
  9. package/dist/args-BnmsEXvu.js.map +1 -0
  10. package/dist/atlas-dev-database-D_LP_Woq.js +62 -0
  11. package/dist/atlas-dev-database-D_LP_Woq.js.map +1 -0
  12. package/dist/auth-aySHEF45.js +414 -0
  13. package/dist/auth-aySHEF45.js.map +1 -0
  14. package/dist/branch-pointer-DvSHBjjz.js +2 -0
  15. package/dist/build-DIHWIqO4.js +336 -0
  16. package/dist/build-DIHWIqO4.js.map +1 -0
  17. package/dist/bundle-CqURVN-K.js +1621 -0
  18. package/dist/bundle-CqURVN-K.js.map +1 -0
  19. package/dist/bundle.d.ts +6 -1
  20. package/dist/cli.d.ts +2 -2
  21. package/dist/cloud-DjByQlkW.js +9667 -0
  22. package/dist/cloud-DjByQlkW.js.map +1 -0
  23. package/dist/collection-drift-BKj_BoMq.js +106 -0
  24. package/dist/collection-drift-BKj_BoMq.js.map +1 -0
  25. package/dist/commands/api-keys.d.ts +2 -0
  26. package/dist/commands/console.d.ts +12 -0
  27. package/dist/commands/db.d.ts +64 -24
  28. package/dist/commands/dev.d.ts +103 -6
  29. package/dist/commands/generate_sdk.d.ts +26 -0
  30. package/dist/commands/init.d.ts +58 -0
  31. package/dist/commands/skills.d.ts +22 -7
  32. package/dist/commands/start.d.ts +15 -0
  33. package/dist/commands/storage.d.ts +46 -0
  34. package/dist/commands/upgrade.d.ts +1 -0
  35. package/dist/consent-ClRHmcxf.js +76 -0
  36. package/dist/consent-ClRHmcxf.js.map +1 -0
  37. package/dist/console-D6SJf8k_.js +102 -0
  38. package/dist/console-D6SJf8k_.js.map +1 -0
  39. package/dist/context-BqhRydBg.js +1234 -0
  40. package/dist/context-BqhRydBg.js.map +1 -0
  41. package/dist/{daemon-entry-LTFKtpHy.js → daemon-entry-Da-D3rmH.js} +3 -4
  42. package/dist/daemon-entry-Da-D3rmH.js.map +1 -0
  43. package/dist/daemon-pzsQwDHa.js +2 -0
  44. package/dist/db-B7RuNuaQ.js +1312 -0
  45. package/dist/db-B7RuNuaQ.js.map +1 -0
  46. package/dist/derive-Dl0z2OWi.js +484 -0
  47. package/dist/derive-Dl0z2OWi.js.map +1 -0
  48. package/dist/dev-CYr_WXan.js +1599 -0
  49. package/dist/dev-CYr_WXan.js.map +1 -0
  50. package/dist/dev-db/atlas-dev-database.d.ts +32 -0
  51. package/dist/dev-db/daemon-entry.d.ts +13 -0
  52. package/dist/dev-db/last-dev-database.d.ts +41 -0
  53. package/dist/dev-db/prepare.d.ts +19 -3
  54. package/dist/dev-db/pull.d.ts +90 -5
  55. package/dist/dev-db/resolve.d.ts +26 -2
  56. package/dist/dev-preflight-B-LYyBf1.js +2 -0
  57. package/dist/dev-server-DG8Tt-uf.js +96 -0
  58. package/dist/dev-server-DG8Tt-uf.js.map +1 -0
  59. package/dist/doctor-BP8cZ-7F.js +771 -0
  60. package/dist/doctor-BP8cZ-7F.js.map +1 -0
  61. package/dist/eject-DizdoecV.js +335 -0
  62. package/dist/eject-DizdoecV.js.map +1 -0
  63. package/dist/fold-static-BC9CYicw.js +201 -0
  64. package/dist/fold-static-BC9CYicw.js.map +1 -0
  65. package/dist/function-portability-BIvlvR9q.js +265 -0
  66. package/dist/function-portability-BIvlvR9q.js.map +1 -0
  67. package/dist/generate_sdk-BPqdJc3Q.js +489 -0
  68. package/dist/generate_sdk-BPqdJc3Q.js.map +1 -0
  69. package/dist/index.es.js +151 -24674
  70. package/dist/index.es.js.map +1 -1
  71. package/dist/init-Utstvh2Q.js +1149 -0
  72. package/dist/init-Utstvh2Q.js.map +1 -0
  73. package/dist/last-dev-database-B58g89uA.js +2 -0
  74. package/dist/manifest-DRp0UVTj.js +880 -0
  75. package/dist/manifest-DRp0UVTj.js.map +1 -0
  76. package/dist/manifest.d.ts +15 -3
  77. package/dist/normalize-imports-X0Tgze9y.js +107 -0
  78. package/dist/normalize-imports-X0Tgze9y.js.map +1 -0
  79. package/dist/{package-manager-CXQevsE1.js → package-manager-DSEOwTqM.js} +2 -2
  80. package/dist/{package-manager-CXQevsE1.js.map → package-manager-DSEOwTqM.js.map} +1 -1
  81. package/dist/path-flags-BFgG9V6y.js +91 -0
  82. package/dist/path-flags-BFgG9V6y.js.map +1 -0
  83. package/dist/precompress.d.ts +17 -0
  84. package/dist/prepare-CDN6lSpz.js +1236 -0
  85. package/dist/prepare-CDN6lSpz.js.map +1 -0
  86. package/dist/{project-DmaGLmH2.js → project-Wp2zoyeN.js} +33 -4
  87. package/dist/project-Wp2zoyeN.js.map +1 -0
  88. package/dist/pull-CrGYMEsy.js +458 -0
  89. package/dist/pull-CrGYMEsy.js.map +1 -0
  90. package/dist/resolve-B2O-wKKk.js +2 -0
  91. package/dist/resources-FD7AfZx8.js +183 -0
  92. package/dist/resources-FD7AfZx8.js.map +1 -0
  93. package/dist/schema-DMdr431S.js +125 -0
  94. package/dist/schema-DMdr431S.js.map +1 -0
  95. package/dist/skills-DTFibT1m.js +642 -0
  96. package/dist/skills-DTFibT1m.js.map +1 -0
  97. package/dist/start-DEa-hOBh.js +267 -0
  98. package/dist/start-DEa-hOBh.js.map +1 -0
  99. package/dist/{state-C59Elrnt.js → state-Do7ZJYkF.js} +49 -4
  100. package/dist/state-Do7ZJYkF.js.map +1 -0
  101. package/dist/status-DxnJTekv.js +352 -0
  102. package/dist/status-DxnJTekv.js.map +1 -0
  103. package/dist/storage-DyVq-f_F.js +303 -0
  104. package/dist/storage-DyVq-f_F.js.map +1 -0
  105. package/dist/telemetry/identity.d.ts +10 -1
  106. package/dist/telemetry-C8Uq8phb.js +129 -0
  107. package/dist/telemetry-C8Uq8phb.js.map +1 -0
  108. package/dist/telemetry-EMFRVRQi.js +351 -0
  109. package/dist/telemetry-EMFRVRQi.js.map +1 -0
  110. package/dist/unknown-command-DNwDcX3w.js +98 -0
  111. package/dist/unknown-command-DNwDcX3w.js.map +1 -0
  112. package/dist/upgrade-CtZtRkTE.js +1332 -0
  113. package/dist/upgrade-CtZtRkTE.js.map +1 -0
  114. package/dist/upgrade.d.ts +24 -3
  115. package/dist/utils/dev-preflight.d.ts +47 -5
  116. package/dist/utils/dev-server.d.ts +30 -0
  117. package/dist/utils/path-flags.d.ts +15 -2
  118. package/dist/utils/project.d.ts +16 -0
  119. package/dist/utils/temp-archive.d.ts +9 -0
  120. package/dist/{version-DsgBmP22.js → version-Buyyo1ut.js} +2 -2
  121. package/dist/{version-DsgBmP22.js.map → version-Buyyo1ut.js.map} +1 -1
  122. package/package.json +7 -7
  123. package/templates/eject/Dockerfile +4 -2
  124. package/templates/eject/backend/src/env.ts +1 -1
  125. package/templates/eject/backend/src/index.ts +29 -4
  126. package/templates/eject/docker-compose.custom.yml +8 -4
  127. package/templates/generated-schemas/blank.ts +40 -0
  128. package/templates/generated-schemas/blog.ts +127 -0
  129. package/templates/generated-schemas/ecommerce.ts +93 -0
  130. package/templates/overlays/baas/config/package.json +1 -0
  131. package/templates/overlays/baas/package.json +1 -0
  132. package/templates/template/.env.example +10 -4
  133. package/templates/template/README.md +11 -4
  134. package/templates/template/ai-instructions.md +3 -2
  135. package/templates/template/config/resources.ts +7 -6
  136. package/templates/template/docker-compose.yml +9 -3
  137. package/templates/template/frontend/vite.config.ts +13 -3
  138. package/templates/template/package.json +1 -0
  139. package/templates/template/scripts/example.ts +2 -1
  140. package/templates/template/tsconfig.json +25 -0
  141. package/dist/branch-pointer-kk9F5FBO.js +0 -111
  142. package/dist/branch-pointer-kk9F5FBO.js.map +0 -1
  143. package/dist/constraints-DKGbNfUW.js +0 -48
  144. package/dist/constraints-DKGbNfUW.js.map +0 -1
  145. package/dist/daemon-C8p32i-n.js +0 -357
  146. package/dist/daemon-C8p32i-n.js.map +0 -1
  147. package/dist/daemon-entry-LTFKtpHy.js.map +0 -1
  148. package/dist/dev-preflight-CNLl4rdo.js +0 -367
  149. package/dist/dev-preflight-CNLl4rdo.js.map +0 -1
  150. package/dist/project-DmaGLmH2.js.map +0 -1
  151. package/dist/pull-Dywm5FWP.js +0 -232
  152. package/dist/pull-Dywm5FWP.js.map +0 -1
  153. package/dist/resolve-BAeRUBhg.js +0 -74
  154. package/dist/resolve-BAeRUBhg.js.map +0 -1
  155. package/dist/state-C59Elrnt.js.map +0 -1
  156. package/templates/template/backend/src/schema.generated.ts +0 -13
package/bin/rebase.js CHANGED
@@ -192,6 +192,9 @@ const { entry } = await import("../dist/index.es.js");
192
192
  // commands spell it: `wantsRawError` in `commands/cloud/errors.ts`.
193
193
  const { parseEnvBoolean } = await import("@rebasepro/types");
194
194
  const wantsStack = process.argv.includes("--debug") || parseEnvBoolean(process.env.REBASE_DEBUG) === true;
195
+ // Down to the driver too: `db`, `schema` and `doctor` run in a child process
196
+ // that prints its own failures, and it reads the same variable.
197
+ if (wantsStack) process.env.REBASE_DEBUG = "1";
195
198
 
196
199
  entry(process.argv).catch((error) => {
197
200
  const message = error instanceof Error ? error.message : String(error);
@@ -0,0 +1,324 @@
1
+ import { t as detectPackageManager } from "./package-manager-DSEOwTqM.js";
2
+ import { n as cliVersion } from "./version-Buyyo1ut.js";
3
+ import { AGENTS, AGENT_KEYS, detectInstalledAgents, installSkills, loadBundledSkills } from "./skills-DTFibT1m.js";
4
+ import chalk from "chalk";
5
+ import fs from "fs";
6
+ import path from "path";
7
+ import inquirer from "inquirer";
8
+ //#region src/commands/agent-setup.ts
9
+ /**
10
+ * Setting a project up for the AI coding assistants a developer uses: the
11
+ * Rebase skills, and the Rebase MCP server in each assistant's own config.
12
+ *
13
+ * `rebase init` used to end by *printing* `rebase skills install`, and nothing
14
+ * ran it — so a generated project had pointer files telling every assistant to
15
+ * read skills that were not there, and an MCP server only Claude Code knew
16
+ * about. This asks once, while the project is being made, pre-ticking the
17
+ * assistants installed on the machine.
18
+ */
19
+ /** The name the server is registered under, in every config. */
20
+ var MCP_SERVER_NAME = "rebase";
21
+ /** The MCP server's package: a devDependency of the project, pinned with the rest. */
22
+ var MCP_PACKAGE = "@rebasepro/mcp";
23
+ /** The bin {@link MCP_PACKAGE} declares. */
24
+ var MCP_BIN = "rebase-mcp";
25
+ /**
26
+ * How an assistant starts the Rebase MCP server: the project's own copy, through
27
+ * the project's package manager.
28
+ *
29
+ * Not `npx -y @rebasepro/mcp`, which fetched the newest release on every first
30
+ * start. The server drives the project's own CLI (`pnpm exec rebase …`) and calls
31
+ * the project's own backend (`/api/admin/schema/plan`, …), whose versions the
32
+ * lockfile pins — so a server from the registry ran ahead of both, at every
33
+ * start, and downloaded before it could answer. `@rebasepro/mcp` is a
34
+ * devDependency of the scaffold, pinned to the CLI's version like every other
35
+ * `@rebasepro` package, and this runs that copy.
36
+ *
37
+ * `npx --no`, not `npx`: an assistant spawns the server with no TTY, and npx
38
+ * then assumes "yes" and installs a missing package from the registry under the
39
+ * name it was given. `--no` makes a missing install an error instead.
40
+ */
41
+ function mcpLaunch(pm) {
42
+ return pm === "npm" ? {
43
+ command: "npx",
44
+ args: ["--no", MCP_BIN]
45
+ } : {
46
+ command: "pnpm",
47
+ args: ["exec", MCP_BIN]
48
+ };
49
+ }
50
+ function isRecord(value) {
51
+ return typeof value === "object" && value !== null && !Array.isArray(value);
52
+ }
53
+ /**
54
+ * Add the server to a JSON config under `key`, keeping everything else in it.
55
+ *
56
+ * A file that does not parse as plain JSON is left alone: VS Code and Gemini
57
+ * both accept comments in these files, and rewriting one through
58
+ * `JSON.stringify` would delete them. Refusing costs one line of hand-editing;
59
+ * the alternative silently costs the developer theirs.
60
+ */
61
+ function addJsonServer(filePath, key, entry) {
62
+ let doc = {};
63
+ if (fs.existsSync(filePath)) {
64
+ let parsed;
65
+ try {
66
+ parsed = JSON.parse(fs.readFileSync(filePath, "utf-8"));
67
+ } catch {
68
+ return "unreadable";
69
+ }
70
+ if (!isRecord(parsed)) return "unreadable";
71
+ doc = parsed;
72
+ }
73
+ const servers = doc[key] ?? {};
74
+ if (!isRecord(servers)) return "unreadable";
75
+ if ("rebase" in servers) return "present";
76
+ doc[key] = {
77
+ ...servers,
78
+ [MCP_SERVER_NAME]: entry
79
+ };
80
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
81
+ fs.writeFileSync(filePath, `${JSON.stringify(doc, null, 2)}\n`, "utf-8");
82
+ return "added";
83
+ }
84
+ /**
85
+ * The Codex block, as TOML. Appended rather than merged: there is no TOML
86
+ * parser here, and an append keeps every byte already in the file.
87
+ */
88
+ function renderCodexServer(projectDir, launch) {
89
+ const str = (v) => JSON.stringify(v);
90
+ return [
91
+ `[mcp_servers.${MCP_SERVER_NAME}]`,
92
+ `command = ${str(launch.command)}`,
93
+ `args = [${launch.args.map(str).join(", ")}]`,
94
+ "",
95
+ `[mcp_servers.${MCP_SERVER_NAME}.env]`,
96
+ `REBASE_PROJECT_DIR = ${str(projectDir)}`,
97
+ ""
98
+ ].join("\n");
99
+ }
100
+ function addCodexServer(filePath, projectDir, launch) {
101
+ const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf-8") : "";
102
+ if (new RegExp(`^\\s*\\[mcp_servers\\.(?:rebase|"rebase")\\]`, "m").test(existing)) return "present";
103
+ const separator = existing === "" ? "" : existing.endsWith("\n") ? "\n" : "\n\n";
104
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
105
+ fs.writeFileSync(filePath, `${existing}${separator}${renderCodexServer(projectDir, launch)}`, "utf-8");
106
+ return "added";
107
+ }
108
+ /**
109
+ * Register the Rebase MCP server in the agent's project-level config, started
110
+ * through the project's package manager (see {@link mcpLaunch}).
111
+ *
112
+ * Returns null for an agent with no project-level config to write.
113
+ */
114
+ function writeMcpConfig(agentKey, projectDir, pm = detectPackageManager(projectDir)) {
115
+ const mcp = AGENTS[agentKey].mcp;
116
+ if (!mcp) return null;
117
+ const filePath = path.join(projectDir, mcp.file);
118
+ const env = { REBASE_PROJECT_DIR: mcp.projectDir };
119
+ const { command, args } = mcpLaunch(pm);
120
+ const write = () => {
121
+ switch (mcp.format) {
122
+ case "mcpServers": return addJsonServer(filePath, "mcpServers", {
123
+ command,
124
+ args,
125
+ env
126
+ });
127
+ case "vscode": return addJsonServer(filePath, "servers", {
128
+ type: "stdio",
129
+ command,
130
+ args,
131
+ env
132
+ });
133
+ case "codexToml": return addCodexServer(filePath, mcp.projectDir, {
134
+ command,
135
+ args
136
+ });
137
+ }
138
+ };
139
+ return {
140
+ file: mcp.file,
141
+ status: write()
142
+ };
143
+ }
144
+ /**
145
+ * Make the project depend on {@link MCP_PACKAGE}, which the config written by
146
+ * {@link writeMcpConfig} runs from the project's own install.
147
+ *
148
+ * Pinned to this CLI's version, as `rebase init` pins every `@rebasepro`
149
+ * package; a project that already lists it keeps its own choice.
150
+ */
151
+ function ensureMcpDependency(projectDir) {
152
+ const manifestPath = path.join(projectDir, "package.json");
153
+ if (!fs.existsSync(manifestPath)) return "unreadable";
154
+ const text = fs.readFileSync(manifestPath, "utf-8");
155
+ let manifest;
156
+ try {
157
+ manifest = JSON.parse(text);
158
+ } catch {
159
+ return "unreadable";
160
+ }
161
+ if (!isRecord(manifest)) return "unreadable";
162
+ for (const field of ["dependencies", "devDependencies"]) {
163
+ const deps = manifest[field];
164
+ if (isRecord(deps) && "@rebasepro/mcp" in deps) return "present";
165
+ }
166
+ const devDependencies = isRecord(manifest.devDependencies) ? manifest.devDependencies : {};
167
+ const version = cliVersion();
168
+ manifest.devDependencies = {
169
+ ...devDependencies,
170
+ [MCP_PACKAGE]: version === "unknown" ? "latest" : version
171
+ };
172
+ const indent = /\n([ \t]+)"/.exec(text)?.[1] ?? " ";
173
+ fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, indent)}\n`, "utf-8");
174
+ return "added";
175
+ }
176
+ /**
177
+ * Point the scaffold's `.mcp.json` at the project's package manager.
178
+ *
179
+ * The template ships the pnpm spelling (`pnpm exec rebase-mcp`); an npm project
180
+ * has no pnpm to run it with. Only the entry the template wrote is rewritten.
181
+ */
182
+ function retargetScaffoldMcpConfig(projectDir, pm) {
183
+ const filePath = path.join(projectDir, ".mcp.json");
184
+ if (!fs.existsSync(filePath)) return;
185
+ let doc;
186
+ try {
187
+ doc = JSON.parse(fs.readFileSync(filePath, "utf-8"));
188
+ } catch {
189
+ return;
190
+ }
191
+ const servers = isRecord(doc) ? doc.mcpServers : void 0;
192
+ const entry = isRecord(servers) ? servers[MCP_SERVER_NAME] : void 0;
193
+ const shipped = mcpLaunch("pnpm");
194
+ if (!isRecord(doc) || !isRecord(servers) || !isRecord(entry)) return;
195
+ if (entry.command !== shipped.command || JSON.stringify(entry.args) !== JSON.stringify(shipped.args)) return;
196
+ const wanted = mcpLaunch(pm);
197
+ if (wanted.command === shipped.command && JSON.stringify(wanted.args) === JSON.stringify(shipped.args)) return;
198
+ servers[MCP_SERVER_NAME] = {
199
+ ...entry,
200
+ command: wanted.command,
201
+ args: wanted.args
202
+ };
203
+ fs.writeFileSync(filePath, `${JSON.stringify(doc, null, 4)}\n`, "utf-8");
204
+ }
205
+ /**
206
+ * Whether the agent's project-level config already registers the Rebase
207
+ * server: `null` for an agent that has no such config, `false` when the file
208
+ * is missing or does not name it. Reads only — for the hint `rebase skills
209
+ * install` prints when it was not asked to write one.
210
+ */
211
+ function mcpServerRegistered(agentKey, projectDir) {
212
+ const mcp = AGENTS[agentKey].mcp;
213
+ if (!mcp) return null;
214
+ const filePath = path.join(projectDir, mcp.file);
215
+ if (!fs.existsSync(filePath)) return false;
216
+ const text = fs.readFileSync(filePath, "utf-8");
217
+ if (mcp.format === "codexToml") return new RegExp(`^\\s*\\[mcp_servers\\.(?:${MCP_SERVER_NAME}|"${MCP_SERVER_NAME}")\\]`, "m").test(text);
218
+ try {
219
+ const doc = JSON.parse(text);
220
+ const servers = isRecord(doc) ? doc[mcp.format === "vscode" ? "servers" : "mcpServers"] : void 0;
221
+ return isRecord(servers) && "rebase" in servers;
222
+ } catch {
223
+ return null;
224
+ }
225
+ }
226
+ /**
227
+ * Install the skills and register the MCP server for each agent.
228
+ *
229
+ * Never throws for a missing skills bundle — the scaffold it runs inside must
230
+ * not fail over its assistants — and reports it as `skills: null` instead.
231
+ */
232
+ function configureAgents(agents, projectDir, load = loadBundledSkills, pm = detectPackageManager(projectDir)) {
233
+ let skillsError;
234
+ let installed = [];
235
+ try {
236
+ installed = installSkills(agents, load(), projectDir);
237
+ } catch (err) {
238
+ skillsError = err instanceof Error ? err.message : String(err);
239
+ }
240
+ const results = agents.map((agent) => {
241
+ const skills = installed.find((r) => r.agent === agent);
242
+ return {
243
+ agent,
244
+ skills: skills ? skills.skills : null,
245
+ sharedWith: skills?.sharedWith,
246
+ mcp: writeMcpConfig(agent, projectDir, pm)
247
+ };
248
+ });
249
+ const registered = results.some((r) => r.mcp?.status === "added" || r.mcp?.status === "present");
250
+ return {
251
+ results,
252
+ skillsError,
253
+ ...registered && { mcpDependency: ensureMcpDependency(projectDir) }
254
+ };
255
+ }
256
+ /** The line to print when {@link ensureMcpDependency} changed or could not change the manifest. */
257
+ function mcpDependencyNote(status, pm) {
258
+ if (status === "added") return `Added ${MCP_PACKAGE} to devDependencies — run \`${pm} install\` before your assistant starts it.`;
259
+ if (status === "unreadable") return `Could not add ${MCP_PACKAGE} to package.json — add it to devDependencies by hand; the MCP config runs the project's own copy.`;
260
+ }
261
+ /** One line per agent, for the scaffold's output. */
262
+ function printAgentSetup({ results, skillsError, mcpDependency }, pm = "pnpm") {
263
+ for (const result of results) {
264
+ const agent = AGENTS[result.agent];
265
+ const parts = [];
266
+ if (result.sharedWith) parts.push(`skills in ${chalk.gray(agent.targetDir)} ${chalk.gray(`(shared with ${AGENTS[result.sharedWith].label})`)}`);
267
+ else if (result.skills !== null) parts.push(`${result.skills} skills in ${chalk.gray(agent.targetDir)}`);
268
+ if (result.mcp?.status === "added") parts.push(`MCP server in ${chalk.gray(result.mcp.file)}`);
269
+ else if (result.mcp?.status === "present") parts.push(`MCP server already in ${chalk.gray(result.mcp.file)}`);
270
+ const mark = parts.length ? chalk.green("✓") : chalk.yellow("!");
271
+ console.log(` ${mark} ${chalk.bold(agent.label)}${parts.length ? ` — ${parts.join(", ")}` : ""}`);
272
+ if (result.mcp?.status === "unreadable") console.log(chalk.yellow(` ${result.mcp.file} is not plain JSON, so it was left alone — add the "${MCP_SERVER_NAME}" server by hand.`));
273
+ else if (!result.mcp) console.log(chalk.gray(` ${agent.label} has no project-level MCP config — add @rebasepro/mcp in its MCP settings.`));
274
+ }
275
+ const dependencyNote = mcpDependencyNote(mcpDependency, pm);
276
+ if (dependencyNote) console.log(chalk.gray(` ${dependencyNote}`));
277
+ if (skillsError) {
278
+ console.log(chalk.yellow(` Could not install the Rebase skills: ${skillsError}`));
279
+ console.log(chalk.yellow(" Run `rebase skills install` in the project once dependencies are installed."));
280
+ }
281
+ }
282
+ /**
283
+ * Ask whether to set up AI agents, then which, pre-ticking what is installed.
284
+ *
285
+ * Interactive only; the caller has already refused a non-TTY. Returns [] when
286
+ * the developer says no or unticks everything.
287
+ */
288
+ async function promptForAgents(home) {
289
+ const { configure } = await inquirer.prompt([{
290
+ type: "confirm",
291
+ name: "configure",
292
+ message: "Set up Rebase skills and the Rebase MCP server for your AI coding agent(s)?",
293
+ default: true
294
+ }]);
295
+ if (!configure) return [];
296
+ const detected = detectInstalledAgents(home);
297
+ const installed = [...detected.filter((a) => a.found), ...detected.filter((a) => !a.found)];
298
+ console.log("");
299
+ console.log("Detecting installed AI coding agents...");
300
+ for (const { label, marker, found } of installed) if (found) console.log(` ${chalk.green("✓")} ${label} — ${marker}`);
301
+ else if (marker) console.log(chalk.gray(` ✗ ${label} — ${marker} (not found)`));
302
+ else console.log(chalk.gray(` · ${label} — can't be detected; tick it below if you use it`));
303
+ console.log("");
304
+ const { selectedAgents } = await inquirer.prompt([{
305
+ type: "checkbox",
306
+ name: "selectedAgents",
307
+ message: "Select agents to configure:",
308
+ choices: installed.map(({ key, label, found }) => {
309
+ const { targetDir, mcp } = AGENTS[key];
310
+ const writes = mcp ? `${targetDir} + ${mcp.file}` : targetDir;
311
+ return {
312
+ name: `${label} ${chalk.gray(`— ${writes}`)}`,
313
+ short: label,
314
+ value: key,
315
+ checked: found
316
+ };
317
+ })
318
+ }]);
319
+ return AGENT_KEYS.filter((key) => selectedAgents.includes(key));
320
+ }
321
+ //#endregion
322
+ export { MCP_SERVER_NAME, configureAgents, ensureMcpDependency, mcpDependencyNote, mcpServerRegistered, printAgentSetup, promptForAgents, retargetScaffoldMcpConfig, writeMcpConfig };
323
+
324
+ //# sourceMappingURL=agent-setup-B31F00DC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-setup-B31F00DC.js","names":[],"sources":["../src/commands/agent-setup.ts"],"sourcesContent":["/**\n * Setting a project up for the AI coding assistants a developer uses: the\n * Rebase skills, and the Rebase MCP server in each assistant's own config.\n *\n * `rebase init` used to end by *printing* `rebase skills install`, and nothing\n * ran it — so a generated project had pointer files telling every assistant to\n * read skills that were not there, and an MCP server only Claude Code knew\n * about. This asks once, while the project is being made, pre-ticking the\n * assistants installed on the machine.\n */\nimport chalk from \"chalk\";\nimport fs from \"fs\";\nimport path from \"path\";\nimport inquirer from \"inquirer\";\nimport {\n AGENT_KEYS,\n AGENTS,\n type AgentKey,\n detectInstalledAgents,\n installSkills,\n type LoadedSkill,\n loadBundledSkills\n} from \"./skills\";\nimport { detectPackageManager, type PackageManager } from \"../utils/package-manager\";\nimport { cliVersion } from \"../utils/version\";\n\n/** The name the server is registered under, in every config. */\nexport const MCP_SERVER_NAME = \"rebase\";\n\n/** The MCP server's package: a devDependency of the project, pinned with the rest. */\nexport const MCP_PACKAGE = \"@rebasepro/mcp\";\n\n/** The bin {@link MCP_PACKAGE} declares. */\nexport const MCP_BIN = \"rebase-mcp\";\n\n/** The command an assistant spawns, and its arguments. */\nexport interface McpLaunch {\n command: string;\n args: string[];\n}\n\n/**\n * How an assistant starts the Rebase MCP server: the project's own copy, through\n * the project's package manager.\n *\n * Not `npx -y @rebasepro/mcp`, which fetched the newest release on every first\n * start. The server drives the project's own CLI (`pnpm exec rebase …`) and calls\n * the project's own backend (`/api/admin/schema/plan`, …), whose versions the\n * lockfile pins — so a server from the registry ran ahead of both, at every\n * start, and downloaded before it could answer. `@rebasepro/mcp` is a\n * devDependency of the scaffold, pinned to the CLI's version like every other\n * `@rebasepro` package, and this runs that copy.\n *\n * `npx --no`, not `npx`: an assistant spawns the server with no TTY, and npx\n * then assumes \"yes\" and installs a missing package from the registry under the\n * name it was given. `--no` makes a missing install an error instead.\n */\nexport function mcpLaunch(pm: PackageManager): McpLaunch {\n return pm === \"npm\"\n ? { command: \"npx\", args: [\"--no\", MCP_BIN] }\n : { command: \"pnpm\", args: [\"exec\", MCP_BIN] };\n}\n\n/** What writing one MCP config did. */\nexport type McpWriteStatus =\n /** The file was created, or the server was added beside the ones in it. */\n | \"added\"\n /** A `rebase` server was already there. It is left exactly as it was. */\n | \"present\"\n /** The file exists but is not something this can edit without losing data. */\n | \"unreadable\";\n\nexport interface McpWriteResult {\n /** Project-relative path of the config file. */\n file: string;\n status: McpWriteStatus;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Add the server to a JSON config under `key`, keeping everything else in it.\n *\n * A file that does not parse as plain JSON is left alone: VS Code and Gemini\n * both accept comments in these files, and rewriting one through\n * `JSON.stringify` would delete them. Refusing costs one line of hand-editing;\n * the alternative silently costs the developer theirs.\n */\nfunction addJsonServer(filePath: string, key: string, entry: Record<string, unknown>): McpWriteStatus {\n let doc: Record<string, unknown> = {};\n if (fs.existsSync(filePath)) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n } catch {\n return \"unreadable\";\n }\n if (!isRecord(parsed)) return \"unreadable\";\n doc = parsed;\n }\n\n const servers = doc[key] ?? {};\n if (!isRecord(servers)) return \"unreadable\";\n if (MCP_SERVER_NAME in servers) return \"present\";\n\n doc[key] = { ...servers, [MCP_SERVER_NAME]: entry };\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, `${JSON.stringify(doc, null, 2)}\\n`, \"utf-8\");\n return \"added\";\n}\n\n/**\n * The Codex block, as TOML. Appended rather than merged: there is no TOML\n * parser here, and an append keeps every byte already in the file.\n */\nexport function renderCodexServer(projectDir: string, launch: McpLaunch): string {\n // A JSON string literal is a valid TOML basic string for these values.\n const str = (v: string) => JSON.stringify(v);\n return [\n `[mcp_servers.${MCP_SERVER_NAME}]`,\n `command = ${str(launch.command)}`,\n `args = [${launch.args.map(str).join(\", \")}]`,\n \"\",\n `[mcp_servers.${MCP_SERVER_NAME}.env]`,\n `REBASE_PROJECT_DIR = ${str(projectDir)}`,\n \"\"\n ].join(\"\\n\");\n}\n\nfunction addCodexServer(filePath: string, projectDir: string, launch: McpLaunch): McpWriteStatus {\n const existing = fs.existsSync(filePath) ? fs.readFileSync(filePath, \"utf-8\") : \"\";\n const table = new RegExp(`^\\\\s*\\\\[mcp_servers\\\\.(?:${MCP_SERVER_NAME}|\"${MCP_SERVER_NAME}\")\\\\]`, \"m\");\n if (table.test(existing)) return \"present\";\n\n const separator = existing === \"\" ? \"\" : existing.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\n fs.mkdirSync(path.dirname(filePath), { recursive: true });\n fs.writeFileSync(filePath, `${existing}${separator}${renderCodexServer(projectDir, launch)}`, \"utf-8\");\n return \"added\";\n}\n\n/**\n * Register the Rebase MCP server in the agent's project-level config, started\n * through the project's package manager (see {@link mcpLaunch}).\n *\n * Returns null for an agent with no project-level config to write.\n */\nexport function writeMcpConfig(\n agentKey: AgentKey,\n projectDir: string,\n pm: PackageManager = detectPackageManager(projectDir)\n): McpWriteResult | null {\n const mcp = AGENTS[agentKey].mcp;\n if (!mcp) return null;\n\n const filePath = path.join(projectDir, mcp.file);\n const env = { REBASE_PROJECT_DIR: mcp.projectDir };\n const { command, args } = mcpLaunch(pm);\n const write = (): McpWriteStatus => {\n switch (mcp.format) {\n case \"mcpServers\":\n return addJsonServer(filePath, \"mcpServers\", { command, args, env });\n case \"vscode\":\n // VS Code's own shape: `servers`, and an explicit transport.\n return addJsonServer(filePath, \"servers\", { type: \"stdio\", command, args, env });\n case \"codexToml\":\n return addCodexServer(filePath, mcp.projectDir, { command, args });\n }\n };\n return { file: mcp.file, status: write() };\n}\n\n/** What making sure the project depends on the MCP server did. */\nexport type McpDependencyStatus =\n /** Added to `devDependencies`, at this CLI's version: an install is due. */\n | \"added\"\n /** Already a dependency. Left at the version the project chose. */\n | \"present\"\n /** No `package.json`, or one that is not plain JSON: left alone. */\n | \"unreadable\";\n\n/**\n * Make the project depend on {@link MCP_PACKAGE}, which the config written by\n * {@link writeMcpConfig} runs from the project's own install.\n *\n * Pinned to this CLI's version, as `rebase init` pins every `@rebasepro`\n * package; a project that already lists it keeps its own choice.\n */\nexport function ensureMcpDependency(projectDir: string): McpDependencyStatus {\n const manifestPath = path.join(projectDir, \"package.json\");\n if (!fs.existsSync(manifestPath)) return \"unreadable\";\n const text = fs.readFileSync(manifestPath, \"utf-8\");\n let manifest: unknown;\n try {\n manifest = JSON.parse(text);\n } catch {\n return \"unreadable\";\n }\n if (!isRecord(manifest)) return \"unreadable\";\n for (const field of [\"dependencies\", \"devDependencies\"] as const) {\n const deps = manifest[field];\n if (isRecord(deps) && MCP_PACKAGE in deps) return \"present\";\n }\n const devDependencies = isRecord(manifest.devDependencies) ? manifest.devDependencies : {};\n const version = cliVersion();\n manifest.devDependencies = { ...devDependencies, [MCP_PACKAGE]: version === \"unknown\" ? \"latest\" : version };\n // The file's own indentation, so the change is one line in a diff.\n const indent = /\\n([ \\t]+)\"/.exec(text)?.[1] ?? \" \";\n fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, indent)}\\n`, \"utf-8\");\n return \"added\";\n}\n\n/**\n * Point the scaffold's `.mcp.json` at the project's package manager.\n *\n * The template ships the pnpm spelling (`pnpm exec rebase-mcp`); an npm project\n * has no pnpm to run it with. Only the entry the template wrote is rewritten.\n */\nexport function retargetScaffoldMcpConfig(projectDir: string, pm: PackageManager): void {\n const filePath = path.join(projectDir, \".mcp.json\");\n if (!fs.existsSync(filePath)) return;\n let doc: unknown;\n try {\n doc = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n } catch {\n return;\n }\n const servers = isRecord(doc) ? doc.mcpServers : undefined;\n const entry = isRecord(servers) ? servers[MCP_SERVER_NAME] : undefined;\n const shipped = mcpLaunch(\"pnpm\");\n if (!isRecord(doc) || !isRecord(servers) || !isRecord(entry)) return;\n if (entry.command !== shipped.command || JSON.stringify(entry.args) !== JSON.stringify(shipped.args)) return;\n const wanted = mcpLaunch(pm);\n if (wanted.command === shipped.command && JSON.stringify(wanted.args) === JSON.stringify(shipped.args)) return;\n servers[MCP_SERVER_NAME] = { ...entry, command: wanted.command, args: wanted.args };\n fs.writeFileSync(filePath, `${JSON.stringify(doc, null, 4)}\\n`, \"utf-8\");\n}\n\n/**\n * Whether the agent's project-level config already registers the Rebase\n * server: `null` for an agent that has no such config, `false` when the file\n * is missing or does not name it. Reads only — for the hint `rebase skills\n * install` prints when it was not asked to write one.\n */\nexport function mcpServerRegistered(agentKey: AgentKey, projectDir: string): boolean | null {\n const mcp = AGENTS[agentKey].mcp;\n if (!mcp) return null;\n const filePath = path.join(projectDir, mcp.file);\n if (!fs.existsSync(filePath)) return false;\n const text = fs.readFileSync(filePath, \"utf-8\");\n if (mcp.format === \"codexToml\") {\n return new RegExp(`^\\\\s*\\\\[mcp_servers\\\\.(?:${MCP_SERVER_NAME}|\"${MCP_SERVER_NAME}\")\\\\]`, \"m\").test(text);\n }\n try {\n const doc: unknown = JSON.parse(text);\n const servers = isRecord(doc) ? doc[mcp.format === \"vscode\" ? \"servers\" : \"mcpServers\"] : undefined;\n return isRecord(servers) && MCP_SERVER_NAME in servers;\n } catch {\n // Not plain JSON (comments): cannot tell, so do not nag.\n return null;\n }\n}\n\n/** What `configureAgents` did for one agent. */\nexport interface AgentSetupResult {\n agent: AgentKey;\n /** Skills written, or null when the bundle could not be loaded. */\n skills: number | null;\n /** An earlier agent in the same run that already wrote the skills directory. */\n sharedWith?: AgentKey;\n mcp: McpWriteResult | null;\n}\n\n/**\n * Install the skills and register the MCP server for each agent.\n *\n * Never throws for a missing skills bundle — the scaffold it runs inside must\n * not fail over its assistants — and reports it as `skills: null` instead.\n */\nexport function configureAgents(\n agents: readonly AgentKey[],\n projectDir: string,\n load: () => LoadedSkill[] = loadBundledSkills,\n pm: PackageManager = detectPackageManager(projectDir)\n): { results: AgentSetupResult[]; skillsError?: string; mcpDependency?: McpDependencyStatus } {\n let skillsError: string | undefined;\n let installed: ReturnType<typeof installSkills> = [];\n try {\n installed = installSkills(agents, load(), projectDir);\n } catch (err) {\n skillsError = err instanceof Error ? err.message : String(err);\n }\n\n const results = agents.map((agent): AgentSetupResult => {\n const skills = installed.find(r => r.agent === agent);\n return {\n agent,\n skills: skills ? skills.skills : null,\n sharedWith: skills?.sharedWith,\n mcp: writeMcpConfig(agent, projectDir, pm)\n };\n });\n // A config that runs the project's copy of the server needs the project to\n // have one.\n const registered = results.some(r => r.mcp?.status === \"added\" || r.mcp?.status === \"present\");\n return { results, skillsError, ...(registered && { mcpDependency: ensureMcpDependency(projectDir) }) };\n}\n\n/** The line to print when {@link ensureMcpDependency} changed or could not change the manifest. */\nexport function mcpDependencyNote(status: McpDependencyStatus | undefined, pm: PackageManager): string | undefined {\n if (status === \"added\") {\n return `Added ${MCP_PACKAGE} to devDependencies — run \\`${pm} install\\` before your assistant starts it.`;\n }\n if (status === \"unreadable\") {\n return `Could not add ${MCP_PACKAGE} to package.json — add it to devDependencies by hand; the MCP config runs the project's own copy.`;\n }\n return undefined;\n}\n\n/** One line per agent, for the scaffold's output. */\nexport function printAgentSetup(\n { results, skillsError, mcpDependency }: ReturnType<typeof configureAgents>,\n pm: PackageManager = \"pnpm\"\n): void {\n for (const result of results) {\n const agent = AGENTS[result.agent];\n const parts: string[] = [];\n\n if (result.sharedWith) {\n parts.push(`skills in ${chalk.gray(agent.targetDir)} ${chalk.gray(`(shared with ${AGENTS[result.sharedWith].label})`)}`);\n } else if (result.skills !== null) {\n parts.push(`${result.skills} skills in ${chalk.gray(agent.targetDir)}`);\n }\n\n if (result.mcp?.status === \"added\") {\n parts.push(`MCP server in ${chalk.gray(result.mcp.file)}`);\n } else if (result.mcp?.status === \"present\") {\n parts.push(`MCP server already in ${chalk.gray(result.mcp.file)}`);\n }\n\n // A tick is a claim that something was written; with nothing, it isn't.\n const mark = parts.length ? chalk.green(\"✓\") : chalk.yellow(\"!\");\n console.log(` ${mark} ${chalk.bold(agent.label)}${parts.length ? ` — ${parts.join(\", \")}` : \"\"}`);\n\n if (result.mcp?.status === \"unreadable\") {\n console.log(chalk.yellow(` ${result.mcp.file} is not plain JSON, so it was left alone — add the \"${MCP_SERVER_NAME}\" server by hand.`));\n } else if (!result.mcp) {\n console.log(chalk.gray(` ${agent.label} has no project-level MCP config — add @rebasepro/mcp in its MCP settings.`));\n }\n }\n\n const dependencyNote = mcpDependencyNote(mcpDependency, pm);\n if (dependencyNote) console.log(chalk.gray(` ${dependencyNote}`));\n\n if (skillsError) {\n console.log(chalk.yellow(` Could not install the Rebase skills: ${skillsError}`));\n console.log(chalk.yellow(\" Run `rebase skills install` in the project once dependencies are installed.\"));\n }\n}\n\n/**\n * Ask whether to set up AI agents, then which, pre-ticking what is installed.\n *\n * Interactive only; the caller has already refused a non-TTY. Returns [] when\n * the developer says no or unticks everything.\n */\nexport async function promptForAgents(home?: string): Promise<AgentKey[]> {\n const { configure } = await inquirer.prompt([{\n type: \"confirm\",\n name: \"configure\",\n message: \"Set up Rebase skills and the Rebase MCP server for your AI coding agent(s)?\",\n default: true\n }]);\n if (!configure) return [];\n\n // Installed first, so the pre-ticked boxes are the ones under the cursor.\n const detected = detectInstalledAgents(home);\n const installed = [...detected.filter(a => a.found), ...detected.filter(a => !a.found)];\n console.log(\"\");\n console.log(\"Detecting installed AI coding agents...\");\n for (const { label, marker, found } of installed) {\n if (found) console.log(` ${chalk.green(\"✓\")} ${label} — ${marker}`);\n else if (marker) console.log(chalk.gray(` ✗ ${label} — ${marker} (not found)`));\n else console.log(chalk.gray(` · ${label} — can't be detected; tick it below if you use it`));\n }\n console.log(\"\");\n\n const { selectedAgents } = await inquirer.prompt([{\n type: \"checkbox\",\n name: \"selectedAgents\",\n message: \"Select agents to configure:\",\n choices: installed.map(({ key, label, found }) => {\n const { targetDir, mcp } = AGENTS[key];\n const writes = mcp ? `${targetDir} + ${mcp.file}` : targetDir;\n return { name: `${label} ${chalk.gray(`— ${writes}`)}`, short: label, value: key, checked: found };\n })\n }]);\n\n return AGENT_KEYS.filter(key => selectedAgents.includes(key));\n}\n"],"mappings":"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"}