@prisma-next/cli 0.8.0 → 0.9.0-dev.2

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 (163) hide show
  1. package/README.md +8 -9
  2. package/dist/{cli-errors-D3_sMh2K.mjs → cli-errors-CF60g2cG.mjs} +40 -2
  3. package/dist/cli-errors-CF60g2cG.mjs.map +1 -0
  4. package/dist/cli.mjs +67 -19
  5. package/dist/cli.mjs.map +1 -1
  6. package/dist/{client-BCnP7cHo.mjs → client-Brv4qlfB.mjs} +28 -30
  7. package/dist/client-Brv4qlfB.mjs.map +1 -0
  8. package/dist/{command-helpers-BeZHkxV8.mjs → command-helpers-D3vL5yi8.mjs} +29 -6
  9. package/dist/command-helpers-D3vL5yi8.mjs.map +1 -0
  10. package/dist/commands/contract-emit.mjs +1 -1
  11. package/dist/commands/contract-infer.mjs +1 -1
  12. package/dist/commands/db-init.mjs +7 -7
  13. package/dist/commands/db-schema.mjs +5 -5
  14. package/dist/commands/db-sign.d.mts.map +1 -1
  15. package/dist/commands/db-sign.mjs +67 -25
  16. package/dist/commands/db-sign.mjs.map +1 -1
  17. package/dist/commands/db-update.d.mts.map +1 -1
  18. package/dist/commands/db-update.mjs +37 -9
  19. package/dist/commands/db-update.mjs.map +1 -1
  20. package/dist/commands/db-verify.d.mts.map +1 -1
  21. package/dist/commands/db-verify.mjs +1 -1
  22. package/dist/commands/migrate.d.mts +28 -0
  23. package/dist/commands/migrate.d.mts.map +1 -0
  24. package/dist/commands/{migration-apply.mjs → migrate.mjs} +65 -39
  25. package/dist/commands/migrate.mjs.map +1 -0
  26. package/dist/commands/migration-check.d.mts +18 -0
  27. package/dist/commands/migration-check.d.mts.map +1 -0
  28. package/dist/commands/migration-check.mjs +284 -0
  29. package/dist/commands/migration-check.mjs.map +1 -0
  30. package/dist/commands/migration-graph.d.mts +16 -0
  31. package/dist/commands/migration-graph.d.mts.map +1 -0
  32. package/dist/commands/migration-graph.mjs +141 -0
  33. package/dist/commands/migration-graph.mjs.map +1 -0
  34. package/dist/commands/migration-list.d.mts +20 -0
  35. package/dist/commands/migration-list.d.mts.map +1 -0
  36. package/dist/commands/migration-list.mjs +107 -0
  37. package/dist/commands/migration-list.mjs.map +1 -0
  38. package/dist/commands/migration-log.d.mts +21 -0
  39. package/dist/commands/migration-log.d.mts.map +1 -0
  40. package/dist/commands/migration-log.mjs +146 -0
  41. package/dist/commands/migration-log.mjs.map +1 -0
  42. package/dist/commands/migration-new.d.mts.map +1 -1
  43. package/dist/commands/migration-new.mjs +30 -29
  44. package/dist/commands/migration-new.mjs.map +1 -1
  45. package/dist/commands/migration-plan.d.mts +2 -2
  46. package/dist/commands/migration-plan.d.mts.map +1 -1
  47. package/dist/commands/migration-plan.mjs +1 -1
  48. package/dist/commands/migration-show.d.mts +1 -1
  49. package/dist/commands/migration-show.d.mts.map +1 -1
  50. package/dist/commands/migration-show.mjs +90 -52
  51. package/dist/commands/migration-show.mjs.map +1 -1
  52. package/dist/commands/migration-status.d.mts +5 -17
  53. package/dist/commands/migration-status.d.mts.map +1 -1
  54. package/dist/commands/migration-status.mjs +732 -1
  55. package/dist/commands/migration-status.mjs.map +1 -0
  56. package/dist/commands/ref.d.mts +34 -0
  57. package/dist/commands/ref.d.mts.map +1 -0
  58. package/dist/commands/{migration-ref.mjs → ref.mjs} +28 -57
  59. package/dist/commands/ref.mjs.map +1 -0
  60. package/dist/{contract-emit-9DBda5Ou.mjs → contract-emit-C3STUIBg.mjs} +6 -6
  61. package/dist/{contract-emit-9DBda5Ou.mjs.map → contract-emit-C3STUIBg.mjs.map} +1 -1
  62. package/dist/{contract-emit-B77TsJqf.mjs → contract-emit-iynA3BCA.mjs} +9 -5
  63. package/dist/contract-emit-iynA3BCA.mjs.map +1 -0
  64. package/dist/{contract-infer-ByxhPjpW.mjs → contract-infer-Cnj8G1E2.mjs} +5 -5
  65. package/dist/{contract-infer-ByxhPjpW.mjs.map → contract-infer-Cnj8G1E2.mjs.map} +1 -1
  66. package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs → contract-space-aggregate-loader-pAc8CDfY.mjs} +4 -4
  67. package/dist/{contract-space-aggregate-loader-BrwKK6Q6.mjs.map → contract-space-aggregate-loader-pAc8CDfY.mjs.map} +1 -1
  68. package/dist/{db-verify-Czm5T-J4.mjs → db-verify-D7cyH_zz.mjs} +12 -9
  69. package/dist/db-verify-D7cyH_zz.mjs.map +1 -0
  70. package/dist/errors-Cw6kyTyV.mjs +56 -0
  71. package/dist/errors-Cw6kyTyV.mjs.map +1 -0
  72. package/dist/exports/control-api.d.mts +1 -1
  73. package/dist/exports/control-api.d.mts.map +1 -1
  74. package/dist/exports/control-api.mjs +2 -2
  75. package/dist/exports/index.mjs +1 -1
  76. package/dist/exports/index.mjs.map +1 -1
  77. package/dist/exports/init-output.mjs +1 -1
  78. package/dist/{framework-components-ChqVUxR-.mjs → framework-components-xFLFpZUO.mjs} +2 -2
  79. package/dist/{framework-components-ChqVUxR-.mjs.map → framework-components-xFLFpZUO.mjs.map} +1 -1
  80. package/dist/{global-flags-Icqpxk23.d.mts → global-flags-DGmw6Kqg.d.mts} +1 -1
  81. package/dist/{global-flags-Icqpxk23.d.mts.map → global-flags-DGmw6Kqg.d.mts.map} +1 -1
  82. package/dist/{migration-status-By9G5p2H.mjs → graph-render-eJDcLWny.mjs} +3 -692
  83. package/dist/graph-render-eJDcLWny.mjs.map +1 -0
  84. package/dist/{init-B-k3a1Qw.mjs → init-DEe-IimY.mjs} +133 -61
  85. package/dist/init-DEe-IimY.mjs.map +1 -0
  86. package/dist/{inspect-live-schema-DxdBd4Er.mjs → inspect-live-schema-CWLK_lgs.mjs} +4 -4
  87. package/dist/{inspect-live-schema-DxdBd4Er.mjs.map → inspect-live-schema-CWLK_lgs.mjs.map} +1 -1
  88. package/dist/migration-cli.mjs +1 -1
  89. package/dist/migration-cli.mjs.map +1 -1
  90. package/dist/{migration-command-scaffold-BdV8JYXV.mjs → migration-command-scaffold-CmXXC1UZ.mjs} +4 -4
  91. package/dist/{migration-command-scaffold-BdV8JYXV.mjs.map → migration-command-scaffold-CmXXC1UZ.mjs.map} +1 -1
  92. package/dist/{migration-plan-mRu5K81L.mjs → migration-plan-CHyUlBV0.mjs} +76 -37
  93. package/dist/migration-plan-CHyUlBV0.mjs.map +1 -0
  94. package/dist/migration-types-D2FW63pr.d.mts +15 -0
  95. package/dist/migration-types-D2FW63pr.d.mts.map +1 -0
  96. package/dist/{migrations-CTsyBXCA.mjs → migrations-DyUf5lTt.mjs} +2 -2
  97. package/dist/migrations-DyUf5lTt.mjs.map +1 -0
  98. package/dist/{output-BVj6a971.mjs → output-B60Gw5fu.mjs} +12 -11
  99. package/dist/{output-BVj6a971.mjs.map → output-B60Gw5fu.mjs.map} +1 -1
  100. package/dist/{result-handler-rmPVKIP2.mjs → result-handler-Bm_6dDYg.mjs} +2 -2
  101. package/dist/{result-handler-rmPVKIP2.mjs.map → result-handler-Bm_6dDYg.mjs.map} +1 -1
  102. package/dist/{terminal-ui-C_hFNbAn.mjs → terminal-ui-XtOQsqe9.mjs} +2 -54
  103. package/dist/terminal-ui-XtOQsqe9.mjs.map +1 -0
  104. package/dist/{types-LItU7E4l.d.mts → types-0aS865QN.d.mts} +14 -8
  105. package/dist/types-0aS865QN.d.mts.map +1 -0
  106. package/dist/{verify-CiwNWM9N.mjs → verify-D7ypCCe6.mjs} +1 -1
  107. package/dist/{verify-CiwNWM9N.mjs.map → verify-D7ypCCe6.mjs.map} +1 -1
  108. package/package.json +39 -23
  109. package/src/cli.ts +78 -15
  110. package/src/commands/db-sign.ts +102 -32
  111. package/src/commands/db-update.ts +56 -4
  112. package/src/commands/db-verify.ts +19 -3
  113. package/src/commands/init/agent-skill-install.ts +145 -43
  114. package/src/commands/init/errors.ts +2 -2
  115. package/src/commands/init/exit-codes.ts +2 -2
  116. package/src/commands/init/index.ts +1 -1
  117. package/src/commands/init/init.ts +15 -6
  118. package/src/commands/init/inputs.ts +1 -1
  119. package/src/commands/init/output.ts +22 -17
  120. package/src/commands/{migration-apply.ts → migrate.ts} +77 -73
  121. package/src/commands/migration-check/exit-codes.ts +3 -0
  122. package/src/commands/migration-check.ts +369 -0
  123. package/src/commands/migration-graph.ts +184 -0
  124. package/src/commands/migration-list.ts +155 -0
  125. package/src/commands/migration-log.ts +218 -0
  126. package/src/commands/migration-new.ts +30 -22
  127. package/src/commands/migration-plan.ts +104 -35
  128. package/src/commands/migration-show.ts +141 -65
  129. package/src/commands/migration-status.ts +82 -69
  130. package/src/commands/{migration-ref.ts → ref.ts} +32 -86
  131. package/src/control-api/client.ts +30 -21
  132. package/src/control-api/operations/apply-aggregate.ts +4 -4
  133. package/src/control-api/operations/contract-emit.ts +26 -3
  134. package/src/control-api/operations/db-apply-aggregate.ts +4 -3
  135. package/src/control-api/operations/db-verify.ts +2 -2
  136. package/src/control-api/operations/migration-apply.ts +5 -4
  137. package/src/control-api/types.ts +12 -7
  138. package/src/load-ts-contract.ts +9 -1
  139. package/src/migration-cli.ts +1 -1
  140. package/src/utils/cli-errors.ts +37 -0
  141. package/src/utils/command-helpers.ts +28 -3
  142. package/src/utils/contract-space-aggregate-loader.ts +4 -4
  143. package/src/utils/contract-space-seed-phase.ts +2 -2
  144. package/src/utils/formatters/help.ts +12 -2
  145. package/src/utils/formatters/migrations.ts +2 -2
  146. package/dist/cli-errors-D3_sMh2K.mjs.map +0 -1
  147. package/dist/client-BCnP7cHo.mjs.map +0 -1
  148. package/dist/command-helpers-BeZHkxV8.mjs.map +0 -1
  149. package/dist/commands/migration-apply.d.mts +0 -51
  150. package/dist/commands/migration-apply.d.mts.map +0 -1
  151. package/dist/commands/migration-apply.mjs.map +0 -1
  152. package/dist/commands/migration-ref.d.mts +0 -45
  153. package/dist/commands/migration-ref.d.mts.map +0 -1
  154. package/dist/commands/migration-ref.mjs.map +0 -1
  155. package/dist/contract-emit-B77TsJqf.mjs.map +0 -1
  156. package/dist/db-verify-Czm5T-J4.mjs.map +0 -1
  157. package/dist/init-B-k3a1Qw.mjs.map +0 -1
  158. package/dist/migration-plan-mRu5K81L.mjs.map +0 -1
  159. package/dist/migration-status-By9G5p2H.mjs.map +0 -1
  160. package/dist/migrations-CTsyBXCA.mjs.map +0 -1
  161. package/dist/terminal-ui-C_hFNbAn.mjs.map +0 -1
  162. package/dist/types-LItU7E4l.d.mts.map +0 -1
  163. /package/dist/{cli-errors-B9OBbled.d.mts → cli-errors-DdcjVLJV.d.mts} +0 -0
