From aa1886ba88ce5335444bfb18412c6c3922559d7a Mon Sep 17 00:00:00 2001 From: willbot Date: Thu, 15 Oct 2026 22:01:07 +0200 Subject: [PATCH 1/5] feat: mount prisma dev url, prisma dev stop and prisma emulator list Composer 0.31.0's family ships three new commands, keyed by the path each is meant to mount at. The shell mounts them there: - dev url and dev stop under dev, which is now a command and a group - emulator list under a new emulator group, whose brief and description say what an emulator is All three are excluded from the real-API e2e rule: they talk to local emulators, never the management API, and Composer's own integration tests run them against real emulators. A new mount test runs them through the shell against Composer's operations double: a piped dev url prints the bare URL and dev stop prints nothing. The READMEs, the CLI's AGENTS.md and the platform skill name the new commands. The @prisma/composer-cli and @prisma/composer pins move to 0.31.0 in a separate commit once it is published. Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- README.md | 2 +- packages/cli/AGENTS.md | 2 +- packages/cli/README.md | 3 +- packages/cli/src/cli.ts | 16 +++- packages/cli/tests/composer-mount.test.ts | 94 +++++++++++++++++++ packages/cli/tests/e2e-coverage.test.ts | 11 +++ packages/cli/tests/mount-coverage.test.ts | 3 + packages/prisma/README.md | 3 +- skills/prisma-platform-core-concepts/SKILL.md | 15 ++- 9 files changed, 139 insertions(+), 10 deletions(-) create mode 100644 packages/cli/tests/composer-mount.test.ts diff --git a/README.md b/README.md index a26c2f4b..65681a77 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ The canonical command shape is: prisma ``` -The package includes project, environment-variable, service and service-version inspection, promotion, rollback, and deletion commands, plus the Prisma ORM (`contract`, `db`, `migration`, `orm init`) and Composer workflows (root `dev` and `deploy`), and the `postgres` and `bucket` resource groups. The product model intentionally avoids product-specific namespaces. +The package includes project, environment-variable, service and service-version inspection, promotion, rollback, and deletion commands, plus the Prisma ORM (`contract`, `db`, `migration`, `orm init`) and Composer workflows (root `dev` and `deploy`, with `dev url`, `dev stop` and `emulator list`), and the `postgres` and `bucket` resource groups. The product model intentionally avoids product-specific namespaces. ## Documentation diff --git a/packages/cli/AGENTS.md b/packages/cli/AGENTS.md index 80934c19..003c02e5 100644 --- a/packages/cli/AGENTS.md +++ b/packages/cli/AGENTS.md @@ -33,7 +33,7 @@ Architecture and contributor workflow references: - Group commands by developer workflow, not product ownership. - No `orm`, `postgres`, or `compute` namespaces in the command surface. - Canonical command shape is `prisma `. -- The shipped groups are `auth`, `project`, `git`, `branch`, `postgres`, `bucket`, `service`, `skills`, the root `init`, `dev` and `deploy` verbs, and the ORM family (`contract`, `db`, `migration`, `orm init`, `lsp`). +- The shipped groups are `auth`, `project`, `git`, `branch`, `postgres`, `bucket`, `service`, `skills`, the root `init` and `deploy` verbs, `dev` (a command that is also a group: `dev url`, `dev stop`), `emulator`, and the ORM family (`contract`, `db`, `migration`, `orm init`, `lsp`). - Preserve the long-term resource model: `workspace -> project -> branch -> { service, database, bucket }`. The mounted tree in `packages/cli/src/cli.ts` is the authoritative command surface. diff --git a/packages/cli/README.md b/packages/cli/README.md index 2571b02f..60a5821b 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -75,7 +75,8 @@ This package exposes `prisma-cli` so it can coexist with the existing | `postgres` | Create, inspect, back up, restore, and delete Prisma Postgres databases and their connections. | | `bucket` | Create, list, and delete object-store buckets and their access keys. | | `service` | Inspect services: versions, logs, domains, promote, roll back, delete. | -| `dev`, `deploy` | Run a Composer app locally; deploy it to the platform. | +| `dev`, `deploy` | Run a Composer app locally; deploy it to the platform. `dev url` prints a running node's local URL and `dev stop` stops the app. | +| `emulator` | List the local emulators `prisma dev` runs services, databases and buckets on. | | `contract`, `db`, `migration`, `orm init`, `lsp` | The Prisma ORM workflow. | Common examples: diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 7afbb9cc..79cd4f9f 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -346,6 +346,16 @@ export const cliGroups: Readonly< "A ref is a named pointer to a contract, letting commands target a contract by a stable name. Set, list, and delete refs here.", }, orm: { brief: "Initialize a Prisma ORM project" }, + dev: { + brief: + "Run your app on this machine, with no Prisma account. Start it, print a node's local URL, stop it", + }, + emulator: { + brief: + "Inspect the local emulators: programs on this machine that stand in for Prisma Cloud during prisma dev", + description: + "An emulator runs one kind of resource locally, so 'prisma dev' needs no account or network: one runs services, one runs Postgres databases, one runs S3-compatible buckets. Each holds instances, one per service, database or bucket that a 'prisma dev' started, from any directory on this machine. Emulators keep running after 'prisma dev' ends, and an instance keeps its port and data until it is deleted.", + }, skills: { brief: "Manage Prisma skills for AI coding agents. Sync and list the instruction files", @@ -411,9 +421,13 @@ export const mountedCommands: Readonly> = { "service domain delete": serviceDomainDeleteCommand, "service domain retry": serviceDomainRetryCommand, "service domain wait": serviceDomainWaitCommand, - // Composer's two product verbs, mounted at the root. + // Composer's product verbs: deploy and dev at the root, dev's + // children beneath it, and the local emulators under their own group. deploy: composerCommandFamily.commands.deploy, dev: composerCommandFamily.commands.dev, + "dev url": composerCommandFamily.commands["dev url"], + "dev stop": composerCommandFamily.commands["dev stop"], + "emulator list": composerCommandFamily.commands["emulator list"], // The ORM family. Written out per path: the shell owns the tree // (R12), so this map — not the family's own keying — is the source of // truth for where each command mounts. diff --git a/packages/cli/tests/composer-mount.test.ts b/packages/cli/tests/composer-mount.test.ts new file mode 100644 index 00000000..f0e5d054 --- /dev/null +++ b/packages/cli/tests/composer-mount.test.ts @@ -0,0 +1,94 @@ +/** + * Composer's commands, mounted at the paths this shell gives them, run + * against Composer's operations double: what is proven is the mount and + * what a pipe receives, not Composer's dev logic, which Composer's own + * integration tests run against real emulators. + */ +import { createTestCli } from "@prisma/cli-engine/testing"; +import { defineConfig as composer } from "@prisma/composer/config"; +import { nodeBuild } from "@prisma/composer/node/control"; +import { createComposerFamily } from "@prisma/composer-cli/family"; +import { createOperationsDouble } from "@prisma/composer-cli/testing"; +import { describe, expect, it } from "vitest"; +import { cliGroups, mountedCommands } from "../src/cli"; + +const build = nodeBuild(); + +const COMPOSER_SECTION = composer({ + extensions: [build], + state: { + extension: build.id, + create: () => { + throw new Error("no command in these tests reaches the state store"); + }, + }, +}); + +const NO_EMULATORS = { + ok: true as const, + value: { emulators: [] }, + assertOk() { + return this.value; + }, + assertNotOk(): never { + throw new Error("the listing succeeded"); + }, +}; + +const COMPOSER_PATHS = ["dev", "dev url", "dev stop", "emulator list"]; + +function shell() { + const family = createComposerFamily({ + operations: createOperationsDouble().operations, + listEmulators: async () => NO_EMULATORS, + }); + const commands = Object.fromEntries( + COMPOSER_PATHS.map((path) => [path, family.commands[path]]), + ); + return createTestCli({ + commandFamilies: [family], + commands, + groups: { dev: cliGroups.dev, emulator: cliGroups.emulator }, + config: { composer: COMPOSER_SECTION }, + now: () => new Date(0), + }); +} + +describe("Composer's commands in the shell", () => { + it("mounts Composer's dev children and emulator list where the shell says", () => { + for (const path of COMPOSER_PATHS) { + expect(mountedCommands[path], path).toBeDefined(); + } + expect(cliGroups.dev).toBeDefined(); + expect(cliGroups.emulator?.description).toContain("emulator"); + }); + + it("pipes the bare URL from dev url", async () => { + const result = await shell().run(["dev", "url", "gateway"]); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toBe("http://localhost:3000\n"); + }); + + it("pipes nothing from dev stop", async () => { + const result = await shell().run(["dev", "stop"]); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toBe(""); + }); + + it("lists emulators", async () => { + const result = await shell().run(["emulator", "list"]); + + expect(result.exitCode).toBe(0); + }); + + it("shows dev's own help with its children listed", async () => { + const result = await shell().run(["dev", "--help"]); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toContain("prisma-test dev"); + expect(result.stdout).toContain("url
"); + expect(result.stdout).toContain("stop"); + }); +}); diff --git a/packages/cli/tests/e2e-coverage.test.ts b/packages/cli/tests/e2e-coverage.test.ts index a7e5f58a..46593825 100644 --- a/packages/cli/tests/e2e-coverage.test.ts +++ b/packages/cli/tests/e2e-coverage.test.ts @@ -50,6 +50,14 @@ const E2E_DIR = path.resolve(import.meta.dirname, "../e2e"); const ORM_FAMILY_REASON = "ORM command: no management API involved. Real e2e lives in prisma/prisma (R7); the shell proves composition in orm-mount.test.ts (R8)."; +/** + * Composer's local commands talk to emulators on this machine, never to + * the management API this suite exists to cover. Composer's own + * integration tests run them against real emulators. + */ +const LOCAL_EMULATOR_REASON = + "Local emulators only: no management API involved. Composer's own integration tests run it against real emulators."; + const EXCLUSIONS: Readonly> = { "contract emit": ORM_FAMILY_REASON, "contract infer": ORM_FAMILY_REASON, @@ -98,6 +106,9 @@ const EXCLUSIONS: Readonly> = { deploy: "Provisions real cloud infrastructure for an app entry point, through a child `alchemy deploy`. Standing that up per CI run is neither cheap nor unattended-safe.", dev: "A session command: it runs until SIGINT or SIGTERM, redeploying on file change, so it has no happy path that terminates on its own.", + "dev url": LOCAL_EMULATOR_REASON, + "dev stop": LOCAL_EMULATOR_REASON, + "emulator list": LOCAL_EMULATOR_REASON, }; /** diff --git a/packages/cli/tests/mount-coverage.test.ts b/packages/cli/tests/mount-coverage.test.ts index d1275329..5d86dc13 100644 --- a/packages/cli/tests/mount-coverage.test.ts +++ b/packages/cli/tests/mount-coverage.test.ts @@ -100,6 +100,9 @@ const EXPECTED_MOUNT_PATHS: readonly string[] = [ "db verify", "deploy", "dev", + "dev stop", + "dev url", + "emulator list", "feedback", "git connect", "git disconnect", diff --git a/packages/prisma/README.md b/packages/prisma/README.md index 1e3fac3b..b8ba4dc5 100644 --- a/packages/prisma/README.md +++ b/packages/prisma/README.md @@ -72,7 +72,8 @@ npx prisma project env list --role preview | `postgres` | Create, inspect, back up, restore, and delete Prisma Postgres databases and their connections. | | `bucket` | Create, list, and delete object-store buckets and their access keys. | | `service` | Inspect services: versions, logs, domains, promote, roll back, delete. | -| `dev`, `deploy` | Run a Composer app locally; deploy it to the platform. | +| `dev`, `deploy` | Run a Composer app locally; deploy it to the platform. `dev url` prints a running node's local URL and `dev stop` stops the app. | +| `emulator` | List the local emulators `prisma dev` runs services, databases and buckets on. | | `contract`, `db`, `migration`, `orm init`, `lsp` | The Prisma ORM workflow. | Common examples: diff --git a/skills/prisma-platform-core-concepts/SKILL.md b/skills/prisma-platform-core-concepts/SKILL.md index bf8c7507..530e6bba 100644 --- a/skills/prisma-platform-core-concepts/SKILL.md +++ b/skills/prisma-platform-core-concepts/SKILL.md @@ -333,11 +333,16 @@ own work: applies the schema, creates local stand-ins for declared buckets, starts the services, and prints a local URL. It watches built output and restarts a service when its build changes. -2. Exercise the running app directly (for example with `curl` against the - printed URL) instead of reasoning about what the code would do. -3. Stopping `dev` leaves local databases, buckets, and their data in place; - the next run is a warm start. `--fresh` wipes this app's local instances - and data first. +2. Exercise the running app directly (for example with + `curl "$(prisma dev url )"`) instead of reasoning about what the + code would do. `prisma dev url ` prints one node's local URL: a + service's HTTP URL, a database's connection string, or a bucket's S3 + address. Use `prisma dev --detach` to start the app and get your shell + back. +3. Stopping `dev` (Ctrl-C, or `prisma dev stop`) leaves local databases, + buckets, and their data in place; the next run is a warm start. `--fresh` + wipes this app's local instances and data first. `prisma emulator list` + shows every local instance on the machine. 4. Deploying is the same pipeline pointed at the platform: switching from local to hosted is a configuration change, not a code change. Reach for `prisma deploy --stage ` only when you need a shareable URL or From 8b5a7cc0c1e56f0f8308dd98744be446419fa426 Mon Sep 17 00:00:00 2001 From: willbot Date: Thu, 15 Oct 2026 22:19:07 +0200 Subject: [PATCH 2/5] test: emulator list pipes one line per instance (skipped until 0.31.0 is pinned) prisma/composer#365 gives emulator list six tab-separated fields per instance: emulator kind, instance id, URL, state, node address and directory. The installed 0.31.0 preview predates it and writes nothing, so the case is skipped; unskip it once the published 0.31.0 is pinned. Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- packages/cli/tests/composer-mount.test.ts | 70 +++++++++++++++++++---- 1 file changed, 58 insertions(+), 12 deletions(-) diff --git a/packages/cli/tests/composer-mount.test.ts b/packages/cli/tests/composer-mount.test.ts index f0e5d054..93e3e320 100644 --- a/packages/cli/tests/composer-mount.test.ts +++ b/packages/cli/tests/composer-mount.test.ts @@ -7,7 +7,10 @@ import { createTestCli } from "@prisma/cli-engine/testing"; import { defineConfig as composer } from "@prisma/composer/config"; import { nodeBuild } from "@prisma/composer/node/control"; -import { createComposerFamily } from "@prisma/composer-cli/family"; +import { + createComposerFamily, + type ListEmulators, +} from "@prisma/composer-cli/family"; import { createOperationsDouble } from "@prisma/composer-cli/testing"; import { describe, expect, it } from "vitest"; import { cliGroups, mountedCommands } from "../src/cli"; @@ -24,23 +27,55 @@ const COMPOSER_SECTION = composer({ }, }); -const NO_EMULATORS = { - ok: true as const, - value: { emulators: [] }, - assertOk() { - return this.value; - }, - assertNotOk(): never { - throw new Error("the listing succeeded"); +type Listing = Awaited>; + +function listing(emulators: readonly EmulatorListing[]): Listing { + const value = { emulators }; + return { + ok: true as const, + value, + assertOk: () => value, + assertNotOk: (): never => { + throw new Error("the listing succeeded"); + }, + }; +} + +type EmulatorListing = Extract< + Listing, + { ok: true } +>["value"]["emulators"][number]; + +/** One running service emulator holding one instance that `prisma dev` + * started, and a database emulator that is not running. */ +const ONE_INSTANCE = listing([ + { + kind: "service", + running: true, + url: "http://localhost:4000", + instances: [ + { + id: "svc_gateway", + kind: "service", + url: "http://localhost:4001", + state: "running", + labels: { + "composer.address": "gateway", + "composer.directory": "/projects/shop", + }, + }, + ], + error: null, }, -}; + { kind: "database", running: false, url: null, instances: [], error: null }, +]); const COMPOSER_PATHS = ["dev", "dev url", "dev stop", "emulator list"]; -function shell() { +function shell(emulators: Listing = listing([])) { const family = createComposerFamily({ operations: createOperationsDouble().operations, - listEmulators: async () => NO_EMULATORS, + listEmulators: async () => emulators, }); const commands = Object.fromEntries( COMPOSER_PATHS.map((path) => [path, family.commands[path]]), @@ -83,6 +118,17 @@ describe("Composer's commands in the shell", () => { expect(result.exitCode).toBe(0); }); + // The installed 0.31.0 preview predates prisma/composer#365, which gives + // emulator list its data lines. Unskip once the published 0.31.0 is pinned. + it.skip("pipes one tab-separated line per emulator instance", async () => { + const result = await shell(ONE_INSTANCE).run(["emulator", "list"]); + + expect(result.exitCode).toBe(0); + expect(result.stdout).toBe( + "service\tsvc_gateway\thttp://localhost:4001\trunning\tgateway\t/projects/shop\n", + ); + }); + it("shows dev's own help with its children listed", async () => { const result = await shell().run(["dev", "--help"]); From 6e46373ae43f6712047d207e0fc7e42f303063b7 Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 19 Oct 2026 08:58:34 +0200 Subject: [PATCH 3/5] Follow the products' released versions: @prisma/composer-cli 0.30.0 -> 0.31.0; @prisma/composer 0.30.0 -> 0.31.0 0.31.0 is the release that ships dev url, dev stop and emulator list. Moved with scripts/update-product-versions.mjs. The emulator list pipe test is unskipped: 0.31.0 prints one line per instance with six tab-separated fields, kind, id, URL, state, node address and directory. Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- packages/cli/package.json | 4 ++-- packages/cli/tests/composer-mount.test.ts | 4 +--- packages/prisma/package.json | 2 +- pnpm-lock.yaml | 26 +++++++++++------------ 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 5bb8e990..889e650d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -50,7 +50,7 @@ "dependencies": { "@manypkg/tools": "^2.1.2", "@prisma/cli-engine": "workspace:0.9.0", - "@prisma/composer-cli": "0.30.0", + "@prisma/composer-cli": "0.31.0", "@prisma/compute-sdk": "0.43.0", "@prisma/management-api-sdk": "1.80.0", "@prisma/orm-toolchain": "8.0.0-rc.18", @@ -62,7 +62,7 @@ "open": "^11.0.0" }, "devDependencies": { - "@prisma/composer": "0.30.0", + "@prisma/composer": "0.31.0", "@prisma/credentials-store": "^7.8.0", "@repo/cli-conformance": "workspace:8.0.0-rc.23", "@repo/cli-telemetry": "workspace:8.0.0-rc.23", diff --git a/packages/cli/tests/composer-mount.test.ts b/packages/cli/tests/composer-mount.test.ts index 93e3e320..d95a6cbc 100644 --- a/packages/cli/tests/composer-mount.test.ts +++ b/packages/cli/tests/composer-mount.test.ts @@ -118,9 +118,7 @@ describe("Composer's commands in the shell", () => { expect(result.exitCode).toBe(0); }); - // The installed 0.31.0 preview predates prisma/composer#365, which gives - // emulator list its data lines. Unskip once the published 0.31.0 is pinned. - it.skip("pipes one tab-separated line per emulator instance", async () => { + it("pipes one tab-separated line per emulator instance", async () => { const result = await shell(ONE_INSTANCE).run(["emulator", "list"]); expect(result.exitCode).toBe(0); diff --git a/packages/prisma/package.json b/packages/prisma/package.json index 3cf76781..ca76f620 100644 --- a/packages/prisma/package.json +++ b/packages/prisma/package.json @@ -51,7 +51,7 @@ "dependencies": { "@manypkg/tools": "^2.1.2", "@prisma/cli-engine": "workspace:0.9.0", - "@prisma/composer-cli": "0.30.0", + "@prisma/composer-cli": "0.31.0", "@prisma/compute-sdk": "0.43.0", "@prisma/management-api-sdk": "1.80.0", "@prisma/orm-toolchain": "8.0.0-rc.18", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6782262f..1496a188 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,8 +30,8 @@ importers: specifier: workspace:0.9.0 version: link:../cli-engine '@prisma/composer-cli': - specifier: 0.30.0 - version: 0.30.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) + specifier: 0.31.0 + version: 0.31.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) '@prisma/compute-sdk': specifier: 0.43.0 version: 0.43.0(@prisma/management-api-sdk@1.80.0)(rollup@4.62.2) @@ -61,8 +61,8 @@ importers: version: 11.0.0 devDependencies: '@prisma/composer': - specifier: 0.30.0 - version: 0.30.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) + specifier: 0.31.0 + version: 0.31.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) '@prisma/credentials-store': specifier: ^7.8.0 version: 7.8.0 @@ -213,8 +213,8 @@ importers: specifier: workspace:0.9.0 version: link:../cli-engine '@prisma/composer-cli': - specifier: 0.30.0 - version: 0.30.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) + specifier: 0.31.0 + version: 0.31.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) '@prisma/compute-sdk': specifier: 0.43.0 version: 0.43.0(@prisma/management-api-sdk@1.80.0)(rollup@4.62.2) @@ -1342,14 +1342,14 @@ packages: '@oxc-project/types@0.146.0': resolution: {integrity: sha512-XC0QsnnhVe7sLIWmYmdPw7x5P0h4W8vUU3Nv1ySgWXtvCz8NizoAEpGXA0sOYoJQV2Rl13LgURAHQ5cI5ILCSA==} - '@prisma/composer-cli@0.30.0': - resolution: {integrity: sha512-HgLn3hZ59NI/qxb7O762lfdkb8L3tOisURF/PtJ7SAOE/DllXv/ePh5KMpqEBW5NLPqhK/lfsdMGIksn+nv0Jg==} + '@prisma/composer-cli@0.31.0': + resolution: {integrity: sha512-a7E0dnq2D/352qxfDt64jSIxfZT5C4xZpCd4DKsmfGq5GfvbFohsXZpzVZ8dLqQnNYlScD03QxqWnV29yTgJlw==} engines: {node: ^22.18.0 || ^24.11.0 || >=26.0.0} peerDependencies: '@prisma/cli-engine': 0.7.0 - '@prisma/composer@0.30.0': - resolution: {integrity: sha512-/P/x6ZGGMUOehieCk62Xd4W32A/BlX5kFjvXlpZR3DhZ2zSNr7Nu5NLR7n8pzaGBI5MrZvai21L3oJU9iHzrEg==} + '@prisma/composer@0.31.0': + resolution: {integrity: sha512-sMU6rW1MyymJyre1x3b/JxQG/PqJn95DT76FWj6UZMLVk7ERskGOrB2S8Aum7uExtEAiz05Ow1D4Ok3F6XgzQQ==} engines: {node: ^22.18.0 || ^24.11.0 || >=26.0.0} '@prisma/compute-sdk@0.43.0': @@ -4059,10 +4059,10 @@ snapshots: '@oxc-project/types@0.146.0': {} - '@prisma/composer-cli@0.30.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0)': + '@prisma/composer-cli@0.31.0(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@prisma/cli-engine@packages+cli-engine)(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0)': dependencies: '@prisma/cli-engine': link:packages/cli-engine - '@prisma/composer': 0.30.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) + '@prisma/composer': 0.31.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0) alchemy: 2.0.0-beta.83(@effect/vitest@4.0.3(effect@4.0.3)(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))))(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(effect@4.0.3)(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(ws@8.21.0) cross-spawn: 7.0.6 effect: 4.0.3 @@ -4096,7 +4096,7 @@ snapshots: - vitest - ws - '@prisma/composer@0.30.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0)': + '@prisma/composer@0.31.0(@types/node@22.19.19)(@vercel/nft@1.10.2(rollup@4.62.2))(hono@4.11.4)(mongodb@6.21.0(@aws-sdk/credential-providers@3.1107.0))(pg@8.23.0)(typescript@6.0.3)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0))(vitest@4.1.8(@types/node@22.19.19)(vite@7.3.5(@types/node@22.19.19)(jiti@2.7.0)(tsx@4.22.4)(yaml@2.9.0)))(ws@8.21.0)': dependencies: '@effect/sql-d1': 4.0.3(effect@4.0.3) '@effect/sql-sqlite-do': 4.0.3(effect@4.0.3) From c56fc5aa577998f8ded76a1a29257b291b57263f Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 19 Oct 2026 09:03:46 +0200 Subject: [PATCH 4/5] fix(cli): the emulator group's help says what happens to instances today It said an instance keeps its port and data until it is deleted, but no command deletes one. Instances and their data stay until 'prisma dev --fresh' removes the current app's, and a stopped instance keeps its port. The brief quotes 'prisma dev' the way the other groups quote command names. Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- packages/cli/src/cli.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/cli.ts b/packages/cli/src/cli.ts index 79cd4f9f..b66688a3 100644 --- a/packages/cli/src/cli.ts +++ b/packages/cli/src/cli.ts @@ -352,9 +352,9 @@ export const cliGroups: Readonly< }, emulator: { brief: - "Inspect the local emulators: programs on this machine that stand in for Prisma Cloud during prisma dev", + "Inspect the local emulators: programs on this machine that stand in for Prisma Cloud during 'prisma dev'", description: - "An emulator runs one kind of resource locally, so 'prisma dev' needs no account or network: one runs services, one runs Postgres databases, one runs S3-compatible buckets. Each holds instances, one per service, database or bucket that a 'prisma dev' started, from any directory on this machine. Emulators keep running after 'prisma dev' ends, and an instance keeps its port and data until it is deleted.", + "An emulator runs one kind of resource locally, so 'prisma dev' needs no account or network: one runs services, one runs Postgres databases, one runs S3-compatible buckets. Each holds instances, one per service, database or bucket that a 'prisma dev' started, from any directory on this machine. Emulators keep running after 'prisma dev' ends. Instances and their data stay until 'prisma dev --fresh' removes the current app's, and a stopped instance keeps its port.", }, skills: { brief: From a74bd007bf6bbb3ac148963146c662151bf41e5e Mon Sep 17 00:00:00 2001 From: willbot Date: Mon, 19 Oct 2026 09:22:20 +0200 Subject: [PATCH 5/5] docs(skills): use a real service name in the prisma dev url example Co-Authored-By: Claude Opus 5.5 Signed-off-by: willbot Signed-off-by: Will Madden --- skills/prisma-platform-core-concepts/SKILL.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/skills/prisma-platform-core-concepts/SKILL.md b/skills/prisma-platform-core-concepts/SKILL.md index 530e6bba..7822d57a 100644 --- a/skills/prisma-platform-core-concepts/SKILL.md +++ b/skills/prisma-platform-core-concepts/SKILL.md @@ -334,7 +334,8 @@ own work: the services, and prints a local URL. It watches built output and restarts a service when its build changes. 2. Exercise the running app directly (for example with - `curl "$(prisma dev url )"`) instead of reasoning about what the + `curl "$(prisma dev url gateway)"`, with your service's name in place of + `gateway`) instead of reasoning about what the code would do. `prisma dev url ` prints one node's local URL: a service's HTTP URL, a database's connection string, or a bucket's S3 address. Use `prisma dev --detach` to start the app and get your shell