Skip to content

Commit f408df2

Browse files
fix(cli): keep the agent setup prompt out of quiet runs; clarify spec
CodeRabbit review follow-ups: --quiet on a TTY could still reach the shared skill prompt because canPrompt does not map quiet; guard it in the shared helper so init and deploy both honor the documented contract. Spec now also states that a failed install records no dismissal (a later interactive run offers again) and that init's remote steps are the accepted link and skill install, not linking alone.
1 parent ce41f7d commit f408df2

3 files changed

Lines changed: 19 additions & 4 deletions

File tree

docs/product/command-spec.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ Purpose:
393393
Behavior:
394394

395395
- init is the config formalizer: `app deploy` works with zero config, and init writes down what deploy would infer so the setup is committed, reviewable, and stable for teammates and CI
396-
- writing the config requires no auth and no network; linking is the only remote step
396+
- writing the config requires no auth and no network; the only steps that go remote are an accepted link and an accepted agent skill install, both optional and both after the config is written
397397
- fails with `INIT_CONFIG_EXISTS` when a compute config already exists in the invocation directory or any ancestor up to the repository or workspace root; the error names the existing file, and init never overwrites or merges — editing a committed config is the user's editor's job
398398
- `--format <ts|json>` selects the config serialization; `ts` (alias `typescript`) is the default and writes `prisma.compute.ts`, `json` writes `prisma.compute.json` via the shared SDK serializer, a dependency-free static document (a `$schema` reference will be emitted once the schema is hosted; the loader already accepts and strips one); both formats pin exactly the same resolved values, and the CLI's global `--json` output flag is unrelated to the config format
399399
- with `--format json`, the types install step never runs: the JSON format exists to be dependency-free, so `--install` is a usage error; without `--install`, the result reports the step as skipped with no install hint
@@ -418,7 +418,7 @@ Behavior:
418418
- interactive mode asks `Link this directory to a Prisma Project now? (Y/n)` when the directory has no project binding; accepting enters the same picker `project link` uses
419419
- `--no-link` suppresses the question; `--link` requires the step; `--project <id-or-name>` links to that project without prompting
420420
- link failures and cancellations after the config is written downgrade to warnings and `nextSteps`; the config write stands and init exits 0
421-
- agent skill step, after the link step: interactive runs prompt once to install the Prisma Compute skill for the project when `prisma-compute` is missing, the same shared prompt `app deploy` uses; accepting installs `prisma-compute` from `prisma/skills` from the config directory, equivalent to the detected package-runner command such as `pnpm dlx @prisma/cli@latest agent install --skill prisma-compute`; declining records the prompt as dismissed in local CLI state, so neither init nor deploy asks again; a failed install downgrades to a warning with the retry command, and the config write stands; does not prompt in `--json`, `--quiet`, CI, non-interactive, or `--yes` runs
421+
- agent skill step, after the link step: interactive runs prompt once to install the Prisma Compute skill for the project when `prisma-compute` is missing, the same shared prompt `app deploy` uses; accepting installs `prisma-compute` from `prisma/skills` from the config directory, equivalent to the detected package-runner command such as `pnpm dlx @prisma/cli@latest agent install --skill prisma-compute`; declining records the prompt as dismissed in local CLI state, so neither init nor deploy asks again; a failed install downgrades to a warning with the retry command, records no dismissal (a later interactive init or deploy offers again), and the config write stands; does not prompt in `--json`, `--quiet`, CI, non-interactive, or `--yes` runs
422422
- `nextSteps` includes the deploy command, plus the project link command when the directory is still unlinked
423423
- user-facing command hints in init output (next steps, link hints, error recovery commands) use the package runner detected from the project, such as `pnpm dlx @prisma/cli@latest project link` or `npx -y @prisma/cli@latest app deploy`, matching the `agent` group's convention
424424
- in `--json`, `result` includes `configPath`, `format` (`typescript` or `json`), `converted` (true only for the `--format ts` conversion path), the written `app` values (null when a conversion transported a config that does not pin a single fully-resolved app), per-value `settings` sources, and `link` state; `--json` never prompts
@@ -1412,7 +1412,7 @@ Behavior:
14121412
- maps user-facing framework names to deploy build strategies
14131413
- does not accept `--build-command` or `--output-directory`; custom build settings live in the `build` block of `prisma.compute.ts`
14141414
- deploys arbitrary framework output with `framework: "custom"` when the config provides a built output directory and entrypoint; `build.command` is optional for prebuilt artifacts
1415-
- in interactive human deploys, prompts once to install the Prisma Compute skill for the project when `prisma-compute` is missing; accepting installs `prisma-compute` from `prisma/skills` from the project directory, equivalent to the detected package-runner command such as `pnpm dlx @prisma/cli@latest agent install --skill prisma-compute`; declining records the prompt as dismissed in local CLI state; the prompt and its dismissal state are shared with `init`, so whichever command runs interactively first asks and neither asks twice
1415+
- in interactive human deploys, prompts once to install the Prisma Compute skill for the project when `prisma-compute` is missing; accepting installs `prisma-compute` from `prisma/skills` from the project directory, equivalent to the detected package-runner command such as `pnpm dlx @prisma/cli@latest agent install --skill prisma-compute`; declining records the prompt as dismissed in local CLI state, while a failed install records no dismissal, so a later interactive run offers again; the prompt and its dismissal state are shared with `init`, so whichever command runs interactively first asks and neither asks twice
14161416
- does not prompt for agent setup in `--json`, `--quiet`, CI, `--no-interactive`, or `--yes`
14171417
- uses `src/index.ts` as the Hono deploy entrypoint when the app has no `package.json#main` or `package.json#module` and that file exists
14181418
- supports vanilla Bun apps with `--framework bun` using `package.json#main` or `package.json#module`, or with `--entry <path>`