@@ -1,44 +1,133 @@
1
1
  import { execFile } from 'node:child_process';
2
2
  import { promisify } from 'node:util';
3
+ import { version as cliVersion } from '../../../package.json' with { type: 'json' };
3
4
  import type { PackageManager } from './detect-package-manager';
4
5
  import { errorInitSkillInstallFailed } from './errors';
5
6
 
6
7
  const exec = promisify(execFile);
7
8
 
8
9
  /**
9
- * The npm package the agent-skill install dispatches to. Version-locked
10
- * to Prisma Next via the consumer project's `package.json`; the install
11
- * subprocess picks up whatever version is resolvable at install time.
10
+ * Default base for the GitHub-URL form `<owner>/<repo>` consumed by
11
+ * upstream `skills add`. Each `SkillSource` joins this base with its
12
+ * own subpath (and optional `#ref` for version-pinned clusters).
13
+ */
14
+ export const DEFAULT_AGENT_SKILL_BASE = 'prisma/prisma-next';
15
+
16
+ /**
17
+ * One discovery scope inside the Prisma Next monorepo. The CLI emits
18
+ * one `skills add <base>/<subpath>[#ref] --all` invocation per source
19
+ * during `init`.
12
20
  *
13
- * The skill is **always** installed at the project level — never the
14
- * user level precisely so the skill version tracks the project's
15
- * Prisma Next version. A user-level (global) install of an
16
- * agent-skills CLI package would have to pick a single version for
17
- * every project on the host, which breaks the version-locking invariant
18
- * the rest of the framework relies on (skills, CLI, runtime, and
19
- * extension packs all ship at the same version per release).
21
+ * `ref` semantics:
22
+ * - `cli`: pin to the CLI's own package version (lockstep with the
23
+ * skills' SPI). Used for the version-locked usage cluster the
24
+ * skills under `skills/<X>/SKILL.md`, which describe the public
25
+ * package API and are pinned to the version of `@prisma-next/*`
26
+ * currently installed in the consumer's project.
27
+ * - `null`: no ref. The cluster is "always-latest" the cumulative
28
+ * instruction set is the source of truth, and the latest revision
29
+ * on `main` includes bug fixes for every prior transition. Used
30
+ * for the upgrade and extension-author clusters.
20
31
  */
21
- export const AGENT_SKILL_PACKAGE = '@prisma-next/agent-skill';
32
+ export interface SkillSource {
33
+ readonly subpath: string;
34
+ readonly ref: 'cli' | null;
35
+ readonly description: string;
36
+ }
37
+
38
+ export const DEFAULT_AGENT_SKILL_SOURCES: readonly SkillSource[] = [
39
+ {
40
+ subpath: 'skills',
41
+ ref: 'cli',
42
+ description: 'usage skills (version-locked to installed Prisma Next)',
43
+ },
44
+ {
45
+ subpath: 'skills/upgrade',
46
+ ref: null,
47
+ description: 'upgrade skill (always tracks `main`)',
48
+ },
49
+ {
50
+ subpath: 'skills/extension-author',
51
+ ref: null,
52
+ description: 'extension-author skill (always tracks `main`)',
53
+ },
54
+ ];
22
55
 
23
56
  /**
24
- * The skill-install command, formatted for the project's detected
25
- * package manager. `npx`/`pnpm dlx`/`bunx` are interchangeable to the
26
- * user; we pick the variant that matches the rest of the install step
27
- * so a single project consistently uses one runner.
57
+ * Test-only escape hatch for pinning the install base to a local
58
+ * checkout. Production runs leave this unset, so installs always use
59
+ * `DEFAULT_AGENT_SKILL_BASE`.
60
+ *
61
+ * When set to an absolute filesystem path (typical for tests), the
62
+ * `#ref` fragment is dropped — local-path mode in upstream's CLI does
63
+ * not accept refs, and the local clone has whatever content the test
64
+ * checked into it anyway. When set to anything else (e.g. a fork name
65
+ * `myuser/prisma-next`), the ref policy is preserved.
66
+ */
67
+ function resolveAgentSkillBase(): string {
68
+ const override = process.env['PRISMA_NEXT_SKILLS_BASE']?.trim();
69
+ return override && override.length > 0 ? override : DEFAULT_AGENT_SKILL_BASE;
70
+ }
71
+
72
+ function isLocalPath(base: string): boolean {
73
+ return base.startsWith('/') || /^[a-zA-Z]:[\\/]/.test(base);
74
+ }
75
+
76
+ /**
77
+ * Build the `<base>/<subpath>[#ref]` URL the `skills` CLI will
78
+ * resolve. Exported for unit tests so the per-source format can be
79
+ * asserted without going through the full install loop.
80
+ */
81
+ export function formatSkillSourceUrl(source: SkillSource): string {
82
+ const base = resolveAgentSkillBase();
83
+ const url = `${base}/${source.subpath}`;
84
+ if (source.ref === null) return url;
85
+ if (isLocalPath(base)) return url;
86
+ if (source.ref === 'cli') return `${url}#v${cliVersion}`;
87
+ return url;
88
+ }
89
+
90
+ /**
91
+ * The skill-install command for one source, formatted for the
92
+ * project's detected package manager. `npx`/`pnpm dlx`/`bunx` are
93
+ * interchangeable to the user; we pick the variant that matches the
94
+ * rest of the install step so a single project consistently uses one
95
+ * runner.
28
96
  *
29
97
  * `--all` auto-selects every skill in the cluster and every detected
30
98
  * agent runtime, skipping the multi-select prompts the `skills` CLI
31
99
  * shows by default. A non-interactive scaffold step cannot present
32
- * prompts, and the cluster is designed to be installed as a unit (the
33
- * router skill routes between the workflow-scoped siblings). Users who
34
- * want a narrower install run `npx skills add @prisma-next/agent-skill`
35
- * themselves after `init` with the flags they want.
100
+ * prompts.
36
101
  *
37
102
  * Exported for unit tests so the per-PM dispatch can be asserted
38
103
  * without a live subprocess.
39
104
  */