packages/cli/src/controllers/agent-setup.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ export async function maybePromptForAgentSetup(
2222
context: CommandContext,
2323
projectDir: string,
2424
): Promise<string[]> {
25-
if (!canPrompt(context) || context.flags.yes) {
25+
// canPrompt covers json/CI/non-TTY/--no-interactive; quiet and yes runs
26+
// must also stay prompt-free even on a TTY.
27+
if (!canPrompt(context) || context.flags.yes || context.flags.quiet) {
2628
return [];
2729
}
2830

packages/cli/tests/init-agent-setup.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ async function setupInitAgentPromptTest(options: {
1616
runAgentInstall?: ReturnType<typeof vi.fn>;
1717
skillsInstalled?: boolean;
1818
isTTY?: boolean;
19+
quiet?: boolean;
1920
}) {
2021
const runAgentInstall =
2122
options.runAgentInstall ??
@@ -60,6 +61,7 @@ async function setupInitAgentPromptTest(options: {
6061
cwd,
6162
stateDir: path.join(cwd, ".state"),
6263
isTTY: options.isTTY ?? true,
64+
flags: options.quiet ? { quiet: true } : undefined,
6365
env: {
6466
...process.env,
6567
PRISMA_CLI_MOCK_FIXTURE_PATH: undefined,
@@ -137,6 +139,17 @@ describe("init agent setup prompt", () => {
137139
]);
138140
});
139141

142+
it("does not offer the skill install in quiet runs", async () => {
143+
const { context, confirmPrompt, runAgentInstall, runInit } =
144+
await setupInitAgentPromptTest({ quiet: true });
145+
146+
const result = await runInit(context, { framework: "hono" });
147+
148+
expect(result.command).toBe("init");
149+
expect(skillPromptCalls(confirmPrompt)).toHaveLength(0);
150+
expect(runAgentInstall).not.toHaveBeenCalled();
151+
});
152+
140153
it("does not offer the skill install in non-interactive runs", async () => {
141154
const { context, confirmPrompt, runAgentInstall, runInit } =
142155
await setupInitAgentPromptTest({ isTTY: false });

0 commit comments

Comments
 (0)