40
- export function formatSkillInstallCommand(pm: PackageManager): string {
41
- const args = ['skills', 'add', AGENT_SKILL_PACKAGE, '--all'];
105
+ export function formatSkillInstallCommand(pm: PackageManager, source: SkillSource): string {
106
+ const args = ['skills@latest', 'add', formatSkillSourceUrl(source), '--all'];
107
+ return formatPackageManagerCommand(pm, args);
108
+ }
109
+
110
+ /**
111
+ * `skills add --all` should cover Claude Code, but upstream currently skips
112
+ * project-local Claude symlinks when `.claude/` does not already exist. Run
113
+ * the explicit Claude Code install as well so fresh projects get
114
+ * `.claude/skills` without asking users to create that folder first.
115
+ */
116
+ export function formatClaudeSkillInstallCommand(pm: PackageManager, source: SkillSource): string {
117
+ const args = [
118
+ 'skills@latest',
119
+ 'add',
120
+ formatSkillSourceUrl(source),
121
+ '--agent',
122
+ 'claude-code',
123
+ '--skill',
124
+ "'*'",
125
+ '-y',
126
+ ];
127
+ return formatPackageManagerCommand(pm, args);
128
+ }
129
+
130
+ function formatPackageManagerCommand(pm: PackageManager, args: readonly string[]): string {
42
131
  switch (pm) {
43
132
  case 'pnpm':
44
133
  return `pnpm dlx ${args.join(' ')}`;
@@ -58,42 +147,55 @@ export function formatSkillInstallCommand(pm: PackageManager): string {
58
147
  * format-then-parse split keeps the user-facing command string the same
59
148
  * as the surface the structured error advertises, so a user who copies
60
149
  * the error's `fix` line gets the same invocation that init just
61
- * attempted.
150
+ * attempted. Single quotes are preserved in the display form so `*` is
151
+ * safe to copy into a shell, then stripped before `execFile`.
62
152
  */
63
153
  function commandToExec(command: string): {
64
154
  readonly file: string;
65
155
  readonly args: readonly string[];
66
156
  } {
67
- const tokens = command.split(/\s+/);
157
+ const tokens = (command.match(/'[^']*'|\S+/g) ?? []).map((token) =>
158
+ token.startsWith("'") && token.endsWith("'") ? token.slice(1, -1) : token,
159
+ );
68
160
  return { file: tokens[0] ?? 'npx', args: tokens.slice(1) };
69
161
  }
70
162
 
71
163
  /**
72
- * Runs the project-level skill install. Returns `{ ok: true, command }`
73
- * on success; throws a structured `errorInitSkillInstallFailed` on
74
- * failure. The throw is intentionally fatal project-level skill
75
- * install is unconditional (modulo `--no-skill`) and the user opted
76
- * into Prisma Next by running `init`. A silent skip would defeat the
77
- * onboarding-to-zero contract.
164
+ * Runs the project-level skill install for every source in
165
+ * `DEFAULT_AGENT_SKILL_SOURCES`, in order. Returns
166
+ * `{ ok: true, commands }` on success; throws a structured
167
+ * `errorInitSkillInstallFailed` on the first failure (subsequent
168
+ * sources are not attempted the user opted into Prisma Next by
169
+ * running `init` and a partial install would leave the project in an
170
+ * ambiguous state). The throw is intentionally fatal — project-level
171
+ * skill install is unconditional (modulo `--no-skill`).
78
172
  */
79
173
  export async function runProjectLevelSkillInstall(ctx: {
80
174
  readonly baseDir: string;
81
175
  readonly pm: PackageManager;
82
176
  readonly filesWritten: readonly string[];
83
- }): Promise<{ readonly ok: true; readonly command: string }> {
84
- const command = formatSkillInstallCommand(ctx.pm);
85
- const { file, args } = commandToExec(command);
86
- try {
87
- await exec(file, args, { cwd: ctx.baseDir });
88
- return { ok: true, command };
89
- } catch (err) {
90
- throw errorInitSkillInstallFailed({
91
- skillInstallCommand: command,
92
- filesWritten: ctx.filesWritten,
93
- cause:
94
- redactSecrets(readChildStderr(err)) || (err instanceof Error ? err.message : String(err)),
95
- });
177
+ }): Promise<{ readonly ok: true; readonly commands: readonly string[] }> {
178
+ const commands: string[] = [];
179
+ const installCommands = DEFAULT_AGENT_SKILL_SOURCES.flatMap((source) => [
180
+ formatSkillInstallCommand(ctx.pm, source),
181
+ formatClaudeSkillInstallCommand(ctx.pm, source),
182
+ ]);
183
+
184
+ for (const command of installCommands) {
185
+ const { file, args } = commandToExec(command);
186
+ try {
187
+ await exec(file, args, { cwd: ctx.baseDir });
188
+ commands.push(command);
189
+ } catch (err) {
190
+ throw errorInitSkillInstallFailed({
191
+ skillInstallCommand: command,
192
+ filesWritten: ctx.filesWritten,
193
+ cause:
194
+ redactSecrets(readChildStderr(err)) || (err instanceof Error ? err.message : String(err)),
195
+ });
196
+ }
96
197
  }
198
+ return { ok: true, commands };
97
199
  }
98
200
 
99
201
  function readChildStderr(err: unknown): string {
@@ -125,6 +227,6 @@ export function redactSecrets(stderr: string): string {
125
227
  /**
126
228
  * Hand-rolled skill stub path that init must not leave behind. Removed
127
229
  * on every init run so a project's `.agents/skills/prisma-next/` does
128
- * not shadow the published `@prisma-next/agent-skill` package.
230
+ * not shadow the installed Prisma Next skill cluster.
129
231
  */
130
232
  export const LEGACY_SKILL_FILE = '.agents/skills/prisma-next/SKILL.md';
@@ -239,7 +239,7 @@ export function errorInitEmitFailed(options: {
239
239
 
240
240
  /**
241
241
  * The project-level agent-skill install (`npx skills add
242
- * @prisma-next/agent-skill`) failed after a successful dependency
242
+ * prisma/prisma-next#v<version>`) failed after a successful dependency
243
243
  * install + emit. The project's scaffold remains on disk; the user
244
244
  * can either fix the underlying issue (network, registry, PATH) and
245
245
  * run the install command manually, or re-run `init --no-skill` to
@@ -253,7 +253,7 @@ export function errorInitSkillInstallFailed(options: {
253
253
  readonly filesWritten: readonly string[];
254
254
  readonly cause: string;
255
255
  }): CliStructuredError {
256
- return new CliStructuredError('5013', 'Failed to install @prisma-next/agent-skill', {
256
+ return new CliStructuredError('5013', 'Failed to install Prisma Next skills', {
257
257
  domain: 'CLI',
258
258
  why: `\`${options.skillInstallCommand}\` exited with an error: ${options.cause}`,
259
259
  fix:
@@ -62,8 +62,8 @@ export const INIT_EXIT_INSTALL_FAILED = 4;
62
62
  export const INIT_EXIT_EMIT_FAILED = 5;
63
63
 
64
64
  /**
65
- * The project-level `@prisma-next/agent-skill` install (`npx skills add
66
- * @prisma-next/agent-skill`) failed after a successful dependency
65
+ * The project-level Prisma Next skills install (`npx skills add
66
+ * prisma/prisma-next#v<version>`) failed after a successful dependency
67
67
  * install + emit. The scaffolded project files remain on disk; the
68
68
  * user can fix the underlying issue (network, registry reachability,
69
69
  * `npx skills` not on PATH) and run the install manually, or re-run
@@ -89,7 +89,7 @@ export function createInitCommand(): Command {
89
89
  .option('--no-install', 'Skip dependency installation and contract emission')
90
90
  .option(
91
91
  '--no-skill',
92
- 'Skip the @prisma-next/agent-skill install (air-gapped CI, restricted registries, etc.)',
92
+ 'Skip Prisma Next skills install (air-gapped CI, restricted registries, etc.)',
93
93
  )
94
94
  .action(async (options: InitCommandOptions) => {
95
95
  const { runInit } = await import('./init');
@@ -8,6 +8,8 @@ import { formatErrorJson, formatErrorOutput } from '../../utils/formatters/error
8
8
  import type { GlobalFlags } from '../../utils/global-flags';
9
9
  import { TerminalUI } from '../../utils/terminal-ui';
10
10
  import {
11
+ DEFAULT_AGENT_SKILL_SOURCES,
12
+ formatClaudeSkillInstallCommand,
11
13
  formatSkillInstallCommand,
12
14
  LEGACY_SKILL_FILE,
13
15
  runProjectLevelSkillInstall,
@@ -182,7 +184,7 @@ export async function runInit(
182
184
  // and missing-on-disk-at-write-time is tolerated.
183
185
  const filesToDelete: string[] = inputs.reinit ? [...findStaleArtefacts(baseDir, schemaDir)] : [];
184
186
 
185
- // `init` delegates the skill to `npx skills add @prisma-next/agent-skill`,
187
+ // `init` delegates the skill to `npx skills add prisma/prisma-next#v<version>`,
186
188
  // so a hand-rolled `.agents/skills/prisma-next/SKILL.md` in the project
187
189
  // would shadow the published package. Queue it for deletion on every
188
190
  // run (not gated on `--reinit`).
@@ -449,18 +451,23 @@ export async function runInit(
449
451
  // potentially fails. We skip the install when the user passed
450
452
  // `--no-install` for the same reason — no `node_modules` means the
451
453
  // workspace isn't ready to consume the skill yet anyway.
452
- const manualProjectSkillCommand = formatSkillInstallCommand(install.effectivePm);
454
+ const manualProjectSkillCommands = DEFAULT_AGENT_SKILL_SOURCES.flatMap((source) => [
455
+ formatSkillInstallCommand(install.effectivePm, source),
456
+ formatClaudeSkillInstallCommand(install.effectivePm, source),
457
+ ]);
458
+ const manualProjectSkillSummary = manualProjectSkillCommands.map((c) => `\`${c}\``).join(' && ');
459
+ let skillRegistered = false;
453
460
  if (!inputs.installProjectSkill) {
454
461
  warnings.push(
455
- `Skipped @prisma-next/agent-skill install (--no-skill). To install later, run \`${manualProjectSkillCommand}\` in this project.`,
462
+ `Skipped Prisma Next agent-skill install (--no-skill). To install the skills later, run: ${manualProjectSkillSummary}`,
456
463
  );
457
464
  } else if (install.skipped) {
458
465
  warnings.push(
459
- `Skipped @prisma-next/agent-skill install because --no-install was passed. Once you run install manually, register the skill with \`${manualProjectSkillCommand}\`.`,
466
+ `Skipped Prisma Next agent-skill install because --no-install was passed. After you run install manually, install the skills with: ${manualProjectSkillSummary}`,
460
467
  );
461
468
  } else {
462
469
  const spinner = ui.spinner();
463
- spinner.start('Registering @prisma-next/agent-skill with the agent runtime...');
470
+ spinner.start('Registering Prisma Next skills with the agent runtime...');
464
471
  try {
465
472
  const project = await runProjectLevelSkillInstall({
466
473
  baseDir,
@@ -468,8 +475,9 @@ export async function runInit(
468
475
  filesWritten,
469
476
  });
470
477
  spinner.stop(
471
- `Registered @prisma-next/agent-skill (project level) — ran \`${project.command}\``,
478
+ `Registered Prisma Next skills (project level) — ran ${project.commands.map((c) => `\`${c}\``).join(', ')}`,
472
479
  );
480
+ skillRegistered = true;
473
481
  } catch (error) {
474
482
  spinner.stop('Agent-skill install failed');
475
483
  if (CliStructuredError.is(error)) {
@@ -497,6 +505,7 @@ export async function runInit(
497
505
  contractEmitted,
498
506
  emitCommand,
499
507
  schemaPath: inputs.schemaPath,
508
+ skillRegistered,
500
509
  }),
501
510
  warnings,
502
511
  };
@@ -69,7 +69,7 @@ export interface ResolvedInitInputs {
69
69
  */
70
70
  readonly removePreviousFacade: string | null;
71
71
  /**
72
- * Whether to run `npx skills add @prisma-next/agent-skill` at the
72
+ * Whether to run `npx skills add prisma/prisma-next#v<version>` at the
73
73
  * project level after install + emit. True by default; `--no-skill`
74
74
  * sets it to `false`. The skill is always project-level (never
75
75
  * user-level / global) so its version stays locked to the project's
@@ -120,27 +120,32 @@ export function buildNextSteps(options: {
120
120
  readonly contractEmitted: boolean;
121
121
  readonly emitCommand: string;
122
122
  readonly schemaPath: string;
123
+ /**
124
+ * Whether the project-level Prisma Next skills install actually ran
125
+ * and succeeded during this `init`. When false (the user passed
126
+ * `--no-skill` or `--no-install`, so the install was skipped), the
127
+ * "registered with your agent runtime" step is omitted — the skip is
128
+ * already surfaced in the warnings array with a manual-install hint.
129
+ */
130
+ readonly skillRegistered: boolean;
123
131
  }): string[] {
124
132
  const steps: string[] = [];
125
- steps.push('1. Set DATABASE_URL in your environment (export it or add it to .env).');
133
+ let stepNumber = 1;
134
+ const push = (text: string): void => {
135
+ steps.push(`${stepNumber}. ${text}`);
136
+ stepNumber += 1;
137
+ };
138
+ push('Set DATABASE_URL in your environment (export it or add it to .env).');
126
139
  if (!options.contractEmitted) {
127
- steps.push(`2. Emit the contract: \`${options.emitCommand}\``);
128
- steps.push(`3. Edit your schema at ${options.schemaPath}, then re-run the emit command.`);
129
- steps.push(
130
- '4. Open prisma-next.md for a quick reference on how to write your first typed query.',
131
- );
132
- steps.push(
133
- '5. @prisma-next/agent-skill is registered with your agent runtime — open the project in your IDE and ask the agent to add a model, run a query, or plan a migration.',
134
- );
140
+ push(`Emit the contract: \`${options.emitCommand}\``);
141
+ push(`Edit your schema at ${options.schemaPath}, then re-run the emit command.`);
135
142
  } else {
136
- steps.push(
137
- `2. Edit your schema at ${options.schemaPath}, then re-run \`${options.emitCommand}\`.`,
138
- );
139
- steps.push(
140
- '3. Open prisma-next.md for a quick reference on how to write your first typed query.',
141
- );
142
- steps.push(
143
- '4. @prisma-next/agent-skill is registered with your agent runtime — open the project in your IDE and ask the agent to add a model, run a query, or plan a migration.',
143
+ push(`Edit your schema at ${options.schemaPath}, then re-run \`${options.emitCommand}\`.`);
144
+ }
145
+ push('Open prisma-next.md for a quick reference on how to write your first typed query.');
146
+ if (options.skillRegistered) {
147
+ push(
148
+ 'Prisma Next skills are registered with your agent runtime — open the project in your IDE and ask the agent to add a model, run a query, or plan a migration.',
144
149
  );
145
150
  }
146
151
  return steps;