diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ab28aa52..d98e10e5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,12 +49,10 @@ The architecture entrypoint lives at `ARCHITECTURE.md`. Read these before changing CLI behavior: -1. `docs/product/resource-model.md` -2. `docs/product/command-principles.md` -3. `docs/product/command-spec.md` -4. `docs/product/cli-style-guide.md` -5. `docs/product/output-conventions.md` -6. `docs/product/error-conventions.md` +1. `docs/product/command-principles.md` +2. `docs/product/cli-style-guide.md` +3. `docs/product/output-conventions.md` +4. `docs/product/error-conventions.md` The CLI must preserve the unified command model: diff --git a/README.md b/README.md index 5a9117b3..5f0f25c3 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,18 @@ Beta of the unified Prisma CLI. -This repository contains the unified Prisma command-line experience. The current -implementation focuses on app deployment workflows while preserving the -long-term command model for Prisma projects, branches, schemas, databases, and -apps. +This repository contains the unified Prisma command-line experience: one +binary for the ORM, Composer, and the Prisma Developer Platform — projects, +branches, services, deployments, environment variables, and the Prisma ORM +schema and migration workflow. -Official beta releases use the primary `@prisma/cli` package line. The package -exposes a `prisma-cli` binary so it can coexist with the existing `prisma` -executable. +The 8.0.0 release candidates publish as `prisma` (binary `prisma`) and +`@prisma/cli` (binary `prisma-cli`) on the `next` dist-tag. ## Install ```bash -pnpm add -D @prisma/cli +pnpm add -D @prisma/cli@next pnpm prisma-cli --help ``` @@ -22,26 +21,14 @@ Example workflow: ```bash pnpm prisma-cli auth login -pnpm prisma-cli app deploy --env DATABASE_URL=postgresql://example +pnpm prisma-cli project create my-app +pnpm prisma-cli git connect git@github.com:owner/repo.git pnpm prisma-cli project env add --file .env --role preview pnpm prisma-cli project env list --role preview ``` -If you want local project scripts that look like the future command shape, add: - -```json -{ - "scripts": { - "prisma": "prisma-cli" - } -} -``` - -Then run: - -```bash -pnpm prisma app deploy -``` +Deployments start from pushing the connected repository, the Console, or +`prisma-cli composer deploy` — there is no standalone deploy command. ## Local Development @@ -98,10 +85,11 @@ The canonical command shape is: prisma ``` -The beta package includes app build, run, deploy, environment-variable, -deployment inspection, promotion, rollback, and removal commands. The product -model intentionally keeps room for future schema, database, and migration -workflows without introducing product-specific namespaces. +The package includes project, environment-variable, service and deployment +inspection, promotion, rollback, and removal commands, plus the Prisma ORM +(`contract`, `db`, `migrate`, `migration`, `orm init`) and Composer +workflows, and the `postgres` and `bucket` resource groups. The product +model intentionally avoids product-specific namespaces. ## Documentation @@ -111,12 +99,10 @@ Product behavior is defined in `docs/product`. Start here when changing command behavior: -1. `docs/product/resource-model.md` -2. `docs/product/command-principles.md` -3. `docs/product/command-spec.md` -4. `docs/product/cli-style-guide.md` -5. `docs/product/output-conventions.md` -6. `docs/product/error-conventions.md` +1. `docs/product/command-principles.md` +2. `docs/product/cli-style-guide.md` +3. `docs/product/output-conventions.md` +4. `docs/product/error-conventions.md` See `CONTRIBUTING.md` for local development and contribution guidance. See `ARCHITECTURE.md` for the short architecture entrypoint. diff --git a/docs/README.md b/docs/README.md index b0659a96..586f0c36 100644 --- a/docs/README.md +++ b/docs/README.md @@ -10,12 +10,10 @@ without inventing behavior outside the product model. Read these in order before changing command behavior: -1. [Resource model](product/resource-model.md) -2. [Command principles](product/command-principles.md) -3. [Command spec](product/command-spec.md) -4. [CLI style guide](product/cli-style-guide.md) -5. [Output conventions](product/output-conventions.md) -6. [Error conventions](product/error-conventions.md) +1. [Command principles](product/command-principles.md) +2. [CLI style guide](product/cli-style-guide.md) +3. [Output conventions](product/output-conventions.md) +4. [Error conventions](product/error-conventions.md) For local development, continue with: diff --git a/docs/architecture/overview.md b/docs/architecture/overview.md index 7cb5f256..2c8ab66d 100644 --- a/docs/architecture/overview.md +++ b/docs/architecture/overview.md @@ -51,7 +51,7 @@ implementation. Local state boundaries are also explicit: -- `prisma.config.ts` stores the linked project id. +- `.prisma/local.json` stores the linked project ID (a gitignored local pin, not a committed config file). - Active branch and app selection are local CLI state. - Secret values must not be printed in human output or structured output. @@ -65,5 +65,5 @@ The beta package should remain small and predictable: - `production` is a protected durable branch and requires explicit intent. - Every other named branch is preview by default. -See [resource model](../product/resource-model.md) and -[command spec](../product/command-spec.md) for the authoritative rules. +The mounted command tree in `packages/cli/src/cli.ts` is the +authoritative command surface. diff --git a/docs/onboarding/common-tasks.md b/docs/onboarding/common-tasks.md index 56327438..1d7fc607 100644 --- a/docs/onboarding/common-tasks.md +++ b/docs/onboarding/common-tasks.md @@ -5,11 +5,9 @@ Use this playbook when making common changes to the CLI. ## Add Or Change A Command 1. Update the source-of-truth product docs first: - - [command spec](../product/command-spec.md) - [command principles](../product/command-principles.md) - - [resource model](../product/resource-model.md), when resources or resolution rules change 2. Add or update the command in `packages/cli/src/commands//` and mount it in - `packages/cli/src/cli.ts`. + `packages/cli/src/cli.ts` (the mounted tree is the authoritative command surface). 3. Put product rules and resource resolution in the operation layer (`packages/cli/src/controllers`, `packages/cli/src/lib`). 4. Update the handler's presentation blocks when output shape changes. @@ -33,11 +31,9 @@ Use this playbook when making common changes to the CLI. ## Change Resource Resolution -1. Update [resource model](../product/resource-model.md). -2. Update [command spec](../product/command-spec.md). -3. Keep `local` local-only. -4. Keep `production` protected and durable. -5. Preserve `workspace -> project -> branch -> { app, database }`. +1. Keep `local` local-only. +2. Keep `production` protected and durable. +3. Preserve `workspace -> project -> branch -> { service, database, bucket }`. ## Update Publish Preparation diff --git a/docs/onboarding/getting-started.md b/docs/onboarding/getting-started.md index c6f6f958..d135f13d 100644 --- a/docs/onboarding/getting-started.md +++ b/docs/onboarding/getting-started.md @@ -18,7 +18,7 @@ pnpm install ```bash pnpm prisma-cli --help pnpm prisma-cli auth whoami -pnpm prisma-cli app deploy --help +pnpm prisma-cli service --help ``` The root `prisma-cli` script runs the TypeScript source entrypoint through `tsx`. @@ -27,12 +27,10 @@ The root `prisma-cli` script runs the TypeScript source entrypoint through `tsx` Before changing behavior, read: -1. [Resource model](../product/resource-model.md) -2. [Command principles](../product/command-principles.md) -3. [Command spec](../product/command-spec.md) -4. [CLI style guide](../product/cli-style-guide.md) -5. [Output conventions](../product/output-conventions.md) -6. [Error conventions](../product/error-conventions.md) +1. [Command principles](../product/command-principles.md) +2. [CLI style guide](../product/cli-style-guide.md) +3. [Output conventions](../product/output-conventions.md) +4. [Error conventions](../product/error-conventions.md) ## Test And Build diff --git a/docs/product/command-spec.md b/docs/product/command-spec.md deleted file mode 100644 index c3f13bdd..00000000 --- a/docs/product/command-spec.md +++ /dev/null @@ -1,2253 +0,0 @@ -# Prisma CLI Beta Command Spec - -## Purpose - -This document defines the public beta command surface. It is the source of -truth for command names, target resolution, and structured behavior. -This file is authoritative for command group scope during beta. - -## Scope - -The beta package includes these command groups: - -- `agent` -- `auth` -- `project` (includes `project env` subgroup) -- `git` -- `branch` -- `database` (includes `database connection` subgroup) -- `bucket` (includes `bucket key` subgroup) -- `app` -- `build` (includes `build logs`) - -The beta package also includes three top-level commands: - -- `version` -- `init` -- `feedback` - -`version` is intentionally outside the workflow groups: it reports CLI build and environment state, requires no auth, no project context, and no network, and is the canonical answer to "is this CLI installed and on the build I expect?" - -`feedback` is also outside the workflow groups: it sends a message to the -Prisma CLI team's feedback service and touches no platform resource, so it -requires no auth, no workspace, and no project context. - -`init` is a top-level workflow verb: it acts on the local project directory -(writing the committed compute config) rather than managing a remote resource, -so it sits beside the ORM's verb register (`generate`, `migrate`, `validate`) -that the unified CLI will absorb. `init` never scaffolds application code; -creating new apps is `create-prisma`'s job. - -The Git repository connection slice uses the `git` group. It does not add a -provider-specific `GitHub` group. - -Out of scope for the current beta: - -- `schema` -- `migrate` -- product-specific namespaces such as `compute` - -## Global Rules - -- Canonical shape is `prisma `. -- `version`, `init`, and `feedback` are the top-level commands outside that shape (see Scope above). -- Every command supports `--json`. -- Shared global flags are: - - `--json` - - `-q`, `--quiet` - - `-v`, `--verbose` - - `--trace` - - `--interactive` - - `--no-interactive` - - `-y`, `--yes` - - `--color` - - `--no-color` -- Universal utility flags also work at the program level: - - `--help` — prints help for the root program or the named command and exits 0. - - `--version` — prints the CLI version and exits 0. Honors `--json` for the structured envelope. No short alias (`-v` is reserved for `--verbose`; `-V` is avoided as a near-collision). -- Long flags use kebab-case. -- Boolean negation uses `--no-`. -- `--json` and non-interactive mode must not block on prompts. -- Automatic update checks are advisory and skipped in CI, `--json`, `--quiet`, - non-TTY stderr, and when `NO_UPDATE_NOTIFIER` is set. When shown, update - notifications are stderr-only human output and do not change the original - command result. -- Public Beta does not read or write committed config files such as `prisma.config.ts` or `.prisma/settings.json` for Project -> Branch resolution. `.prisma/local.json` is a gitignored local pin/cache, not a declarative repo config file. `prisma.app.json` is legacy and no longer read or written. `prisma.compute.ts` supplies typed `app deploy` defaults (app name, app region, app root, framework, entrypoint, HTTP port, env inputs) and never selects Project or Branch scope. -- Remote commands do not silently change local context. - -## Authentication - -The CLI accepts two authentication sources, in this fixed precedence: - -1. `PRISMA_SERVICE_TOKEN` environment variable — long-lived service token, intended for CI and other headless contexts. -2. Stored OAuth session — created by `prisma-cli auth login`, kept in the OS-appropriate credentials store, refreshed automatically. - -Stored OAuth sessions include a short-lived access token and a refresh token. The local credentials store may contain OAuth grants for multiple workspaces. One local active workspace pointer selects which grant authenticated commands use. Commands refresh the selected access token automatically when the API rejects it, coordinate refreshes across concurrent CLI processes, and tolerate short refresh-token rotation races. If the selected session cannot be refreshed, commands fail with a structured `AUTH_REQUIRED` error instead of surfacing SDK stack traces or silently falling through to another workspace. - -When `PRISMA_SERVICE_TOKEN` is set and non-empty, the token is fully sufficient for authenticated commands. If `PRISMA_SERVICE_TOKEN` is set but empty or only whitespace, commands fail with an auth configuration error instead of falling back to stored OAuth. The CLI does not read any locally stored OAuth session when a non-empty service token is present, so behavior is identical on a fresh runner and a developer machine that happens to be signed in. The active workspace is derived from the token's `sub` claim; no additional flag or environment variable is required for the common case where the token is scoped to a single workspace. - -`auth login`, `auth logout`, and `auth workspace` operate on stored OAuth sessions. They do not affect the `PRISMA_SERVICE_TOKEN` environment variable. `auth login` stores the authorized workspace and makes it active. `auth logout` clears all local OAuth workspace sessions. `auth workspace logout` and `auth logout --workspace` clear one local OAuth workspace session, including while `PRISMA_SERVICE_TOKEN` is set, because they only clean local OAuth state. If that workspace was active, the CLI does not silently fall through to another cached workspace; the user must explicitly choose the next workspace with `auth workspace use`. `auth workspace use` changes only local CLI context and never mutates a remote resource. When `PRISMA_SERVICE_TOKEN` is set, workspace switching is unavailable because the token is the active auth source. - -## Context Resolution - -### Project - -Commands resolve project context in this order: - -1. explicit `--project ` when present -2. `PRISMA_PROJECT_ID` when set for headless deploy/domain commands -3. `.prisma/local.json` project pin when present, revalidated against platform data -4. durable platform mapping when available -5. explicit setup choice from `project link`, `project create`, an interactive setup picker, `app deploy --project`, or `app deploy --create-project` -6. structured failure when no explicit or durable Project binding exists - -`--project` is an explicit Project choice. When used from an unbound directory -with `app deploy`, it writes `.prisma/local.json` after validation and before -the deployment starts. `--create-project ` is the explicit deploy-time -choice to create and bind a new Project. Package names and directory names may -suggest setup defaults, but they never authorize Project creation by themselves. -When `PRISMA_PROJECT_ID` is set, `app deploy` and `app domain` commands skip -`.prisma/local.json` reads and do not write a new pin. - -Project-scoped commands never use package-name matching, directory-name -matching, or remembered local context as selected Project scope. Local metadata -may suggest setup defaults and candidate Projects, but only explicit input or -durable state may select a Project. Without a pin, durable mapping, supported -env var, or explicit Project flag, Project-scoped commands fail with -`PROJECT_SETUP_REQUIRED`; `app deploy` may enter explicit interactive setup -before failing. - -### App Selection - -Preview app commands that need an app resolve it in this order: - -1. `--app ` -2. `PRISMA_APP_ID` when set for headless deploy/domain commands -3. compute config target from the `[app]` argument, or inferred from the invocation directory being inside a target's `root`; the target's `name` (or `apps` key) selects the app -4. locally selected app for non-deploy commands when it still exists in the resolved branch -5. inferred app name from `package.json#name` -6. current directory name -7. `app deploy` only: create the inferred app in the resolved branch when no existing app matches -8. interactive picker only when multiple matching apps make the target ambiguous -9. `APP_AMBIGUOUS` in non-interactive or `--json` mode when unresolved - -App management commands (`show`, `open`, `logs`, `list-deploys`, `promote`, -`rollback`, `remove`, `domain`) accept the same `[app]` target argument and -upward config discovery as `app deploy`: the project binding is read from the -config file's directory, and the config target is an additional app-name -source. Unlike deploy, management commands never require a target: with -multiple targets, no argument, and nothing inferred from the invocation -directory, they fall back to the selection order above — except step 7; -management commands never create apps or mutate remote state to resolve one. - -Config `region` and `--region` are not app selectors. They are used only when -`app deploy` creates a new app; existing apps keep their current region. - -`.prisma/local.json` pins the directory to a Workspace and Project only. It does -not pin an App ID. App services are branch-scoped; a service ID from `main` -must not be reused automatically when the user deploys from `feat/billing`. - -`app domain` commands do not create apps. They resolve an existing app on the -resolved production Branch and fail when none exists. - -### Branch - -Deploy resolves the branch it writes to in this order: - -1. explicit branch argument or `--branch ` when the command accepts one -2. active Git branch for local deploy workflows -3. `main` - -App management commands (`show`, `open`, `logs`, `list-deploys`, `promote`, -`rollback`, `remove`) never create branches, so they resolve the branch they -read in this order: - -1. explicit `--branch ` when the command accepts one, honored as-is -2. the active Git branch when a branch with that name exists in the project -3. the project's default (production) branch - -Resolving the default branch from the project keeps a git-push app deployed on -a non-`main` default branch (for example `master`) visible to management -commands regardless of the local Git branch. - -`local` is local CLI context only. It is never a branch or deploy target. -Production is a protected durable branch and must require explicit user intent. - -`app domain` commands default to the production Branch. During Public Beta, -custom domains are supported only on production Branches. Passing a -non-production `--branch` fails with `BRANCH_NOT_DEPLOYABLE`. - -## Command Result Envelopes - -Successful `--json` output uses: - -```json -{ - "ok": true, - "command": "app.deploy", - "result": {}, - "warnings": [], - "nextSteps": [] -} -``` - -Failure `--json` output uses the error envelope defined in -`error-conventions.md`. - -## Auth Result Contract - -`auth login`, `auth logout`, and `auth whoami` return the current auth state. - -In `--json`, `result` uses this shape: - -```json -{ - "authenticated": true, - "provider": "github", - "user": { - "id": "usr_123", - "email": "alice@example.com", - "name": "Alice" - }, - "workspace": { - "id": "wksp_123", - "name": "Acme Inc" - }, - "credential": { - "type": "oauth", - "id": null, - "name": null - } -} -``` - -For service-token sessions, `user` is `null` and `credential` identifies the token when the API can resolve it: - -```json -{ - "authenticated": true, - "provider": null, - "user": null, - "workspace": { - "id": "wksp_123", - "name": "Acme Inc" - }, - "credential": { - "type": "service_token", - "id": "itgr_123", - "name": "ci-deploys-prod" - } -} -``` - -Fallback auth states may omit user details when the deployed Management API does not yet expose `/v1/me`: - -```json -{ - "authenticated": true, - "provider": "github", - "user": { - "email": "alice@example.com" - }, - "workspace": { - "id": "wksp_123", - "name": "Acme Inc" - }, - "credential": null -} -``` - -Rules: - -- `authenticated` is always present -- `provider` is `github`, `google`, or `null` -- `user` contains the current user id, email, and display name when known, a fallback email-only object during rollout, or `null` -- `workspace` is the active workspace or `null` -- `credential` identifies the active credential when known, or is `null` -- signed-out state is an empty auth state, not an error - -`auth workspace list --json` returns local workspace sessions: - -```json -{ - "context": { - "authSource": "oauth", - "activeWorkspaceId": "wksp_123", - "activeWorkspaceName": "Acme Inc" - }, - "items": [ - { - "id": "wksp_123", - "name": "Acme Inc", - "status": "active", - "source": "oauth", - "switchable": true, - "credentialWorkspaceId": "cmmx...", - "lastSeenAt": "2026-06-19T00:00:00.000Z" - } - ], - "count": 1 -} -``` - -`auth workspace use --json` returns: - -```json -{ - "previousWorkspace": { - "id": "wksp_123", - "name": "Acme Inc" - }, - "workspace": { - "id": "wksp_456", - "name": "Prisma Labs" - } -} -``` - -`auth workspace logout --json` returns: - -```json -{ - "workspace": { - "id": "wksp_123", - "name": "Acme Inc" - }, - "wasActive": true, - "activeWorkspace": null -} -``` - -## `prisma-cli version` - -Purpose: - -- report the installed CLI build and a small block of host environment metadata - -Behavior: - -- requires no auth, no project context, and no network -- reads the package's own version from its bundled metadata -- reports CLI name, CLI version, Node.js version, OS platform, OS architecture, and a best-effort `invocation` label (`bunx`, `npx`, `global`, `dev`, or `unknown`) -- uses the `show` output pattern (see `output-conventions.md`) -- fails only when the bundled CLI metadata cannot be read; this is treated as `VERSION_UNAVAILABLE` and is not expected in practice - -In `--json`, `result` uses this shape: - -```json -{ - "cli": { - "name": "prisma-cli", - "version": "3.0.0-beta.0" - }, - "node": { - "version": "v24.14.1" - }, - "os": { - "platform": "darwin", - "arch": "arm64" - }, - "invocation": "bunx" -} -``` - -Rules: - -- `cli.name` is the published package's `bin` name (`prisma-cli` in the current beta). -- `cli.version` is the published package version. -- `node.version` mirrors `process.version` exactly, including the leading `v`. -- `os.platform` and `os.arch` mirror `process.platform` and `process.arch`. -- `invocation` is best-effort and falls back to `"unknown"` when no signal is conclusive. - -Examples: - -```bash -prisma-cli version -prisma-cli version --json -``` - -## `prisma-cli --version` - -Purpose: - -- universal smoke-test flag at the root of the program - -Behavior: - -- prints the CLI version and exits 0 -- requires no auth, no project context, and no network -- works before any subcommand parsing — bare `prisma-cli --version` is sufficient -- in human mode, prints a single line to stdout: `prisma-cli ` -- in `--json` mode, emits the standard success envelope (see Command Result Envelopes) with `command: "version"` and `result.version: ""` -- `--version` is documented as a universal utility flag in Global Rules, not as a shared global flag (it is an early-exit utility, not a per-command modifier) - -Examples: - -```bash -prisma-cli --version -prisma-cli --version --json -``` - -`prisma-cli version` is the richer environment report; `prisma-cli --version` is the terse one-liner. Both report the same `cli.version`. Use the flag for quick checks, the subcommand for support tickets and bug reports. - -## `prisma-cli init --framework --entry --http-port --region --name --link --no-link --project --install --no-install --format ` - -Purpose: - -- write a committed `prisma.compute.ts` (or, with `--format json`, a dependency-free `prisma.compute.json`) for the app in this directory - -Behavior: - -- 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 -- writing the config requires no auth and no network; the only steps that may go remote are the accepted types install, link, and agent skill install, all optional and all after the config is written -- 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 -- `--format ` 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 -- 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 -- with `--format json` and the custom framework, init fails with a usage error: custom needs `build.outputDirectory` and `build.entrypoint`, which init does not collect, and strict JSON cannot carry the commented build stub the TypeScript format uses; the fix is the TypeScript format or a hand-written `build` object -- graduation path: an explicit `--format ts` with an existing `prisma.compute.json` converts it in place; the JSON config is loaded and validated, the equivalent `prisma.compute.ts` wrapping the same object in `defineComputeConfig` is written next to it, the JSON file is then deleted (a failed delete rolls the write back, and a failed rollback fails with `INIT_CONVERT_INCOMPLETE` so two config files never coexist silently), and the types install and link steps run as usual (`--install`/`--no-install`, `--link`/`--no-link`/`--project`) and act on the discovered config directory, not the invocation directory, so a conversion run from a nested app dir installs types and writes the project pin where the config lives; config values are transported, never re-resolved, so the value-resolution flags (`--framework`, `--entry`, `--http-port`, `--name`, `--region`) are usage errors during conversion, and the conversion is reported with `converted: true` -- conversion is one-way and explicit: plain `init` with any existing config still fails with `INIT_CONFIG_EXISTS`, and `--format json` with an existing TypeScript config fails with `INIT_CONVERT_UNSUPPORTED` because TypeScript configs may contain logic that a static JSON file cannot express; a fully static config can be rewritten by hand -- detects the framework from the same registry and signals `app deploy` uses; explicit `--framework` wins over detection -- `--entry` sets the source entrypoint for entrypoint frameworks (Bun, Hono); `--http-port` overrides the framework default port; `--name` overrides the app name inferred from `package.json#name` or the directory name -- previews the resolved values with per-value source annotations (`detected`, `framework default`, `package.json`, `flag`) before writing; in interactive mode the preview is followed by an optional adjust step for framework and HTTP port, and `--yes` accepts the preview as shown -- the generated config pins the app's identity: `name`, `framework`, and `httpPort` always; `entry` when the framework consumes a source entrypoint; `region` only when `--region` is passed, because pinning a region the user did not choose would silently place new apps -- the generated config does not include a `build` block: build settings stay inferred (and shown with their sources by deploy) until the user adds one, which keeps package-manager and build-script inference live -- init never scaffolds application code, never creates schema or database resources, and never deploys -- with `--framework custom`, the config includes a commented `build` stub, since custom artifacts require `build.outputDirectory` and `build.entrypoint` before deploy can use them -- when detection fails and no `--framework` is passed: interactive mode prompts for the framework from the supported list; non-interactive and `--json` mode fail with `INIT_DETECTION_FAILED`, with `nextActions` enumerating the `--framework` choices -- types step, after the config is written: the generated config's typed import (`@prisma/compute-sdk/config`) is resolved by the CLI at deploy time without a local install, so a local `@prisma/compute-sdk` devDependency exists purely for editor types - - when the package is already a dependency or devDependency, the step is a no-op - - interactive mode asks `Install @prisma/compute-sdk for config types?` (default yes) and runs the detected package manager's add command (`pnpm add -D`, `bun add -d`, `yarn add -D`, `npm install -D`) - - `--install` runs the install without prompting; `--no-install` skips the step; non-interactive and `--json` mode skip by default - - a skipped, declined, or failed install downgrades to a hint or warning with the exact add command in `nextSteps`; the config write stands and init exits 0 - - a directory without a `package.json` skips the step with the hint -- link step, after the config is written: - - 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 - - `--no-link` suppresses the question; `--link` requires the step; `--project ` links to that project without prompting - - link failures and cancellations after the config is written downgrade to warnings and `nextSteps`; the config write stands and init exits 0 -- 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 -- `nextSteps` includes the deploy command, plus the project link command when the directory is still unlinked -- 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 -- 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 - -Examples: - -```bash -prisma-cli init -prisma-cli init --framework hono --entry src/index.ts -prisma-cli init --name api --http-port 8080 --no-link -prisma-cli init --project proj_123 -prisma-cli init --format json -prisma-cli init --format ts -prisma-cli init --json -``` - -## `prisma-cli feedback --email ` - -Purpose: - -- send feedback about the CLI to the Prisma team - -Behavior: - -- requires no auth, no workspace, no project context, and no config; never prompts, in any mode -- anonymous by default; `--email
` opts into being contactable, and the address is validated when passed -- attaches non-PII environment context to every submission: CLI version, node version, and OS platform and arch; the command help discloses exactly this list -- the feedback service uses the client IP transiently, in memory, to rate limit submissions; the IP is never stored with the feedback -- `` is required, trimmed, and limited to 4000 characters; an empty or oversized message is a usage error and nothing is sent -- posts to the feedback service with a 3-second timeout; delivery failures (unreachable service, timeout, non-2xx response) fail with `FEEDBACK_SEND_FAILED` and exit 1, and the message is not persisted anywhere locally -- `PRISMA_CLI_FEEDBACK_URL` overrides the service endpoint for testing and staging -- unexpected CLI crashes point here: the human crash message ends with a `Tell us what happened: prisma-cli feedback "..."` hint pre-filled with the failing command and error line (suppressed by `--quiet`), and `--json` crashes return an `UNEXPECTED_ERROR` envelope whose `nextActions` carries the same pre-filled command as a `recover` action; expected failures and usage errors never advertise feedback -- in `--json`, `result` includes the submission `id` returned by the service (null when the response carries none), the `email` sent (null when anonymous), and the attached `context` - -Examples: - -```bash -prisma-cli feedback "the deploy flow is great" -prisma-cli feedback "please add X" --email you@example.com -prisma-cli feedback "agent output is solid" --json -``` - -## ` @prisma/cli@latest agent install --agent --all-agents --skill --global --copy` - -Purpose: - -- install Prisma context for AI coding agents - -Behavior: - -- user-facing agent install commands use the package runner detected from the project: `bunx`, `pnpm dlx`, `yarn dlx`, or `npx -y` -- installs Prisma skills from `prisma/skills` by invoking `skills@latest` through the detected project package manager: - ` skills@latest add prisma/skills --skill "*" --agent codex --agent claude-code --yes` -- detects the runner from the current directory and its ancestors: - - `bun.lock`, `bun.lockb`, or `packageManager: "bun@..."` -> `bunx` - - `pnpm-lock.yaml`, `pnpm-workspace.yaml`, or `packageManager: "pnpm@..."` -> `pnpm dlx` - - `yarn.lock` or `packageManager: "yarn@..."` -> `yarn dlx` - - `package-lock.json`, `npm-shrinkwrap.json`, `packageManager: "npm@..."`, or no package-manager signal -> `npx -y` -- defaults to the `codex` and `claude-code` agent targets because those are the primary local agent workflows during beta -- accepts repeated `--agent ` flags to target specific skills CLI agents, such as `codex`, `claude-code`, or `cursor` -- accepts `--all-agents` to pass `--agent "*"` to the skills CLI -- accepts repeated `--skill ` flags to install a subset such as `prisma-compute` -- accepts `--global` and `--copy` and forwards them to the skills CLI -- accepts `--dry-run` to report the skills CLI command without spawning the installer - -Examples: - -```bash -npx -y @prisma/cli@latest agent install -pnpm dlx @prisma/cli@latest agent install --agent codex -pnpm dlx @prisma/cli@latest agent install --agent codex --agent cursor -pnpm dlx @prisma/cli@latest agent install --all-agents -pnpm dlx @prisma/cli@latest agent install --skill prisma-compute -``` - -## ` @prisma/cli@latest agent update --agent --all-agents --skill --global --copy` - -Purpose: - -- refresh Prisma skills - -Behavior: - -- has the same flags and behavior as `agent install` -- reruns the detected package-manager runner with `skills@latest add prisma/skills ...` instead of `skills update`, so it refreshes only Prisma's skills and works for project-scoped installs - -Examples: - -```bash -npx -y @prisma/cli@latest agent update -pnpm dlx @prisma/cli@latest agent update --agent codex -pnpm dlx @prisma/cli@latest agent update --all-agents -``` - -## ` @prisma/cli@latest agent status --global` - -Purpose: - -- show whether Prisma skills are installed for the current project or globally - -Behavior: - -- resolves the Compute config directory before checking project skills, so running from an app subdirectory still checks the project root -- runs `skills@latest list --json` through the detected package runner and reports installed Prisma skills from the skills CLI by default -- accepts `--global` to run `skills@latest list -g --json` and report globally installed Prisma skills instead -- filters the list to Prisma skills and includes each skill's name, path, scope, and agent targets in JSON output -- for project status, falls back to whether `skills-lock.json` references `prisma/skills` when the skills CLI list command fails -- for global status, reports the Skills CLI list failure instead of falling back to project-local state -- reports whether the project has dismissed the interactive agent setup prompt -- does not require authentication - -Examples: - -```bash -npx -y @prisma/cli@latest agent status -pnpm dlx @prisma/cli@latest agent status --json -pnpm dlx @prisma/cli@latest agent status --global -``` - -## `prisma-cli auth login` - -Purpose: - -- log in to your Prisma platform account - -Behavior: - -- starts the login flow -- stores the resulting session locally -- resolves active workspace when required -- confirms successful browser authentication and directs the user back to the terminal -- returns the current auth state after login -- in human output, when run from a project directory that does not already have Prisma skills and has not dismissed the setup prompt, suggests the detected package-runner command, such as `pnpm dlx @prisma/cli@latest agent install` -- does not install skills during auth; auth is not project-scoped and must not mutate the project -- does not show the agent setup tip in `--json`, `--quiet`, CI, non-TTY output, or directories that do not look like projects - -Examples: - -```bash -prisma-cli auth login -prisma-cli auth login --json -``` - -## `prisma-cli auth logout` - -Purpose: - -- clear all stored OAuth workspace credentials - -Behavior: - -- removes all local OAuth workspace sessions -- with `--workspace `, removes only the target local OAuth workspace session -- succeeds even if no session exists -- returns the signed-out auth state unless `PRISMA_SERVICE_TOKEN` is still set - -Examples: - -```bash -prisma-cli auth logout -prisma-cli auth logout --workspace wksp_123 -prisma-cli auth logout --json -``` - -## `prisma-cli auth whoami` - -Purpose: - -- show the authenticated user and accessible workspace - -Behavior: - -- returns the current auth state -- succeeds when signed out - -Examples: - -```bash -prisma-cli auth whoami -prisma-cli auth whoami --json -``` - -## `prisma-cli auth workspace list` - -Purpose: - -- list locally authenticated workspaces - -Behavior: - -- succeeds when signed out -- lists local OAuth workspaces stored on this machine -- human output includes a table with workspace name and workspace id -- marks the active local workspace when one is selected -- when `PRISMA_SERVICE_TOKEN` is set, shows the token workspace when resolvable and also shows stored local OAuth workspaces as non-switchable until the variable is unset -- does not claim to list every workspace the user can access unless each workspace has been authorized locally -- does not mutate local or remote state - -Examples: - -```bash -prisma-cli auth workspace list -prisma-cli auth workspace list --json -``` - -## `prisma-cli auth workspace use [id-or-name]` - -Purpose: - -- switch or interactively select the local CLI workspace - -Behavior: - -- with `[id-or-name]`, requires a stored OAuth session for the target workspace -- with `[id-or-name]`, accepts the cached workspace id, credential workspace id, or cached workspace name case-insensitively -- without `[id-or-name]`, lists locally authenticated OAuth workspaces in an interactive picker when prompting is available -- without `[id-or-name]`, shows the workspace name and workspace id for each interactive choice -- without `[id-or-name]`, selects the only local OAuth workspace without prompting when exactly one is available -- without `[id-or-name]`, fails in non-interactive mode when more than one local OAuth workspace is available -- changes local CLI context only; it does not mutate a remote resource -- fails with `WORKSPACE_SWITCH_UNAVAILABLE` when `PRISMA_SERVICE_TOKEN` is set -- fails with `WORKSPACE_NOT_AUTHENTICATED` when no cached OAuth session matches -- fails with `WORKSPACE_AMBIGUOUS` when a workspace name matches multiple cached workspaces - -Examples: - -```bash -prisma-cli auth workspace use -prisma-cli auth workspace use wksp_123 -prisma-cli auth workspace use "Acme Inc" -``` - -## `prisma-cli auth workspace logout ` - -Purpose: - -- remove one local OAuth workspace session - -Behavior: - -- requires a stored OAuth session for the target workspace -- accepts the cached workspace id, credential workspace id, or cached workspace name case-insensitively -- removes only the target workspace's local OAuth grant -- works while `PRISMA_SERVICE_TOKEN` is set; the service token remains the active auth source -- if the removed workspace was active, leaves no active local OAuth workspace selected -- does not mutate a remote resource and does not revoke remote access -- fails with `WORKSPACE_NOT_AUTHENTICATED` when no cached OAuth session matches -- fails with `WORKSPACE_AMBIGUOUS` when a workspace name matches multiple cached workspaces - -Examples: - -```bash -prisma-cli auth workspace logout wksp_123 -prisma-cli auth workspace logout "Acme Inc" -``` - -## `prisma-cli project list` - -Purpose: - -- list all projects in your workspace - -Behavior: - -- requires auth -- lists projects visible to the active workspace -- human output shows each Project's name and id -- does not resolve the current directory -- does not mutate local state -- when the current directory is not linked, human output adds setup hints after the list -- in JSON, unlinked directories include a `user-choice` `nextActions` entry for Project setup -- listed Projects are not marked selected unless durable local binding actually selects one -- listed Projects are candidates only; the user must choose one before `project link ` runs -- `branches` is intentionally deferred until `/v1/projects` exposes a branch count in this same response; the CLI must not make per-project branch-list requests to render `project list` - -Examples: - -```bash -prisma-cli project list -prisma-cli project list --json -``` - -## `prisma-cli project show` - -Purpose: - -- show this directory's Prisma Project binding - -Behavior: - -- requires auth -- inspects explicit or durable project context without creating projects -- does not prompt for project selection -- does not mutate local state -- `--project ` resolves only the explicit project -- when bound, returns Workspace, Project, and `resolution.projectSource` -- when bound, human output shows the local repo path, the ` / ` platform label, and the Project URL; it does not show the internal resolution source -- when unbound, human output says `project: Not linked` and shows link/create next steps -- when unbound, JSON exits successfully with `project: null`, `localBinding.status: "not-linked"`, `resolution.projectSource: "unbound"`, a suggested Project name, matching Project candidates, recovery commands, and `user-choice` `nextActions` -- package names and directory names only power unbound suggestions -- fails with `PROJECT_NOT_FOUND`, `PROJECT_AMBIGUOUS`, `LOCAL_PROJECT_WORKSPACE_MISMATCH`, or `LOCAL_STATE_STALE` when explicit or durable binding validation cannot continue safely - -Examples: - -```bash -prisma-cli project show -prisma-cli project show --json -prisma-cli project show --project proj_123 --json -``` - -## `prisma-cli project create [--region ]` - -Purpose: - -- create a Prisma Project and bind the current directory to it - -Behavior: - -- requires auth -- creates a Project in the authenticated workspace -- `--region ` sets the Project's default Compute region; Apps created in the Project inherit this region unless overridden at deploy time with `--region`; when omitted the platform assigns the default region -- writes `.prisma/local.json` with Workspace and Project IDs -- ensures `.prisma/` is ignored by Git -- does not create a Branch, App, Deployment, database, or Git repository connection -- fails if the platform rejects Project creation - -Examples: - -```bash -prisma-cli project create my-app -prisma-cli project create my-app --region us-east-1 -prisma-cli project create my-app --json -``` - -## `prisma-cli project link [id-or-name]` - -Purpose: - -- bind the current directory to a Prisma Project - -Behavior: - -- requires auth -- with `[id-or-name]`, resolves exactly one existing Project by id or name in the authenticated workspace -- without `[id-or-name]` in interactive mode, prompts the user to choose an existing Project, create a new Project, or cancel -- choosing an existing Project writes the local binding and does not create remote resources -- choosing "Create a new Project" prompts for a Project name, creates the Project, and writes the local binding -- without `[id-or-name]` in `--json`, `--no-interactive`, non-TTY, CI, or `--yes` mode, fails with `PROJECT_LINK_TARGET_REQUIRED` -- `--yes` does not choose Project scope -- writes `.prisma/local.json` with Workspace and Project IDs -- ensures `.prisma/` is ignored by Git -- does not create Branch, App, Deployment, database, or Git repository connection state -- fails with `PROJECT_NOT_FOUND` or `PROJECT_AMBIGUOUS` when the Project cannot be selected safely - -Examples: - -```bash -prisma-cli project link -prisma-cli project link proj_123 -prisma-cli project link "Acme Dashboard" --json -``` - -## `prisma-cli project rename --project ` - -Purpose: - -- rename the resolved Prisma Project - -Behavior: - -- requires auth -- renames the resolved Project; accepts `--project ` as an explicit fallback and otherwise uses the directory's durable Project binding -- requires a non-empty `` -- renames the remote Project only; `.prisma/local.json` pins Project IDs, so existing directory bindings stay valid without rewrite -- returns the previous and new name -- does not mutate any other remote resource -- fails with `PROJECT_NOT_FOUND`, `PROJECT_AMBIGUOUS`, or `PROJECT_SETUP_REQUIRED` when the Project cannot be resolved safely -- fails with `PROJECT_RENAME_FAILED` when the platform rejects the rename - -Examples: - -```bash -prisma-cli project rename "Acme Dashboard v2" -prisma-cli project rename billing-api --project proj_123 -prisma-cli project rename billing-api --json -``` - -## `prisma-cli project remove --confirm ` - -Purpose: - -- remove a Prisma Project permanently - -Behavior: - -- requires auth -- resolves `` by exact Project id or exact Project name inside the active workspace -- never defaults to the directory's bound Project: the positional target is required, because removal is destructive -- requires `--confirm ` where the value exactly matches the resolved Project id; `--yes` does not satisfy this confirmation -- removal is permanent: the Project's databases are deleted and its Apps stop being served -- fails with `PROJECT_REMOVE_BLOCKED` when the platform reports the Project still has active deployments; remove or tear down the Apps first -- when this directory's `.prisma/local.json` pin points at the removed Project, the pin is cleared and the result reports it -- fails with `PROJECT_NOT_FOUND` or `PROJECT_AMBIGUOUS` when the target cannot be selected safely - -Examples: - -```bash -prisma-cli project remove proj_123 --confirm proj_123 -prisma-cli project remove "Old Sandbox" --confirm proj_456 -prisma-cli project remove proj_123 --confirm proj_123 --json -``` - -## `prisma-cli project transfer (--to-workspace | --recipient-token ) --confirm ` - -Purpose: - -- transfer a Prisma Project to another workspace - -Behavior: - -- requires auth -- resolves `` by exact Project id or exact Project name inside the active workspace; the positional target is required and never defaults to the directory's bound Project -- exactly one recipient source is required: - - `--to-workspace ` resolves a locally authenticated OAuth workspace, the same targets `auth workspace use` accepts, and authorizes the transfer with that workspace's stored session; this is the same-user path - - `--recipient-token ` passes an access token for the receiving workspace directly; this is the cross-account and headless path -- `--to-workspace` and `--recipient-token` are mutually exclusive; passing neither fails with `TRANSFER_RECIPIENT_REQUIRED` -- `--to-workspace` fails with `WORKSPACE_NOT_AUTHENTICATED` or `WORKSPACE_AMBIGUOUS` when no unique local OAuth session matches, and with `TRANSFER_RECIPIENT_UNAVAILABLE` when `PRISMA_SERVICE_TOKEN` is set, because service-token mode does not read local OAuth sessions -- requires `--confirm ` where the value exactly matches the resolved Project id; `--yes` does not satisfy this confirmation -- after the transfer the Project belongs to the recipient workspace and the source workspace loses access; Project, Branch, App, and database ids are unchanged -- when this directory's `.prisma/local.json` pin points at the transferred Project: with `--to-workspace` the pin's workspace id is rewritten to the recipient workspace, otherwise the pin is cleared; the result reports which happened -- fails with `PROJECT_TRANSFER_REJECTED` when the platform rejects the transfer, for example an invalid or expired recipient token -- fails with `PROJECT_NOT_FOUND` or `PROJECT_AMBIGUOUS` when the target cannot be selected safely - -Examples: - -```bash -prisma-cli project transfer proj_123 --to-workspace "Prisma Labs" --confirm proj_123 -prisma-cli project transfer proj_123 --recipient-token --confirm proj_123 -prisma-cli project transfer proj_123 --to-workspace wksp_456 --confirm proj_123 --json -``` - -## `prisma-cli git connect [git-url]` - -Purpose: - -- connect the resolved Prisma project to a GitHub repository - -Behavior: - -- requires auth -- resolves project context without creating projects -- supports `--project ` for explicit project selection -- if `[git-url]` is provided, parses it as a GitHub repository URL -- if `[git-url]` is omitted, reads the local Git `origin` remote URL -- accepts common GitHub URL forms such as: - - `https://github.com/prisma/prisma-cli` - - `https://github.com/prisma/prisma-cli.git` - - `git@github.com:prisma/prisma-cli.git` -- rejects unsupported providers with `REPO_PROVIDER_UNSUPPORTED` -- stores the repository connection server-side through the Management API -- does not write repository data to `prisma.config.ts` -- does not create branches synchronously -- when the connection is active, enables platform webhook automation to map GitHub branch activity to Prisma Branch state - -Current backend contract: - -- the CLI lists GitHub App installations for the authenticated workspace through the Management API -- if no installation exists, the CLI creates a GitHub App install intent and returns the install URL -- in interactive mode, the CLI attempts to open the install URL in the browser and waits for the installation to become available -- in non-interactive or `--json` mode, the CLI exits with `REPO_INSTALLATION_REQUIRED` and includes the install URL -- the CLI lists repositories visible to the installation and finds the matching `owner/repo` -- if the repository is not visible to any installation, the CLI creates a GitHub App install intent and exposes the install URL -- if the repository still is not visible after the installation or repository-access step, the command fails with `REPO_NOT_ACCESSIBLE` -- if the project is already connected to the same repository, the command returns the existing connection without creating a duplicate -- if the project is already connected to a different repository, the command fails with `REPO_ALREADY_CONNECTED` -- the CLI links the project to the repository with `POST /v1/source-repositories` -- the link call sends `projectId`, `provider: "github"`, `providerRepositoryId`, and `installationId` - -Examples: - -```bash -prisma-cli git connect -prisma-cli git connect git@github.com:prisma/prisma-cli.git -prisma-cli git connect --project proj_123 -prisma-cli git connect https://github.com/prisma/prisma-cli --project proj_123 -``` - -## `prisma-cli git disconnect` - -Purpose: - -- disconnect the GitHub repository from the resolved Prisma project - -Behavior: - -- requires auth -- resolves project context without creating projects -- supports `--project ` for explicit project selection -- removes the active server-side repository connection -- stops future GitHub branch automation for that project -- does not delete the resolved Prisma project -- does not delete existing Branches synchronously; server-side retention rules own that behavior - -Examples: - -```bash -prisma-cli git disconnect -prisma-cli git disconnect --project proj_123 -prisma-cli git disconnect --json -``` - -## `prisma-cli branch list` - -Purpose: - -- list Platform branches for the resolved project - -Behavior: - -- shows known remote branches for the resolved project -- shows each branch's name, role, and role-derived env map (`production` for `role=production`, `preview` for `role=preview`) -- does not create remote state -- does not include branch-specific env overrides, durability, protection, or deployment metadata - -Examples: - -```bash -prisma-cli branch list -prisma-cli branch list --json -``` - -## `prisma-cli database list --project --branch ` - -Purpose: - -- list Prisma Postgres databases for the resolved project - -Behavior: - -- requires auth and resolved project context; accepts `--project ` as an explicit fallback -- lists database metadata only: name, id, branch, region, status, and created timestamp when available -- `--branch ` narrows the list to databases attached to that Branch -- never prints or returns connection strings, passwords, or endpoint secrets -- does not create, delete, or mutate remote state -- uses the standard list JSON envelope with redacted database metadata - -Examples: - -```bash -prisma-cli database list -prisma-cli database list --branch feature/foo -prisma-cli database list --json -``` - -## `prisma-cli database show --project --branch ` - -Purpose: - -- show metadata for one Prisma Postgres database - -Behavior: - -- requires auth and resolved project context; accepts `--project ` as an explicit fallback -- resolves `` by exact database id or exact database name inside the resolved project -- `--branch ` narrows name resolution when the same database name exists on multiple Branches -- returns database metadata and connection metadata only -- never prints or returns connection strings, passwords, or endpoint secrets -- fails with `DATABASE_NOT_FOUND` or `DATABASE_AMBIGUOUS` when the target cannot be selected safely - -Examples: - -```bash -prisma-cli database show db_123 -prisma-cli database show acme-preview --branch preview -prisma-cli database show db_123 --json -``` - -## `prisma-cli database create --project --branch --region ` - -Purpose: - -- create a Prisma Postgres database and return its first one-time connection URL - -Behavior: - -- requires auth and resolved project context; accepts `--project ` as an explicit fallback -- creates an empty Prisma Postgres database in the resolved project -- `--branch ` targets the created database to a Branch when supplied -- `--region ` passes the Prisma Postgres region id when supplied -- the Management API returns the first connection as a one-time-view secret -- in default human mode, stderr shows a short creation summary with the resolved Project and Branch when a Branch is present -- in default human mode, stdout contains exactly one line: the raw connection URL -- human stderr does not repeat, label, or wrap the connection URL -- `--verbose` adds human-only metadata rows such as Workspace, Project, Branch, Database, region, status, and first connection id on stderr before the URL is written to stdout -- `--quiet` suppresses successful stderr output and leaves stdout as exactly the raw connection URL -- in `--json`, `result.connectionString` contains the raw one-time URL exactly once -- no `DATABASE_URL=` or `DIRECT_URL=` formatting is added; consumers decide how to store the URL - -Examples: - -```bash -prisma-cli database create my-db -prisma-cli database create my-db --branch feature/foo --region eu-central-1 -prisma-cli database create my-db --json -``` - -## `prisma-cli database usage --project --branch --from --to ` - -Purpose: - -- show usage metrics for one Prisma Postgres database - -Behavior: - -- requires auth and resolved project context; accepts `--project ` as an explicit fallback -- resolves `` by exact database id or exact database name inside the resolved project -- `--branch ` narrows name resolution when the same database name exists on multiple Branches -- `--from ` and `--to ` bound the reporting period; when omitted, the platform defaults the period to the current month so far -- `--from` and `--to` accept a calendar date (`2026-06-01`) or an ISO datetime (`2026-06-01T12:00:00Z`); a calendar-date `--from` expands to the start of its UTC day and a calendar-date `--to` expands to the end of its UTC day, so `--from 2026-06-01 --to 2026-06-30` is a calendar-day-inclusive June range without relying on server-side end-of-day handling -- the CLI rejects malformed or impossible calendar dates (for example `2026-02-30`) and a `--from` later than `--to` before calling the API -- reports operations used (`ops`) and storage used (`GiB`) for the period, plus the resolved period bounds and the generation timestamp -- read-only; never prints or returns connection strings, passwords, or endpoint secrets -- fails with `DATABASE_NOT_FOUND` or `DATABASE_AMBIGUOUS` when the target cannot be selected safely - -Examples: - -```bash -prisma-cli database usage db_123 -prisma-cli database usage acme-production --from 2026-06-01 --to 2026-06-30 -prisma-cli database usage db_123 --json -``` - -## `prisma-cli database backup` - -Manage backups for a database. `backup` is nested under `database` because -backups exist only in the context of one Prisma Postgres database, following -the same parent-noun/subordinate-noun/action shape as `database connection`. -The platform creates backups automatically; the first slice is read-only. - -### `prisma-cli database backup list --limit ` - -Purpose: - -- list backups for a database - -Behavior: - -- requires auth and resolved project context; accepts `--project ` as an explicit fallback -- resolves `` by exact database id or exact database name inside the resolved project -- supports `--branch ` to narrow database name resolution -- `--limit ` caps the number of returned backups; the platform accepts 1 to 100 and defaults to 25 -- lists backup id, type (`full` or `incremental`), status (`running`, `completed`, `failed`, or `unknown`), size when available, and created timestamp -- includes the platform's backup retention window in days -- read-only; never prints or returns secret values -- fails with `DATABASE_BACKUPS_UNSUPPORTED` when the platform reports backups are not available for the database (for example remote/BYO databases) -- fails with `DATABASE_NOT_FOUND` or `DATABASE_AMBIGUOUS` when the target cannot be selected safely - -Examples: - -```bash -prisma-cli database backup list db_123 -prisma-cli database backup list acme-production --limit 50 -prisma-cli database backup list db_123 --json -``` - -## `prisma-cli database restore --backup --source-database --confirm ` - -Purpose: - -- restore a database's data from a backup - -Behavior: - -- requires auth and resolved project context; accepts `--project ` as an explicit fallback -- restores into the resolved `` (the target): all current data is immediately and irreversibly overwritten with the backup contents; connections and credentials are preserved, so no new connection URL is printed -- resolves `` by exact database id or exact database name inside the resolved project; `--branch ` narrows name resolution -- `--backup ` is required and names the backup to restore from; ids come from `database backup list` -- by default the backup must belong to the target database; `--source-database ` restores from another database's backup, for example a production backup into a scratch database, and requires access to both databases' projects -- requires `--confirm ` where the value exactly matches the resolved target database id; `--yes` does not satisfy this confirmation -- the restore runs asynchronously: the target database status becomes `recovering` until the restore completes, and `database show` reports the current status; `nextSteps` includes the show command -- fails with `DATABASE_BACKUP_NOT_FOUND` when the backup id cannot be resolved for the source database -- fails with `DATABASE_RESTORE_CONFLICT` when the target database is provisioning or already recovering -- fails with `DATABASE_NOT_FOUND` or `DATABASE_AMBIGUOUS` when a database target cannot be selected safely -- never prints or returns connection strings, passwords, or endpoint secrets - -Examples: - -```bash -prisma-cli database restore db_123 --backup bkp_456 --confirm db_123 -prisma-cli database restore scratch --backup bkp_456 --source-database acme-production --confirm db_789 -prisma-cli database restore db_123 --backup bkp_456 --confirm db_123 --json -``` - -## `prisma-cli database remove --confirm ` - -Purpose: - -- remove a Prisma Postgres database - -Behavior: - -- requires auth and resolved project context; accepts `--project ` as an explicit fallback -- resolves `` by exact database id or exact database name inside the resolved project -- requires `--confirm ` where the value exactly matches the resolved database id -- `--yes` does not satisfy this confirmation -- removes the database and its connection metadata through the Management API -- never prints or returns connection strings, passwords, or endpoint secrets - -Examples: - -```bash -prisma-cli database remove db_123 --confirm db_123 -``` - -## `prisma-cli database connection` - -Manage one-time-view connection strings for a database. - -`connection` is nested under `database` because connection strings are only -valid in the context of a Prisma Postgres database. The subgroup mirrors the -`project env ` shape: the parent command names the resource family, -the nested noun names the subordinate resource, and the final token is the -action. There is no `database connection show` command because connection -strings are one-time-view secrets: the platform returns them only from -`connection create` and `connection rotate`, never from read endpoints. - -### `prisma-cli database connection list ` - -Purpose: - -- list connection metadata for a database - -Behavior: - -- requires auth and resolved project context; accepts `--project ` as an explicit fallback -- resolves `` by exact database id or exact database name inside the resolved project -- supports `--branch ` to narrow database name resolution -- lists connection names, ids, and created timestamps when available -- never prints or returns connection strings, passwords, or endpoint secrets - -Examples: - -```bash -prisma-cli database connection list db_123 -prisma-cli database connection list acme-preview --branch preview -prisma-cli database connection list db_123 --json -``` - -### `prisma-cli database connection create --name ` - -Purpose: - -- create a new one-time-view connection URL for a database - -Behavior: - -- requires auth and resolved project context; accepts `--project ` as an explicit fallback -- resolves `` by exact database id or exact database name inside the resolved project -- supports `--branch ` to narrow database name resolution -- `--name ` sets the connection metadata name; when omitted, the CLI generates a `cli-YYYYMMDDhhmmssSSS-xxxx` name -- in default human mode, stderr shows a short creation summary with the resolved Project and Branch when a Branch is present -- in default human mode, stdout contains exactly one line: the raw connection URL -- human stderr does not repeat, label, or wrap the connection URL -- default human stderr does not show generated connection names; use `--verbose` or `--json` for connection metadata -- `--verbose` adds human-only metadata rows such as Workspace, Project, Branch, Database, and connection id on stderr before the URL is written to stdout -- `--quiet` suppresses successful stderr output and leaves stdout as exactly the raw connection URL -- in `--json`, `result.connectionString` contains the raw one-time URL exactly once -- no `DATABASE_URL=` or `DIRECT_URL=` formatting is added; consumers decide how to store the URL - -Examples: - -```bash -prisma-cli database connection create db_123 -prisma-cli database connection create db_123 --name readonly -prisma-cli database connection create db_123 --json -``` - -### `prisma-cli database connection rotate --confirm ` - -Purpose: - -- rotate a database connection's credentials and print the new one-time connection URL - -Behavior: - -- requires auth -- treats `` as the connection id to rotate -- requires `--confirm ` where the value exactly matches the connection id; `--yes` does not satisfy this confirmation, because rotation revokes the previous credentials (best-effort) and breaks clients still using them -- mints new credentials for the same connection; the connection id and name are unchanged -- the new connection URL is a one-time-view secret with the same output contract as `database connection create`: - - in default human mode, stderr shows a short rotation summary and stdout contains exactly one line, the raw new connection URL - - human stderr does not repeat, label, or wrap the connection URL - - `--verbose` adds human-only metadata rows such as database and connection id on stderr before the URL is written to stdout - - `--quiet` suppresses successful stderr output and leaves stdout as exactly the raw connection URL - - in `--json`, `result.connectionString` contains the raw one-time URL exactly once -- no `DATABASE_URL=` or `DIRECT_URL=` formatting is added; consumers decide how to store the URL -- fails with `DATABASE_CONNECTION_NOT_FOUND` when the connection does not exist - -Examples: - -```bash -prisma-cli database connection rotate conn_123 --confirm conn_123 -prisma-cli database connection rotate conn_123 --confirm conn_123 --json -``` - -### `prisma-cli database connection remove --confirm ` - -Purpose: - -- remove a database connection - -Behavior: - -- requires auth -- treats `` as the connection id to remove -- requires `--confirm ` where the value exactly matches the connection id -- `--yes` does not satisfy this confirmation -- never prints or returns connection strings, passwords, or endpoint secrets - -Examples: - -```bash -prisma-cli database connection remove conn_123 --confirm conn_123 -``` - -## `prisma-cli bucket` - -Manage Tigris-backed object-store buckets for a project. `bucket` is a -top-level group, parallel to `database`, because buckets are branch-scoped -platform resources with their own key-management subgroup. - -`bucket key` is nested under `bucket` because access keys exist only in the -context of one bucket. There is no `bucket key show` command because the secret -access key is a one-time-view secret: the platform returns it only from -`bucket key create`. - -### `prisma-cli bucket list --project --branch ` - -Purpose: - -- list object-store buckets for the resolved project - -Behavior: - -- requires auth and resolved project context; accepts `--project ` as an explicit fallback -- lists bucket metadata only: name, id, status, branch id, and created timestamp -- `--branch ` narrows the list to buckets attached to that branch -- does not create, delete, or mutate remote state -- uses the standard list JSON envelope with bucket metadata - -In `--json`, `result` uses this shape: - -```json -{ - "context": { "project": "Acme Dashboard" }, - "items": [ - { "name": "acme-preview-store", "id": "bkt_123", "status": "ready" } - ], - "count": 1, - "projectId": "proj_123", - "branchName": null, - "buckets": [ - { - "id": "bkt_123", - "name": "acme-preview-store", - "status": "ready", - "branchId": "br_123", - "createdAt": "2026-06-01T00:00:00.000Z" - } - ] -} -``` - -Examples: - -```bash -prisma-cli bucket list -prisma-cli bucket list --branch preview -prisma-cli bucket list --json -``` - -### `prisma-cli bucket create --name --project --branch ` - -Purpose: - -- create an object-store bucket in the resolved project - -Behavior: - -- requires auth and resolved project context; accepts `--project ` as an explicit fallback -- `--name ` sets the bucket display name; when omitted, the platform assigns an auto-generated name -- `--branch ` scopes the bucket to that branch; when omitted, the bucket is unscoped and visible across all branches -- the bucket is created with `ready` status when provisioning succeeds -- fails with `BRANCH_NOT_FOUND` when `--branch` names a branch that does not exist in the resolved project - -In `--json`, `result` uses this shape: - -```json -{ - "projectId": "proj_123", - "projectName": "Acme Dashboard", - "bucket": { - "id": "bkt_123", - "name": "acme-preview-store", - "status": "ready", - "branchId": "br_123", - "createdAt": "2026-06-01T00:00:00.000Z" - } -} -``` - -Examples: - -```bash -prisma-cli bucket create -prisma-cli bucket create --name my-store -prisma-cli bucket create --branch preview --json -``` - -### `prisma-cli bucket delete --confirm ` - -Purpose: - -- permanently delete a bucket, all objects stored in it, and all its access keys - -Behavior: - -- requires auth -- treats `` as the bucket id to delete -- requires `--confirm ` to match the positional argument exactly; - exits with code 2 and `CONFIRMATION_REQUIRED` if the flag is missing or - does not match -- cascades the deletion through the Management API: all stored objects are - removed and then all access keys are revoked before the bucket is destroyed -- fails with `BUCKET_NOT_FOUND` when the bucket id does not exist - -In `--json`, `result` uses this shape: - -```json -{ - "bucket": { "id": "bkt_123" } -} -``` - -Examples: - -```bash -prisma-cli bucket delete bkt_123 --confirm bkt_123 -prisma-cli bucket delete bkt_123 --confirm bkt_123 --json -``` - -### `prisma-cli bucket key list ` - -Purpose: - -- list access keys for a bucket - -Behavior: - -- requires auth -- lists key metadata only: name, id, role, value hint, and created timestamp -- never prints or returns the secret access key -- fails with `BUCKET_NOT_FOUND` when the bucket id does not exist - -In `--json`, `result` uses this shape: - -```json -{ - "context": { "bucket": "bkt_123" }, - "items": [ - { "name": "primary", "id": "bkey_123", "status": null } - ], - "count": 1, - "bucketId": "bkt_123", - "keys": [ - { - "id": "bkey_123", - "name": "primary", - "role": "read_write", - "valueHint": "AKIABKT123...", - "createdAt": "2026-06-01T00:00:00.000Z" - } - ] -} -``` - -Examples: - -```bash -prisma-cli bucket key list bkt_123 -prisma-cli bucket key list bkt_123 --json -``` - -### `prisma-cli bucket key create --role --name ` - -Purpose: - -- create an access key for a bucket and print its one-time credentials as an S3-compatible env block - -Behavior: - -- requires auth -- `--role ` sets the access role; defaults to `read_write`; Commander validates the choice at parse time — any other value is rejected as a usage error before the action runs -- `--name ` sets the key display name; when omitted, the platform assigns an auto-generated name -- the secret access key is a one-time-view secret: it is returned only from this command and cannot be retrieved again -- in default human mode, stderr shows a short creation summary with a "shown once" warning; stdout contains exactly four lines — the S3-compatible env block: - ``` - S3_ENDPOINT= - S3_ACCESS_KEY_ID= - S3_SECRET_ACCESS_KEY= - S3_BUCKET= - ``` -- human stderr does not repeat, label, or wrap the credential values -- `--quiet` suppresses successful stderr output and leaves stdout as exactly the four-line env block -- in `--json`, `result` contains the full credential set exactly once, including `secretAccessKey` -- fails with `BUCKET_NOT_FOUND` when the bucket id does not exist -- fails with `BUCKET_KEY_SECRET_MISSING` when the Management API response does not include the one-time credential payload - -In `--json`, `result` uses this shape: - -```json -{ - "bucketId": "bkt_123", - "key": { - "id": "bkey_456", - "name": "ci-key", - "role": "read", - "valueHint": "AKIABKT456...", - "createdAt": "2026-06-09T00:00:00.000Z" - }, - "secretAccessKey": "", - "accessKeyId": "", - "endpoint": "https://fly.storage.tigris.dev", - "bucketName": "acme-preview-store" -} -``` - -Examples: - -```bash -prisma-cli bucket key create bkt_123 -prisma-cli bucket key create bkt_123 --role read -prisma-cli bucket key create bkt_123 --name ci-key --role read_write -prisma-cli bucket key create bkt_123 --json -``` - -### `prisma-cli bucket key delete ` - -Purpose: - -- revoke and delete a bucket access key - -Behavior: - -- requires auth -- treats `` and `` as the bucket id and key id to target -- revokes and removes the access key through the Management API -- fails with `BUCKET_NOT_FOUND` when the bucket id does not exist -- fails with `BUCKET_KEY_NOT_FOUND` when the key id does not exist for the bucket - -In `--json`, `result` uses this shape: - -```json -{ - "key": { "id": "bkey_123" } -} -``` - -Examples: - -```bash -prisma-cli bucket key delete bkt_123 bkey_123 -prisma-cli bucket key delete bkt_123 bkey_123 --json -``` - -## `prisma-cli app build [app] --entry --build-type ` - -Purpose: - -- build the app locally into a deployable artifact - -Behavior: - -- resolves the optional `[app]` target, app root, framework, and entrypoint from `prisma.compute.ts` exactly like `app deploy`; explicit `--entry` and a non-`auto` `--build-type` override the config -- detects supported project shapes when `--build-type auto` is used and no config framework applies; an explicit `--entry` targets a Bun build and wins over that detection, exactly like `app deploy` resolves `--entry` -- supports Bun, Next.js, Nuxt, Astro, NestJS, TanStack Start, and custom artifact app builds in the beta package -- fails with `USAGE_ERROR` when framework detection is ambiguous - -Examples: - -```bash -prisma-cli app build --build-type nextjs -prisma-cli app build --build-type nuxt -prisma-cli app build --build-type astro -prisma-cli app build --build-type nestjs -prisma-cli app build --build-type tanstack-start -prisma-cli app build --build-type bun --entry server.ts -prisma-cli app build api -prisma-cli app build frontend -``` - -## `prisma-cli app run [app] --entry --build-type --port ` - -Purpose: - -- run your app locally - -Behavior: - -- resolves the optional `[app]` target, app root, framework, entrypoint, and port from `prisma.compute.ts` exactly like `app deploy`; explicit `--entry`, `--port`, and a non-`auto` `--build-type` override the config -- fails with `USAGE_ERROR` when the configured framework has no local dev server in the current preview -- detects supported project shapes when `--build-type auto` is used and no config framework applies; an explicit `--entry` targets a Bun app and wins over that detection, exactly like `app deploy` resolves `--entry` -- starts the local framework command -- reports `RUN_FAILED` when the local process cannot start or exits unsuccessfully - -Examples: - -```bash -prisma-cli app run --build-type nextjs -prisma-cli app run --build-type bun --entry server.ts --port 3000 -prisma-cli app run api -``` - -## `prisma-cli app deploy [app] --project --create-project --app --branch --framework --entry --http-port --region --env --db --no-db --prod --no-promote` - -Purpose: - -- creates a new deployment for the app - -Compute config file (`prisma.compute.ts`): - -- deploy reads an optional typed config file, using the nearest one from the invocation directory up to the repository or workspace root (the closest ancestor with `.git`, `pnpm-workspace.yaml`, `bun.lock`, or a `workspaces` field); without such a boundary only the invocation directory is checked, so discovery never escapes the repository -- per directory, exactly one of `prisma.compute.ts`, `prisma.compute.mts`, `prisma.compute.js`, `prisma.compute.mjs`, or `prisma.compute.cjs` may exist -- config-relative paths (`root`, `env.file`) resolve from the config file's directory, so the config means the same thing from any working directory; `--env` flag paths still resolve from the invocation directory -- when a config is discovered, its directory is the project directory: `.prisma/local.json` is read and written there, the local CLI state cache (`.prisma/cli/state.json`) lives there, and `--db` scans for Prisma schema sources there (for prompting and suggestions only); locating the config for these purposes never evaluates it -- the config default-exports `defineComputeConfig({ ... })` from `@prisma/compute-sdk/config` (the shared compute config contract; the CLI loader resolves the import without a local install); the helper is an identity function, so plain object exports also work for JavaScript configs -- the config defines exactly one of: - - `app` — a single-app repository - - `apps` — a multi-app or monorepo repository, keyed by deploy target name -- each app accepts `name`, `region`, `root`, `framework`, `entry`, `httpPort`, `env`, and `build`: - - `region` is the Compute region id used when deploy creates a new app; existing apps keep their current region - - `env` is a dotenv file path, or `{ file, vars }` with file path(s) and inline assignments - - `build` is `{ command, outputDirectory, entrypoint }`; all fields are optional except where a framework requires enough information to stage a runnable artifact, and `command: null` skips the build step - - `build.entrypoint` is the built artifact entrypoint when `outputDirectory` is set, and is the source entrypoint for Bun/Hono configs that do not set an output directory - - `framework: "custom"` deploys a prebuilt or custom-built artifact and requires `build.outputDirectory` and `build.entrypoint` -- when `build` is present, the compute config owns build settings for that app: fields it sets override framework defaults, fields it omits are inferred; without a `build` block, settings are inferred entirely, with their sources shown -- the compute config does not declare databases in the current beta; database setup stays on the `--db`/`--no-db` flags (a future project-level `database` field is the reserved growth path, since databases are branch resources shared by every app on the branch) - -Unification note (forward-looking, normative for design decisions): Prisma ORM -ships `prisma.config.ts` (`defineConfig` from `prisma/config`). The compute -config is designed to become a `compute` key inside that unified file: its -shape must remain self-contained, must not add top-level keys that collide -with ORM config keys, and `database.schema` will become unnecessary once the -unified file's own `schema` field is in scope. Project, branch, and -production targeting stay out of committed config in the unified file for the -same reasons they are excluded today. -- config values are deploy defaults; explicit flags always win: `--framework`, `--entry`, `--http-port`, and `--region` override per value, and any `--env` flag replaces the config env inputs entirely -- the config `name` (or the `apps` key when `name` is absent) selects the app like `--app`, but ranks below both `--app` and `PRISMA_APP_ID` -- `--region` and config `region` apply only when the resolved app does not exist yet and deploy creates it; `--app` and `PRISMA_APP_ID` still control which app is selected -- `root` is a relative path inside the repository; framework detection, entrypoint resolution, build settings, and the build/upload run in that directory while Project binding and the local pin stay in the config file's directory -- `prisma.compute.ts` never selects Project or Branch scope; project resolution is unchanged -- the `[app]` argument selects an `apps` target by key: - - without an `[app]` argument, a command run from inside a target's `root` selects that target, so `cd apps/api && prisma-cli app deploy` deploys `api`; the deepest matching root wins and an ambiguous tie selects nothing - - with multiple `apps` entries, no `[app]` argument, and no target inferred from the invocation directory, deploy deploys every target sequentially in declaration order — the config declares the system, and a bare `prisma-cli app deploy` ships it - - deploying all targets rejects per-app inputs (`--app`, `--framework`, `--entry`, `--http-port`, `--region`, `--env`, `PRISMA_APP_ID`) with a usage error; project- and branch-level flags (`--project`, `--create-project`, `--branch`, `--db`, `--no-db`, `--prod`, `--no-promote`, `--yes`) apply to the whole run, with `--create-project` creating and binding the Project once before the first target - - a deploy-all run stops at the first failure and reports the targets already live; `--json` output aggregates one full deploy result per target - - `app build` and `app run` still require a target in multi-app configs and fail with `COMPUTE_CONFIG_TARGET_REQUIRED` (a dev server cannot run N apps at once; build keeps the same shape) - - an `[app]` argument that matches no target fails with `COMPUTE_CONFIG_TARGET_UNKNOWN` - - a single-entry `apps` map deploys its only target without an argument - - with a single `app` config, `[app]` is accepted only when it equals the configured `name` - - `[app]` without any compute config file is a usage error -- a config that fails to load or validate fails with `COMPUTE_CONFIG_INVALID` before any remote work -- settings sourced from the config are annotated `set by prisma.compute.ts` in human output and deploy settings metadata -- `deploySettings.config.path` reports the compute config file in effect whenever one loaded, even when it has no `build` block, so `path: null` means "no config loaded" rather than "no build block"; `deploySettings.config.status` stays `"config"` when the build block owned the build settings and `"inferred"` when they came from framework defaults - -```ts -import { defineComputeConfig } from "@prisma/compute-sdk/config"; - -// Single-app repository: prisma-cli app deploy -export default defineComputeConfig({ - app: { - name: "api", - region: "eu-central-1", - framework: "hono", - httpPort: 8080, - env: ".env", - }, -}); - -// Multi-app repository: prisma-cli app deploy web -export default defineComputeConfig({ - apps: { - web: { root: "apps/web", framework: "nextjs" }, - worker: { root: "apps/worker", framework: "bun", entry: "src/index.ts" }, - frontend: { - root: "apps/frontend", - framework: "custom", - build: { - command: "npm run build", - outputDirectory: "build", - entrypoint: "handler.js", - }, - }, - }, -}); -``` - -Behavior: - -- requires auth -- resolves project context from `--project`, `--create-project`, `PRISMA_PROJECT_ID`, `.prisma/local.json`, durable platform mapping, or an interactive setup choice -- does not infer and create Project context from `package.json#name` or current directory name without explicit setup -- when no Project is resolved in interactive mode, asks which Project the directory should use: - - ```text - ? Which Project should this directory use? - ❯ + Create a new Project - Acme Dashboard - Billing API - Cancel - ``` - -- "Create a new Project" is listed first, highlighted with a `+` glyph that does not rely on color, so it stays reachable without paging through a long project list; Cancel is last -- when "Create a new Project" is selected, prompts for a Project name with the package/directory name as a suggestion -- when no Project is resolved in `--json` / `--no-interactive` mode, fails with `PROJECT_SETUP_REQUIRED` -- `PROJECT_SETUP_REQUIRED` preserves readable recovery commands in `nextSteps` and includes structured `nextActions` for choosing, linking, creating, or retrying with an explicit Project -- `--yes` alone does not choose Project scope; use `--project` or `--create-project` -- `--project` and `--create-project` are mutually exclusive with each other and with `PRISMA_PROJECT_ID` -- resolves or creates branch context from `--branch`, local Git branch, or `main` -- treats only the resolved Branch `role` as production authority; branch name, `main`, `production`, and `isDefault` are not production authority -- resolves or creates app context inside the resolved branch from `--app`, `PRISMA_APP_ID`, `package.json#name`, or current directory name -- auto-promotes the first production deploy for an App without `--prod` -- requires `--prod` for subsequent deploys to a production Branch; `--yes` only skips the confirmation prompt when `--prod` is also present -- supports `--no-promote` to build a new deployment without promoting it to live: the previous deployment keeps serving, and the new deployment is reachable only at its own candidate URL until a later `app promote ` makes it live -- `--no-promote` never replaces the live deployment, so it bypasses the production gate: `app deploy --no-promote` on a production Branch builds a candidate without `--prod` and without confirmation. It is the CI build-then-verify path — build the candidate, health-check its URL, then `app promote` -- does not prompt when there is no real choice; zero matching apps creates the inferred app -- writes `.prisma/local.json` after Project binding succeeds and before build/deploy starts, so retries after a failed deploy do not repeat setup -- before asking `Customize build settings? (y/N)`, previews the detected framework and runtime so the user can see the defaults they are accepting or changing -- asks `Customize build settings? (y/N)` only while binding the directory for the first time, and only asks for Framework and HTTP port when the user opts in -- resolves build settings from the compute config `build` block over framework inference; nothing is read from or written to disk for them: - - `Build Command` prefers ` run build` when `package.json` has `scripts.build` - - the package manager is detected from the app directory first, then from each ancestor up to the repository or workspace root, so workspace apps build with the workspace package manager - - build commands run with every `node_modules/.bin` between the app and the repository or workspace root on `PATH`, so hoisted workspace binaries resolve - - otherwise `Build Command` falls back to the framework default, such as `next build` - - `Output Directory` is a literal framework output path, such as `.next/standalone`, `.output`, or `.` - - `Entrypoint` is shown when the config or framework settings provide a concrete built artifact entrypoint -- `prisma.app.json` is legacy and never read or written; a leftover file that matches the resolved settings produces a deletion warning, an unparsable one is ignored with a warning, and one with custom values fails with `BUILD_SETTINGS_MIGRATION_REQUIRED` including the exact `build` block to move into `prisma.compute.ts` -- after setup, deploy prints `Deploying to / / `; later deploys print a compact target header such as `Deploying ./j1 to j1 / main / j1` -- deploy progress uses short stage copy (`Building locally...`, `Built `, `Uploading...`, `Uploaded`, `Deploying...`, `Deployed`) and never prints `Status: running` or `Deployment is running at ...` -- success human output prints `Live in `, the URL on its own line, and `Logs prisma-cli app logs` -- when the deploy resolved its settings without a compute config, success human output adds a `Config` hint line with the runner-formatted init command (such as `pnpm dlx @prisma/cli@latest init`), pointing at the command that pins the inferred settings; the hint is omitted once a config file is discovered -- with `--no-promote`, success human output instead prints `Built in (not promoted)`, the candidate URL on its own line, a note that the live deployment is unchanged, and a `Promote prisma-cli app promote ` next step -- accepts repeated `--env NAME=VALUE` flags and dotenv file paths such as `--env .env` -- supports `--db` to create a new empty Prisma Postgres database and write `DATABASE_URL` and `DIRECT_URL` through the existing `project env` storage; the CLI never runs schema or migration commands — applying the schema stays with the user's own tooling -- `--db` is the opinionated single-database path: it creates **one** branch database and exposes `DATABASE_URL`/`DIRECT_URL` as branch-scoped env vars, so every app on the branch shares it. In a multi-app deploy-all run the database is created once (on the first target) and reused by the rest; the run never creates a database per app. Per-app or per-service database topologies are explicit-configuration territory — set each app's database env vars yourself rather than relying on `--db` to infer app-to-database ownership -- supports `--no-db` to suppress automatic database prompting for the deploy -- `--db` and `--no-db` are mutually exclusive; passing both is rejected -- `--yes` alone never creates a database; CI must pass `--db --yes` to create and wire one -- preview Branch setup writes branch-scoped env-var overrides -- production setup writes production env vars only during the first production deploy, before the selected App has a live deployment -- later production deploys do not prompt for database setup; explicit `--db` is rejected once the selected production App has a live deployment -- database setup never overwrites an existing branch-scoped `DATABASE_URL`; when the branch already has `DATABASE_URL`, `--db` leaves branch database env vars unchanged and continues -- production setup treats existing production `DATABASE_URL` or `DIRECT_URL` as BYO DB intent; it does not prompt, and explicit `--db` leaves production env vars unchanged and continues with a warning -- when only `DIRECT_URL` exists on a preview branch, explicit `--db` treats it as partial setup and repairs the pair by writing fresh branch database env values -- if env-var wiring fails after database creation, the CLI deletes the newly created database before returning the error -- after creating a database, the CLI emits a warning that the database is empty and suggests a schema command based on the detected local schema source (`prisma migrate deploy` when `prisma/migrations` exists, `prisma db push` for a bare `schema.prisma`, `prisma-next db init` for a Prisma Next config); the suggestion is never executed -- known non-Postgres Prisma sources do not trigger automatic database prompting; explicit `--db` is rejected because the created database is Prisma Postgres -- `--env DATABASE_URL=...`, `--env DIRECT_URL=...`, or the same keys loaded from an env file suppress automatic database prompting; combining those database env vars with `--db` is rejected -- maps user-facing framework names to deploy build strategies -- does not accept `--build-command` or `--output-directory`; custom build settings live in the `build` block of `prisma.compute.ts` -- deploys arbitrary framework output with `framework: "custom"` when the config provides a built output directory and entrypoint; `build.command` is optional for prebuilt artifacts -- 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 -- does not prompt for agent setup in `--json`, `--quiet`, CI, `--no-interactive`, or `--yes` -- 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 -- supports vanilla Bun apps with `--framework bun` using `package.json#main` or `package.json#module`, or with `--entry ` -- treats `--entry ` without `--framework` as a Bun app deploy -- does not print secret values -- returns app, deployment id, URL, deploy settings including build settings origin metadata, and next steps in `--json` output - -Examples: - -```bash -prisma-cli app deploy -prisma-cli app deploy --project proj_123 -prisma-cli app deploy --create-project my-app --yes -prisma-cli app deploy --app my-app --env DATABASE_URL=postgresql://example -prisma-cli app deploy --app my-app --region us-west-1 -prisma-cli app deploy --db -prisma-cli app deploy --db --yes -prisma-cli app deploy --no-db -prisma-cli app deploy --framework nextjs --http-port 3000 -prisma-cli app deploy --branch feat-login --framework hono --http-port 3000 -prisma-cli app deploy --prod --yes -prisma-cli app deploy --no-promote -prisma-cli app deploy --framework bun --entry src/server.ts --http-port 3000 -prisma-cli app deploy --entry src/server.ts --http-port 3000 -prisma-cli app deploy web -prisma-cli app deploy worker --branch feat-queue -``` - -## `prisma-cli project env` - -Manage durable, platform-stored environment variables for the resolved -project. The `env` namespace operates on the -platform-managed `/v1/environment-variables` API; values are stored -encrypted at rest and **never returned** by the platform — read-back -is not supported in Beta. - -### Scope flags - -Every write targets exactly one scope: - -- `--role ` targets a project template. -- `--branch ` targets a preview branch override. -- `--role` and `--branch` are mutually exclusive. -- For write verbs (`add`, `update`, `remove`), one scope flag is required - so the CLI never silently writes to production. -- For read verbs (`list`), omitting `--role` or `--branch` resolves from - the active local Git branch when one exists; outside a Git branch it - shows a production/preview project-level overview. - -### `prisma-cli project env add (KEY=VALUE | --file ) (--role | --branch )` - -Purpose: - -- create a new environment variable on the targeted scope. Fails if a - variable with the same key already exists. - -Behavior: - -- requires auth and a resolved project; accepts `--project ` as an explicit fallback -- KEY=VALUE is parsed from a single positional; KEY must match - `[A-Z_][A-Z0-9_]*` -- KEY without `=VALUE` reads the value from the current process environment -- `--file ` reads KEY=VALUE assignments from a dotenv file relative to - the current directory; `--file` is mutually exclusive with the positional - assignment -- file imports validate the whole file before writing; duplicate keys, invalid - keys, empty values, or existing target variables fail before any variables are - created -- if a variable with the same key already exists in the scope, the - command fails with a clear error directing to `env update` -- branch-only variables are allowed; the CLI warns when the key does - not exist in the preview template -- the response carries metadata only — the value is never echoed back - -Examples: - -```bash -prisma-cli project env add STRIPE_KEY=sk_test_xxx --role production -prisma-cli project env add STRIPE_KEY=sk_test_xxx --role preview -prisma-cli project env add --file .env --role preview -prisma-cli project env add DATABASE_URL=postgresql://branch --branch feature/foo -prisma-cli project env add --file .env.local --branch feature/foo -API_URL=https://api.example prisma-cli project env add API_URL --project proj_123 --role preview -``` - -### `prisma-cli project env update (KEY=VALUE | --file ) (--role | --branch )` - -Purpose: - -- replace the value of an existing environment variable on the - targeted scope. Fails if no variable with the given key exists. - -Behavior: - -- requires auth and a resolved project; accepts `--project ` as an explicit fallback -- KEY=VALUE is parsed from a single positional; KEY must match - `[A-Z_][A-Z0-9_]*` -- KEY without `=VALUE` reads the value from the current process environment -- `--file ` reads KEY=VALUE assignments from a dotenv file relative to - the current directory; `--file` is mutually exclusive with the positional - assignment -- file imports validate the whole file before writing; duplicate keys, invalid - keys, empty values, or missing target variables fail before any variables are - updated -- if no variable with the key exists in the scope, the command fails - with a clear error directing to `env add` -- the response carries metadata only — the value is never echoed back - -Examples: - -```bash -prisma-cli project env update STRIPE_KEY=sk_new_xxx --role production -prisma-cli project env update STRIPE_KEY=sk_new_xxx --role preview -prisma-cli project env update --file .env --role production -prisma-cli project env update DATABASE_URL=postgresql://branch --branch feature/foo -``` - -### `prisma-cli project env list [--role | --branch ]` - -Purpose: - -- list environment variable names and metadata for the targeted scope. - -Behavior: - -- requires auth and a resolved project; accepts `--project ` as an explicit fallback -- explicit `--role production|preview` lists that project-level map -- explicit `--branch` lists the resolved preview branch view: preview defaults - plus branch overrides, with source metadata -- with no scope and an active local Git branch, resolves the matching - Platform Branch and lists the env map for its role; preview Branches - include preview defaults plus Branch overrides -- with no scope and an active local Git branch that has no Platform - Branch yet, lists preview template metadata and marks the target as - not created yet -- with no scope and no local Git branch, lists an overview of the - production and preview project-level maps, excluding Branch overrides -- never prints values (never-reveal) -- emits `key`, `id`, `last updated`, and source/scope annotations per - row, plus resolved target metadata for human and JSON output - -Examples: - -```bash -prisma-cli project env list -prisma-cli project env list --role preview -prisma-cli project env list --branch feature/foo -``` - -### `prisma-cli project env remove KEY (--role | --branch )` - -Purpose: - -- remove an environment variable from the targeted scope. - -Behavior: - -- requires auth and a resolved project; accepts `--project ` as an explicit fallback -- looks the variable up by natural key in the scope and `DELETE`s it -- `rm` is supported as an alias for `remove` -- returns a focused error when no matching variable exists - -Examples: - -```bash -prisma-cli project env remove STRIPE_KEY --role production -prisma-cli project env remove STRIPE_KEY --role preview -prisma-cli project env remove DATABASE_URL --branch feature/foo -``` - -## `prisma-cli app show [app] --app ` - -Purpose: - -- show the app and its current deployment - -Behavior: - -- requires auth and project context -- resolves the selected app -- shows live URL and deployment summary when available - -Examples: - -```bash -prisma-cli app show -prisma-cli app show --app hello-world -``` - -## `prisma-cli app open [app] --app ` - -Purpose: - -- open the app's live URL - -Behavior: - -- requires auth and project context -- resolves the selected app -- opens the live URL in a browser when possible -- returns the URL in `--json` - -Examples: - -```bash -prisma-cli app open -prisma-cli app open --app hello-world -``` - -## `prisma-cli app domain` - -Purpose: - -- manage custom domains for an app's production Branch runtime - -Behavior: - -- requires auth and project context -- resolves the selected app on the production Branch -- supports only production Branch custom domains during Public Beta -- does not expose workspace-wide domain listing until the Management API has a - workspace-scoped list endpoint - -Commands: - -- `add ` registers a custom domain -- `show ` shows status, certificate detail, and fix hints -- `remove ` detaches a custom domain -- `retry ` re-triggers DNS verification and TLS issuance -- `wait ` blocks until `active`, terminal `failed`, or timeout - -Examples: - -```bash -prisma-cli app domain add shop.acme.com -prisma-cli app domain wait shop.acme.com --timeout 15m -prisma-cli app domain retry shop.acme.com -``` - -## `prisma-cli app domain add [app]` - -Purpose: - -- register a custom domain on the selected app's production Branch - -Behavior: - -- requires auth and project context -- resolves the selected app -- registers the hostname against the selected app's compute service -- is idempotent for a hostname already attached to the same app -- does not re-trigger DNS verification for an existing row -- prints DNS record instructions only when returned by the API -- does not synthesize DNS records client-side when the API omits them -- returns `DOMAIN_DNS_NOT_CONFIGURED` with a CNAME target only when the API error includes the required target -- returns `DOMAIN_ALREADY_REGISTERED` when the hostname is attached outside the selected app -- rejects non-production `--branch` with `BRANCH_NOT_DEPLOYABLE` - -Examples: - -```bash -prisma-cli app domain add shop.acme.com -prisma-cli app domain add shop.acme.com --app shop --branch production -``` - -## `prisma-cli app domain show [app]` - -Purpose: - -- show status and recovery guidance for one custom domain - -Behavior: - -- requires auth and project context -- resolves the selected app -- finds the domain by hostname within the selected app -- includes failure category, failure reason, certificate expiry, and DNS record - instructions when returned by the API - -Examples: - -```bash -prisma-cli app domain show checkout.acme.com -``` - -## `prisma-cli app domain remove [app]` - -Purpose: - -- detach a custom domain from the selected app - -Behavior: - -- requires auth and project context -- resolves the selected app -- requires confirmation unless `-y` or `--yes` is passed -- deletes the domain binding by id after resolving the hostname - -Examples: - -```bash -prisma-cli app domain remove old.acme.com -prisma-cli app domain remove old.acme.com --yes -``` - -## `prisma-cli app domain retry [app]` - -Purpose: - -- re-trigger DNS verification and TLS issuance for a failed or stuck domain - -Behavior: - -- requires auth and project context -- resolves the selected app -- finds the domain by hostname within the selected app -- calls the domain retry endpoint -- prints DNS record instructions and failure guidance when returned by the API -- returns `DOMAIN_RETRY_NOT_ELIGIBLE` when the API reports the domain is not in - a retryable state - -Examples: - -```bash -prisma-cli app domain retry checkout.acme.com -``` - -## `prisma-cli app domain wait [app]` - -Purpose: - -- block until a custom domain reaches `active`, terminal `failed`, or timeout - -Behavior: - -- requires auth and project context -- resolves the selected app -- finds the domain by hostname within the selected app -- polls domain detail until status is `active`, `failed`, or the timeout expires -- defaults `--timeout` to `15m` -- treats `--timeout 0` as poll-once snapshot mode -- exits 0 on `active`, and 1 on terminal `failed` or timeout -- in `--json` mode, streams newline-delimited status events - -Examples: - -```bash -prisma-cli app domain wait shop.acme.com -prisma-cli app domain wait shop.acme.com --timeout 0 --json -``` - -## `prisma-cli app logs [app] --app --deployment ` - -Purpose: - -- stream logs for the app's current deployment - -Behavior: - -- requires auth and project context -- resolves the selected app and the deployment currently serving live traffic -- streams raw app log lines to stdout in human mode -- writes CLI status and errors to stderr -- when `--deployment` is provided, streams logs for that exact deployment -- when both `--app` and `--deployment` are provided, verifies the deployment belongs to the selected app -- returns `FEATURE_UNAVAILABLE` only when the platform cannot provide logs for the resolved deployment - -Examples: - -```bash -prisma-cli app logs -prisma-cli app logs --deployment dep_123 -``` - -## `prisma-cli build list [app] --app --project --branch --limit ` - -Status: blocked on Management API rollout. The `GET /v1/apps/{appId}/builds` -endpoint exists in the control plane but is not yet deployed or published in -`@prisma/management-api-sdk`. This section is normative for the implementation -that lands once the SDK exposes the endpoint. - -Purpose: - -- list the git build jobs for an app, so build ids are discoverable without the Console - -Behavior: - -- requires auth and project context -- resolves the selected app exactly like the other app management commands: `[app]` target argument, `--app`, compute config target, locally selected app, inferred name; never creates apps or branches -- resolves the branch it reads like management commands: explicit `--branch`, active Git branch when it exists in the project, then the project's default branch -- lists builds newest first: build id, state (`pending`, `running`, `succeeded`, `failed`, `cancelled`), source (`webhook`, `setup`, `manual`), Git branch, short commit sha, created and finished timestamps, and the produced deployment id when the build reached that stage -- build ids are the ids `build logs ` accepts -- `--limit ` caps the number of returned builds; JSON output includes `pagination.nextCursor` and `pagination.hasMore` so agents can page -- read-only; never prints secret values -- `nextSteps` includes `prisma-cli build logs ` for the newest build -- fails with the standard app selection errors (`APP_AMBIGUOUS`, app not found) when the target cannot be resolved safely - -Examples: - -```bash -prisma-cli build list -prisma-cli build list --app my-app --limit 50 -prisma-cli build list --json -``` - -## `prisma-cli build show ` - -Status: blocked on Management API rollout, same as `build list`; the backing -endpoint is `GET /v1/builds/{buildId}`. - -Purpose: - -- show one build in detail - -Behavior: - -- requires auth -- takes a build id, as shown by `build list`, the Console build view, and git-push output -- authorization matches `build logs`: access stays with the workspace that owned the build when it ran, and an unknown or foreign build id fails with an indistinguishable `BUILD_NOT_FOUND` -- shows state, source, Git branch, commit sha, created/started/finished timestamps, the error message when the build failed, and the produced deployment id and deployed URL when present -- read-only; never prints secret values -- `nextSteps` includes `prisma-cli build logs ` - -Examples: - -```bash -prisma-cli build show cmcz3v6ft0a1b2c3d -prisma-cli build show cmcz3v6ft0a1b2c3d --json -``` - -## `prisma-cli build logs --follow --cursor ` - -Purpose: - -- stream the build log for a specific build (from a git-push or a Console deploy) - -Behavior: - -- requires auth; authorizes against the workspace that owned the build when it ran (build logs can contain secrets, so access stays with that workspace) -- takes a build id — shown in the Console build view and in git-push output; this is a build id, distinct from a runtime deployment id (`prisma-cli app logs` streams a deployment's runtime logs; this streams a build's logs) -- streams the build's log records to stdout in human mode (each line carries its source — `runner` / `stdout` / `stderr` — and the build step); `stderr` and error-level records are written to stderr so stdout stays redirectable to a clean build log -- a clean end prints no trailing line; a build with no recorded logs prints `No build logs are available for this build.`, and read errors print their message (these terminal messages are written to stderr) -- `--follow` keeps the connection open and streams new lines while an in-flight build runs; it ends on its own once the build reaches a terminal state -- `--cursor ` resumes from a prior terminal cursor -- `--json` emits one JSON event per record, ending in a terminal record (no trailing wrapper success event) -- returns an indistinguishable `BUILD_NOT_FOUND` when the build does not exist or the caller's workspace does not own it - -Examples: - -```bash -prisma-cli build logs cmcz3v6ft0a1b2c3d -prisma-cli build logs cmcz3v6ft0a1b2c3d --follow -prisma-cli build logs cmcz3v6ft0a1b2c3d --json -``` - -## `prisma-cli app list-deploys [app] --app ` - -Purpose: - -- list deployments for the app - -Behavior: - -- requires auth and project context -- resolves the selected app -- marks the live deployment when known - -Examples: - -```bash -prisma-cli app list-deploys -prisma-cli app list-deploys --app hello-world -``` - -## `prisma-cli app show-deploy ` - -Purpose: - -- show a deployment in detail - -Behavior: - -- requires auth and project context -- resolves the deployment by id -- includes app context when available - -Examples: - -```bash -prisma-cli app show-deploy dep_123 -``` - -## `prisma-cli app promote [app] --app ` - -Purpose: - -- promote a deployment to production by rebuilding with production env vars - -Behavior: - -- requires auth and project context -- resolves the selected app -- resolves the deployment by id -- reports whether the deployment was already live - -Examples: - -```bash -prisma-cli app promote dep_123 -prisma-cli app promote dep_123 --app hello-world -``` - -## `prisma-cli app rollback [app] --app --to ` - -Purpose: - -- roll back production to a previous deployment - -Behavior: - -- requires auth and project context -- resolves the selected app -- restores the deployment passed with `--to`, or the previous deployment when available -- fails with `NO_PREVIOUS_DEPLOYMENT` when no previous deployment can be resolved - -Examples: - -```bash -prisma-cli app rollback -prisma-cli app rollback --app hello-world --to dep_123 -``` - -## `prisma-cli app remove [app] --app --branch -y --yes` - -Purpose: - -- remove the app, and every deployment it owns, from the resolved branch - -Behavior: - -- requires auth and project context -- resolves the selected app on the resolved branch -- `--branch ` scopes the removal to that branch, honored as-is; an empty value is rejected rather than inferred -- without `--branch`, the branch is inferred (active Git branch, else the project's default production branch), so automation that must not touch production should always pass `--branch` -- requires confirmation unless `-y` or `--yes` is passed -- clears local selected app state when the removed app was selected - -Examples: - -```bash -prisma-cli app remove --app hello-world -prisma-cli app remove --app hello-world --yes -prisma-cli app remove --app hello-world --branch feature/foo --yes -``` diff --git a/docs/product/resource-model.md b/docs/product/resource-model.md deleted file mode 100644 index 18dea44a..00000000 --- a/docs/product/resource-model.md +++ /dev/null @@ -1,351 +0,0 @@ -# Prisma CLI Resource Model - -## Purpose - -This document defines the nouns and boundaries used by the Prisma CLI. It is the -source of truth for what the CLI means by workspace, project, branch, app, -deployment, database, and environment variables. - -## North Star Hierarchy - -The Prisma CLI resolves through one hierarchy: - -```text -workspace -> project -> branch -> { app, database, bucket } -``` - -The preview implementation exposes only part of this hierarchy, but current -behavior must not contradict it. - -## Core Resources - -### Workspace - -`workspace` is the account, membership, and billing boundary. - -Preview relevance: - -- authentication -- current identity -- project discovery - -### Project - -`project` is the remote Prisma resource resolved for local work. - -Rules: - -- `project` is not the same thing as `app` -- Public Beta does not read or write committed config files such as `prisma.config.ts` or `.prisma/settings.json` for project resolution -- `.prisma/local.json` is a gitignored local pin/cache for Workspace and Project IDs; it is not a declarative repo config file. When a `prisma.compute.ts` is discovered (nearest config from the invocation directory up to the repository or workspace root), the pin and the CLI state cache (`.prisma/cli/state.json`) are read and written in the config file's directory; without a config they stay in the invocation directory -- `prisma.compute.ts` is a committed deploy-defaults file; it must not contain Workspace, Project, Branch, env-secret, or credential resolution state -- `init` is the only command that writes `prisma.compute.ts`, and it never overwrites an existing one; deploy reads the config but never writes it -- Project setup is explicit: users choose an existing Project or explicitly create a new one before remote work starts -- `app deploy` may orchestrate Project setup, but it must not silently choose or create Project scope -- everything under a project happens in a branch -- `project rename` mutates only the remote Project name; pins bind by id and stay valid -- `project remove` and `project transfer` take an explicit positional Project target and exact id confirmation with `--confirm `; they never default to the directory's bound Project and `--yes` is not sufficient -- removal is permanent and takes the Project's databases with it; transfer moves ownership to another workspace without changing resource ids -- when a destructive Project command invalidates this directory's local pin, the CLI cleans the pin up (clear on remove; rewrite or clear on transfer) and reports it - -### Branch - -`branch` is the named project-scoped isolation boundary for app and database -work. - -A Prisma branch is not just a Git branch and not just a database branch. It is -the platform container for a version of a project: app resources, databases, -deploy state, preview URL, scoped configuration, logs, and automation context can -all belong to the branch over time. - -Rules: - -- `production` is a protected durable branch -- every other named branch is a preview branch by default -- preview branches are disposable by default -- non-production branches can become durable later -- `local` is local CLI context only, not a branch -- branch context comes from explicit targeting, Git, or safe command defaults, - not `prisma.config.ts` - -Examples of preview branches: - -- `preview` -- `staging` -- `feat-auth` -- `pr-123` - -Branch role and durability are product concepts in the current docs. The preview -command JSON for `branch list` exposes `role`; `durability` remains target-model -until the Management API returns it everywhere. - -### Branch Role And Durability - -Branch role describes what the branch is used for. Branch durability describes -the reliability contract attached to it. - -Rules: - -- production branches are durable by default -- preview branches are disposable by default -- a non-production branch can become durable for staging, QA, demos, release - candidates, or persistent automation work -- all production branches are durable, but not all durable branches are - production - -Disposable preview work can have stricter runtime guardrails, automatic archive -after inactivity, and restore-on-request behavior. Durable branches carry a -stronger recovery expectation and should have stronger safeguards against -accidental destructive actions. - -### App - -`app` is the deployable runtime workload for a project branch. - -Rules: - -- `app` is not the same thing as `project` -- the app name is registered within the resolved project -- the runtime app service is scoped by branch in the platform model -- the app may be selected or created as part of app deployment workflows -- app selection is local CLI state when needed for the beta package -- app region is set at app creation time; `prisma.compute.ts` can provide the new-app default, but deploys to existing apps do not move them between regions -- app build settings live in the `build` block of `prisma.compute.ts` (`command`, `outputDirectory`, `entrypoint`); `prisma.app.json` is legacy and no longer read - -### Deployment - -`deployment` is one build-and-release instance of an app. - -Deployment fields should be treated as first-class: - -- `id` -- `status` -- `url` when available -- `timestamps` -- `sourceRevision` when known -- whether it is currently live - -A branch can have many deployments over time, but at most one live deployment -for a given app. - -### Source Revision - -`sourceRevision` is the code state a deployment was built from. - -It matters because: - -- promotion should be source-aware -- production releases should make clear what source is going live -- rollback should restore a known previous deployment - -### Environment Variables - -Environment variables are deploy-time inputs, not top-level CLI resources in the -beta command model. - -Rules: - -- deployments get a snapshot of variables at deploy time -- changing variables does not mutate older deployments -- changing variables does not auto-redeploy unless the command explicitly - creates a new deployment -- command output must not print secret values -- listing variables should show names only - -The `env` word is reserved for environment-variable ergonomics. The current -top-level target-context group is `branch`, not `env`. - -### Object Store and Bucket - -`bucket` is a branch-scoped object-store resource backed by Tigris. - -A bucket is created inside a project and may be scoped to a branch. Access to -its contents is controlled by access keys. Each access key has a role (`read` -or `read_write`) and is issued as a one-time secret: the secret access key is -returned only when the key is created and cannot be retrieved again. - -The `bucket key` subgroup manages access keys for a bucket. Its secret-reveal -behavior mirrors `database connection create`: the one-time credential is -written to stdout as a four-line S3-compatible env block, and human metadata -goes to stderr. - -Rules: - -- `bucket` is the canonical public group; Public Beta does not add public - `storage` or `object-store` aliases -- `bucket create` provisions the bucket; `--branch ` scopes it to - that branch -- `bucket key create` returns the secret access key exactly once, as an env - block on stdout: `S3_ENDPOINT`, `S3_ACCESS_KEY_ID`, `S3_SECRET_ACCESS_KEY`, - `S3_BUCKET` -- `bucket list` and `bucket key list` never print or return secret values -- `bucket delete` cascades: all stored objects are removed and all access - keys are revoked before the bucket is destroyed; the command requires - `--confirm ` matching the positional argument to prevent - accidental data loss - -The beta package exposes: - -- `bucket list` -- `bucket create` -- `bucket delete ` -- `bucket key list ` -- `bucket key create ` -- `bucket key delete ` - -### Schema and Database - -`schema` stays a local code artifact. `database` stays a branch-bound remote -resource. - -The beta package exposes `database` as the canonical database management group. -It manages Prisma Postgres database metadata, usage, backups, and one-time-view -connection strings: - -- `database list` -- `database show ` -- `database create ` -- `database usage ` -- `database restore ` -- `database remove ` -- `database backup list ` -- `database connection list ` -- `database connection create ` -- `database connection rotate ` -- `database connection remove ` - -The `database connection` and `database backup` subgroups are nested because -connections and backups exist only for databases. They follow the same -parent-noun/subordinate-noun/action shape as `project env `. There is -no `database connection show` command: connection strings are secrets and the -platform returns them only from create and rotate operations. - -Rules: - -- `database` is the canonical public group; Public Beta does not add public - `db` or `postgres` aliases -- `database create` prints the first returned connection URL exactly once -- `database connection create` prints the created connection URL exactly once -- create commands print raw URLs only, never `DATABASE_URL=` or `DIRECT_URL=` -- database wiring uses the existing environment-variable model -- `database list`, `database show`, and `database connection list` never print - or return secret values -- database and database connection removal require exact id confirmation with - `--confirm `; `--yes` is not sufficient -- database restore and connection rotation are equally destructive (restore - overwrites the target's data; rotation revokes the previous credentials) and - require the same exact id confirmation with `--confirm ` -- backups are platform-created; the CLI lists them and restores from them but - never creates or deletes them in the current slice -- `database usage` and `database backup list` are read-only and never print - secret values -- preview Branch setup writes branch-scoped `DATABASE_URL` and `DIRECT_URL` overrides, not separate app bindings -- first production deploy setup writes production `DATABASE_URL` and `DIRECT_URL` env vars before the App has a live deployment -- database setup never overwrites an existing branch-scoped `DATABASE_URL` -- production setup treats existing production `DATABASE_URL` or `DIRECT_URL` as BYO DB intent and leaves env vars unchanged -- the CLI provisions the database and wires its env vars; it never runs schema, migration, or generate commands. A detected local Prisma schema source feeds only the suggested follow-up command the user runs themselves; the CLI does not clone or infer schema from another database -- when detecting that local schema source for the suggestion, a Prisma Next config (`prisma-next.config.*`) is preferred over `schema.prisma` -- a known non-Postgres Prisma source is treated as unsupported: it does not trigger automatic database prompting, and explicit `--db` is rejected -- later production database configuration is managed through explicit environment-variable commands - -## Relationships - -```text -workspace -> project -project -> branch -branch -> app* -branch -> database* -branch -> bucket* -app -> deployment* -bucket -> bucket_key* -``` - -Long-term, branch is where app, database, and bucket relationships meet. - -## Invariants - -- `project` is not `app` -- `project` is not `branch` -- `branch` is not `deployment` -- `deployment` is not `sourceRevision` -- `local` is CLI context, not a branch or deploy target -- `production` is protected and durable -- every other named branch is preview by default -- Public Beta does not use committed repo config files for Project -> Branch -> App resolution -- `.prisma/local.json` may cache Workspace and Project resolution, but Branch still comes from explicit targeting or Git and App is resolved inside the Branch - -## Resolution Rules - -### Project Resolution - -Commands resolve project context in this order: - -1. explicit `--project ` when present -2. `PRISMA_PROJECT_ID` when set for headless deploy/domain commands -3. `.prisma/local.json` project pin when present, revalidated against platform data -4. durable platform mapping when available -5. explicit setup choice: `project link`, `project create`, interactive setup picker, `app deploy --project`, or `app deploy --create-project` -6. structured failure when no explicit or durable Project binding exists - -Package names and directory names may suggest setup defaults and matching -Project candidates, but they do not select Project scope. Remembered local -context may help with app/deployment convenience after a Project is explicit, -but it is not a Project binding source. - -Project-scoped commands require explicit or durable Project context. If the -directory is not pinned and no explicit Project source is provided, they fail -with `PROJECT_SETUP_REQUIRED`; `app deploy` may enter explicit interactive setup -before failing. - -### App Selection Resolution - -Preview app commands that need an app resolve it inside the resolved branch in -this order: - -1. explicit `--app ` -2. `PRISMA_APP_ID` when set for headless deploys -3. locally selected app for non-deploy commands when it still exists in the resolved branch -4. inferred app name from `package.json#name` -5. current directory name -6. create the inferred app service in the resolved branch when no existing app matches -7. interactive selection only when multiple matching apps make the target ambiguous -8. structured usage error when no app can be resolved non-interactively - -`.prisma/local.json` does not pin an app ID. The local pin binds the directory -to a Workspace and Project; branches come from explicit targeting, Git, or -`main` when neither is available. Apps are resolved within that resolved branch, -including the `main` fallback, which avoids accidentally deploying -feature-branch code into a service owned by another branch. - -### Branch Context Resolution - -Commands that use branch context resolve it in this order: - -1. explicit branch argument when the command accepts one -2. local Git branch when available -3. `main` - -Consequences: - -- `local` never becomes a branch or deploy target -- first remote app work falls back to `main` when no Git branch is available -- production requires explicit user intent - -### Inspect Resolution - -Commands that inspect deployments resolve in this order: - -1. exact deployment id if the command accepts one -2. selected app for the resolved project -3. latest known live deployment for that app - -### Promote Resolution - -`app promote` releases an existing successful deployment or source into a more -trusted target. Production promotion must be explicit and must not hide what is -going live. - -### Rollback Resolution - -`app rollback` restores a previous known deployment. Rollback output must make -clear what changed and which deployment is now live. diff --git a/docs/reference/glossary.md b/docs/reference/glossary.md index 35bf5224..83a9f295 100644 --- a/docs/reference/glossary.md +++ b/docs/reference/glossary.md @@ -7,26 +7,26 @@ output, and implementation. | Term | Meaning | Source | | --- | --- | --- | -| Workspace | Account, membership, and billing boundary. | [Resource model](../product/resource-model.md) | -| Project | Remote Prisma resource linked to a local repo. | [Resource model](../product/resource-model.md) | -| Branch | Project-scoped isolation boundary for app and database work. | [Resource model](../product/resource-model.md) | -| Local | Local-only CLI context. It is not a branch or remote deploy target. | [Resource model](../product/resource-model.md) | -| Preview branch | Any named branch other than `production` by default. | [Resource model](../product/resource-model.md) | -| Production branch | Protected durable branch that requires explicit user intent. | [Resource model](../product/resource-model.md) | -| Durable branch | Branch with explicit recovery guarantees. | [Resource model](../product/resource-model.md) | -| App | Deployable runtime workload for a project branch. | [Resource model](../product/resource-model.md) | -| Deployment | One build-and-release instance of an app. | [Resource model](../product/resource-model.md) | -| Source revision | Code state a deployment was built from. | [Resource model](../product/resource-model.md) | -| Schema | Local data model in the codebase. Out of scope for the current beta package. | [Resource model](../product/resource-model.md) | -| Database | Branch-bound Prisma Postgres data store managed by the `database` command group. | [Resource model](../product/resource-model.md) | -| Bucket | Branch-scoped Tigris object-store resource managed by the `bucket` command group. | [Resource model](../product/resource-model.md) | -| Bucket key | One-time-credential access key for a bucket, with role `read` or `read_write`. | [Resource model](../product/resource-model.md) | -| Command group | First command segment after `prisma`, such as `auth` or `app`. | [Command spec](../product/command-spec.md) | -| Action | Operation inside a command group, such as `deploy` or `whoami`. | [Command spec](../product/command-spec.md) | +| Workspace | Account, membership, and billing boundary. | Resource model | +| Project | Remote Prisma resource linked to a local repo. | Resource model | +| Branch | Project-scoped isolation boundary for app and database work. | Resource model | +| Local | Local-only CLI context. It is not a branch or remote deploy target. | Resource model | +| Preview branch | Any named branch other than `production` by default. | Resource model | +| Production branch | Protected durable branch that requires explicit user intent. | Resource model | +| Durable branch | Branch with explicit recovery guarantees. | Resource model | +| App | Deployable runtime workload for a project branch. | Resource model | +| Deployment | One build-and-release instance of an app. | Resource model | +| Source revision | Code state a deployment was built from. | Resource model | +| Schema | Local data model in the codebase. Out of scope for the current beta package. | Resource model | +| Database | Branch-bound Prisma Postgres data store managed by the `database` command group. | Resource model | +| Bucket | Branch-scoped Tigris object-store resource managed by the `bucket` command group. | Resource model | +| Bucket key | One-time-credential access key for a bucket, with role `read` or `read_write`. | Resource model | +| Command group | First command segment after `prisma`, such as `auth` or `app`. | Command spec | +| Action | Operation inside a command group, such as `deploy` or `whoami`. | Command spec | | Structured output | Explicit `--json` output intended for automation. | [Output conventions](../product/output-conventions.md) | | Human output | Status, prompts, summaries, and decoration intended for terminal users. | [Output conventions](../product/output-conventions.md) | | Error code | Stable machine-readable failure code. | [Error conventions](../product/error-conventions.md) | -| Beta package | Public prerelease package line for `@prisma/cli` on the `latest` dist-tag. | [ADR 0001](../architecture/adrs/0001-preview-package-and-publishing.md) | +| Beta package | Public prerelease package line for `@prisma/cli`; the RC line publishes on the `next` dist-tag (see [versioning](../oss/versioning.md)). | [ADR 0001](../architecture/adrs/0001-preview-package-and-publishing.md) | | Dev package | Latest successful `main` build of `@prisma/cli` on the `dev` dist-tag. | [ADR 0001](../architecture/adrs/0001-preview-package-and-publishing.md) | | PR preview package | Installable pkg.pr.new package for a trusted same-repo pull request commit. | [ADR 0001](../architecture/adrs/0001-preview-package-and-publishing.md) | diff --git a/examples/hello-world/README.md b/examples/hello-world/README.md index 5e1bac04..31f0b730 100644 --- a/examples/hello-world/README.md +++ b/examples/hello-world/README.md @@ -2,7 +2,7 @@ Manual Bun smoke app for exercising the local source Prisma CLI from inside this repo. -This example mirrors the recommended external Bun workflow: `bun init --yes`, replace `index.ts` with a small `Bun.serve(...)` server, then deploy it with the CLI. +This example mirrors the recommended external Bun workflow: `bun init --yes`, replace `index.ts` with a small `Bun.serve(...)` server, then wire it to a Prisma project with the CLI. Deployments start from pushing a connected repository (`git connect`), the Console, or `composer deploy` — there is no standalone deploy command. This example is intentionally not part of the root pnpm workspace. Install it only when you want to run manual end-to-end checks. @@ -12,12 +12,12 @@ This example is intentionally not part of the root pnpm workspace. Install it on cd examples/hello-world pnpm install pnpm prisma auth login -pnpm prisma app deploy --app hello-world --env DATABASE_URL=postgresql://example -pnpm prisma app list-env -pnpm prisma app list-deploys -pnpm prisma app show-deploy -pnpm prisma app update-env --app hello-world --env DATABASE_URL=postgresql://another -pnpm prisma app list-env +pnpm prisma project create hello-world +pnpm prisma project env add DATABASE_URL=postgresql://example --role preview +pnpm prisma project env list +pnpm prisma git connect git@github.com:OWNER/REPO.git +pnpm prisma service list +pnpm prisma service deployment list ``` Optional local run: @@ -32,28 +32,25 @@ Fresh external scaffold: mkdir my-bun-app cd my-bun-app bun init --yes -pnpm add -D @prisma/cli +pnpm add -D @prisma/cli@next ``` Then replace `index.ts` with a `Bun.serve(...)` server and run: ```bash -pnpm prisma-cli app build pnpm prisma-cli auth login -pnpm prisma-cli app deploy --app my-bun-app --env DATABASE_URL=postgresql://example -pnpm prisma-cli app list-env +pnpm prisma-cli project create my-bun-app +pnpm prisma-cli git connect git@github.com:OWNER/REPO.git ``` What this validates: - the CLI runs from the example directory, so config and local state resolve there -- auth can be established from inside this example before running deploy flows -- first deploy bootstraps an example-local `prisma.config.ts` when no project is linked -- first deploy can create or reuse the `hello-world` app -- first deploy can carry deploy-time environment variables like `DATABASE_URL` -- second deploy reuses saved local app selection from `.prisma/cli/state.json` -- `app list-env` shows variable names without exposing values -- the beta build flow can package and deploy a simple Bun server +- auth can be established from inside this example before connecting a repository +- `project create` and `project link` save the local binding in `.prisma/local.json` +- `project env add` can carry environment variables like `DATABASE_URL` +- `project env list` shows variable names without exposing values +- pushes to the connected repository create deployments, visible via `service deployment list` Local files intentionally ignored in this example: diff --git a/examples/next-smoke/README.md b/examples/next-smoke/README.md index 6b64c810..43fcc925 100644 --- a/examples/next-smoke/README.md +++ b/examples/next-smoke/README.md @@ -4,7 +4,7 @@ Manual smoke app for exercising the local source Prisma CLI from inside this rep This example is intentionally not part of the root pnpm workspace. Install it only when you want to run manual end-to-end checks. -This example already sets `output: "standalone"` in `next.config.ts`, which is required for Next.js deploys in the current beta. +This example already sets `output: "standalone"` in `next.config.ts`, which is required for Next.js deploys. ## Manual Flow @@ -12,22 +12,22 @@ This example already sets `output: "standalone"` in `next.config.ts`, which is r cd examples/next-smoke pnpm install pnpm prisma auth login -pnpm prisma app deploy --app next-smoke -pnpm prisma app list-deploys -pnpm prisma app show-deploy -pnpm prisma app deploy -pnpm prisma app deploy --app next-smoke --framework nextjs --http-port 3000 +pnpm prisma project create next-smoke +pnpm prisma git connect git@github.com:OWNER/REPO.git +pnpm prisma service list +pnpm prisma service deployment list +pnpm prisma service deployment show DEPLOYMENT_ID ``` +Deployments start from pushing the connected repository, the Console, or `composer deploy` — there is no standalone deploy command. + What this validates: - the CLI runs from the example directory, so config and local state resolve there -- auth can be established from inside this example before running deploy flows -- first deploy bootstraps an example-local `prisma.config.ts` when no project is linked -- first deploy can create or reuse the `next-smoke` app -- first deploy uses the Next.js standalone build path without needing `--http-port` -- `--framework nextjs --http-port 3000` is available as an explicit repair or override path -- second deploy reuses saved local app selection from `.prisma/cli/state.json` +- auth can be established from inside this example before connecting a repository +- `project create` and `project link` save the local binding in `.prisma/local.json` +- pushes to the connected repository create deployments, visible via `service deployment list` +- the Next.js standalone build path deploys without extra configuration Local files intentionally ignored in this example: diff --git a/examples/next-smoke/app/page.tsx b/examples/next-smoke/app/page.tsx index 658edee4..993487d1 100644 --- a/examples/next-smoke/app/page.tsx +++ b/examples/next-smoke/app/page.tsx @@ -13,7 +13,7 @@ export default function Home() { Run pnpm prisma auth login
  • - Run pnpm prisma app deploy --app next-smoke + Run pnpm prisma git connect and push to deploy
  • diff --git a/packages/cli/AGENTS.md b/packages/cli/AGENTS.md index 8d7bfa97..0ef6d4e7 100644 --- a/packages/cli/AGENTS.md +++ b/packages/cli/AGENTS.md @@ -9,18 +9,16 @@ The docs in `docs/product` are the source of truth. Do not invent product behavi ## What This CLI Is - This is the future unified Prisma CLI. -- The first implementation slice is app deployment workflows, but the command model must preserve the long-term CLI for ORM, Postgres, and app workflows. +- The command model must preserve the long-term CLI for ORM, Postgres, and service workflows; deployments start from a pushed connected repository, the Console, or `composer deploy`. ## Read These First Start with `docs/README.md` for the public docs index. -1. `docs/product/resource-model.md` -2. `docs/product/command-principles.md` -3. `docs/product/command-spec.md` -4. `docs/product/cli-style-guide.md` -5. `docs/product/output-conventions.md` -6. `docs/product/error-conventions.md` +1. `docs/product/command-principles.md` +2. `docs/product/cli-style-guide.md` +3. `docs/product/output-conventions.md` +4. `docs/product/error-conventions.md` Architecture and contributor workflow references: @@ -35,10 +33,10 @@ 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 current preview uses only `auth`, `project`, `branch`, and `app`. -- Preserve the long-term resource model: `workspace -> project -> branch -> { app, database }`. +- The shipped groups are `auth`, `project`, `git`, `branch`, `postgres`, `bucket`, `service`, `build`, `composer`, and the ORM family (`contract`, `db`, `migrate`, `migration`, `format`, `orm init`, `lsp`). +- Preserve the long-term resource model: `workspace -> project -> branch -> { service, database, bucket }`. -For exact definitions and resolution rules, see `resource-model.md` and `command-spec.md`. +The mounted tree in `packages/cli/src/cli.ts` is the authoritative command surface. ## Branch Model @@ -51,12 +49,7 @@ Do not redefine this casually: - preview branches are disposable by default - non-production branches can become durable later - first remote deploy defaults to preview -- production is reached by `app promote` or explicit user targeting - -See: - -- `docs/product/resource-model.md` -- `docs/product/command-spec.md` +- production is reached by `service deployment promote` or explicit user targeting ## Output and Error Behavior diff --git a/packages/cli/README.md b/packages/cli/README.md index 96b492a1..f5abb967 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -15,15 +15,9 @@ `@prisma/cli` is the public beta of the new CLI for the Prisma Developer Platform. -It is the terminal surface managing your platform projects, branches, apps, -deployments, and environment variables. - -The command model is under active development to include tooling for your -schema, database, migration, and broader platform workflows. - -Looking for Prisma ORM commands such as `prisma generate`, `prisma migrate`, or -`prisma studio`? Use the [`prisma`](https://www.npmjs.com/package/prisma) -package. +It is one binary for the ORM, Composer, and the Prisma Developer +Platform: projects, branches, services, deployments, environment +variables, and the Prisma ORM schema and migration workflow. --- @@ -32,7 +26,7 @@ package. Install the beta package locally: ```bash -npm install --save-dev @prisma/cli +npm install --save-dev @prisma/cli@next ``` Run the binary exposed by this package: @@ -40,22 +34,26 @@ Run the binary exposed by this package: ```bash npx prisma-cli --help npx prisma-cli auth login -npx prisma-cli app deploy +npx prisma-cli project create my-app +npx prisma-cli git connect git@github.com:owner/repo.git ``` +Deployments start from pushing the connected repository, the Console, or +`prisma-cli composer deploy` — there is no standalone deploy command. + With `pnpm`: ```bash -pnpm add -D @prisma/cli +pnpm add -D @prisma/cli@next pnpm prisma-cli auth login -pnpm prisma-cli app deploy +pnpm prisma-cli git connect ``` Useful next commands: ```bash -npx prisma-cli app logs -npx prisma-cli app open +npx prisma-cli service list +npx prisma-cli service logs npx prisma-cli project env add DATABASE_URL=postgresql://example --role preview npx prisma-cli project env add --file .env --role preview npx prisma-cli project env list @@ -71,24 +69,27 @@ The beta package exposes `prisma-cli` so it can coexist with the existing | Group | What it does | | --- | --- | -| `version` | Show the installed CLI build and host environment. | | `auth` | Log in, log out, and inspect the active Prisma account. | -| `project` | List projects, show the resolved project, and manage project environment variables. | -| `git` | Connect or disconnect a project from a GitHub repository. | +| `project` | List, create, link, and manage projects and their environment variables. | +| `git` | Connect or disconnect a project from a GitHub repository; pushes deploy. | | `branch` | List Prisma branches for the resolved project. | -| `database` | Create, inspect, and remove Prisma Postgres databases and their connection strings. | -| `bucket` | Create, list, and delete Tigris object-store buckets and their access keys. | -| `app` | Build, run, deploy, inspect, open, stream logs, promote, roll back, and remove apps. | +| `postgres` | Create, inspect, restore, and remove Prisma Postgres databases and their connections. | +| `bucket` | Create, list, and delete object-store buckets and their access keys. | +| `service` | Inspect services: deployments, logs, domains, promote, roll back, remove. | +| `build` | Stream platform build logs. | +| `composer` | Deploy, destroy, and develop Composer apps. | +| `contract`, `db`, `migrate`, `migration`, `format`, `orm init`, `lsp` | The Prisma ORM workflow. | +| `init` | Write a committed compute config for the project. | Common examples: ```bash -npx prisma-cli version +npx prisma-cli --version npx prisma-cli auth whoami npx prisma-cli project show npx prisma-cli branch list -npx prisma-cli app deploy --branch feat-login --framework nextjs -npx prisma-cli app promote +npx prisma-cli service list +npx prisma-cli service deployment promote DEPLOYMENT_ID ``` ### Built for humans, CI, and agents @@ -105,9 +106,9 @@ npx prisma-cli app promote ## Beta notes - Requires Node.js 22.18 or newer. -- This is a beta package and may change quickly. -- Official beta releases publish as `@prisma/cli`. -- The package binary is `prisma-cli`, not `prisma`, during beta. +- This is a release-candidate package and may change quickly. +- The 8.0.0 release candidates publish as `@prisma/cli` on the `next` dist-tag. +- The package binary is `prisma-cli`; the sibling `prisma` package ships the same CLI under the `prisma` binary. - Local project context is cached in `.prisma/local.json`, which is gitignored and not a declarative repo config file. --- @@ -115,9 +116,7 @@ npx prisma-cli app promote ## Documentation - [CLI docs index](https://github.com/prisma/prisma-cli/blob/main/docs/README.md) -- [Resource model](https://github.com/prisma/prisma-cli/blob/main/docs/product/resource-model.md) - [Command principles](https://github.com/prisma/prisma-cli/blob/main/docs/product/command-principles.md) -- [Command spec](https://github.com/prisma/prisma-cli/blob/main/docs/product/command-spec.md) - [Output conventions](https://github.com/prisma/prisma-cli/blob/main/docs/product/output-conventions.md) - [Error conventions](https://github.com/prisma/prisma-cli/blob/main/docs/product/error-conventions.md) diff --git a/packages/cli/src/auth/operations.ts b/packages/cli/src/auth/operations.ts index 1f460091..db3383d8 100644 --- a/packages/cli/src/auth/operations.ts +++ b/packages/cli/src/auth/operations.ts @@ -142,7 +142,7 @@ export async function readAuthState( // so behavior is independent of any OAuth session that happens to be stored // on the runner. This matches the precedence already documented on // `authenticatedManagementApiClient` and keeps `auth whoami` and downstream commands - // (e.g. `app deploy`) reading the same source of truth. + // (e.g. `service list`) reading the same source of truth. const rawServiceToken = env[SERVICE_TOKEN_ENV_VAR]; if (rawServiceToken !== undefined) { const serviceToken = rawServiceToken.trim(); diff --git a/packages/cli/src/cli-command.ts b/packages/cli/src/cli-command.ts index 2500b1be..1045ad1f 100644 --- a/packages/cli/src/cli-command.ts +++ b/packages/cli/src/cli-command.ts @@ -1,5 +1,8 @@ export const PRISMA_CLI_PACKAGE_NAME = "@prisma/cli"; -export const PRISMA_CLI_PACKAGE_SPEC = `${PRISMA_CLI_PACKAGE_NAME}@latest`; +// `next` is the RC line's canonical dist-tag (docs/oss/versioning.md); +// `latest` still serves the 3.x beta until the deliberate cutover, so a +// hint spelling `@latest` would bounce users into the pre-8 command set. +export const PRISMA_CLI_PACKAGE_SPEC = `${PRISMA_CLI_PACKAGE_NAME}@next`; export const DEFAULT_PRISMA_CLI_PACKAGE_RUNNER = ["npx", "-y"]; export const PRISMA_CLI_BINARY = "prisma-cli"; diff --git a/packages/cli/src/cli-name.ts b/packages/cli/src/cli-name.ts index 6ef3ee2e..9f262cc3 100644 --- a/packages/cli/src/cli-name.ts +++ b/packages/cli/src/cli-name.ts @@ -6,5 +6,8 @@ */ export const CLI_NAME = "prisma-cli"; -/** The CLI docs page (also the update-check fallback instruction URL). */ -export const CLI_DOCS_URL = "https://www.prisma.io/docs/orm/tools/prisma-cli"; +/** The CLI docs page (also the update-check fallback instruction URL). + * The old /docs/orm/tools/prisma-cli path 308-redirects to the ORM CLI + * reference — the wrong docs for the unified CLI — so this points at + * the docs root until the unified CLI has its own page. */ +export const CLI_DOCS_URL = "https://www.prisma.io/docs"; diff --git a/packages/cli/src/commands/init/presentation.ts b/packages/cli/src/commands/init/presentation.ts index 0710dfcf..1d4c3898 100644 --- a/packages/cli/src/commands/init/presentation.ts +++ b/packages/cli/src/commands/init/presentation.ts @@ -91,7 +91,7 @@ export function initPresentations( ...(typesMissing(result) && result.types.installCommand ? [runCommand(result.types.installCommand)] : []), - runCommand(formatCommand(["app", "deploy"])), + runCommand(formatCommand(["git", "connect"])), ...(isLinked(result) ? [] : [runCommand(formatCommand(["project", "link"]))]), diff --git a/packages/cli/src/commands/project/presentation.ts b/packages/cli/src/commands/project/presentation.ts index 6deecf93..cb05620f 100644 --- a/packages/cli/src/commands/project/presentation.ts +++ b/packages/cli/src/commands/project/presentation.ts @@ -7,10 +7,12 @@ import { serializeProjectSetup } from "../../presenters/project"; import type { ProjectSetupResult } from "../../types/project"; import { portCommandString } from "./errors"; -export const DEPLOY_NEXT_ACTION: NextAction = { +/** Deploys come from pushing a connected repository, so the step after + * creating or linking a Project is connecting one. */ +export const CONNECT_REPO_NEXT_ACTION: NextAction = { kind: "run-command", - label: `${CLI_NAME} app deploy`, - command: `${CLI_NAME} app deploy`, + label: `${CLI_NAME} git connect`, + command: `${CLI_NAME} git connect`, }; /** The legacy local-pin warnings of `project remove` / `project @@ -66,6 +68,6 @@ export function setupPresentations(result: ProjectSetupResult): Presentations { }, ], json: () => serializeProjectSetup(result), - next: () => [DEPLOY_NEXT_ACTION], + next: () => [CONNECT_REPO_NEXT_ACTION], }; } diff --git a/packages/cli/src/controllers/app-env.ts b/packages/cli/src/controllers/app-env.ts index 4187eddc..48f1e8d4 100644 --- a/packages/cli/src/controllers/app-env.ts +++ b/packages/cli/src/controllers/app-env.ts @@ -371,7 +371,7 @@ async function resolveOrCreateBranch( why: "Creating the first branch would make it the project default, but branch overrides are preview-only.", fix: "Create or deploy the default branch first, then add the branch override.", exitCode: 1, - nextSteps: ["prisma-cli app deploy --branch main"], + nextSteps: ["prisma-cli git connect "], }); } diff --git a/packages/cli/src/lib/app/compute-config.ts b/packages/cli/src/lib/app/compute-config.ts index 8f402b76..66d2b64e 100644 --- a/packages/cli/src/lib/app/compute-config.ts +++ b/packages/cli/src/lib/app/compute-config.ts @@ -4,10 +4,6 @@ import { COMPUTE_CONFIG_FILENAME, type ComputeConfigError, type ComputeConfigTargetError, - type ComputeDeployTarget, - type ComputeFramework, - type FrameworkBuildType, - frameworkByKey, type LoadedComputeConfig, loadComputeConfig as loadComputeConfigFromSdk, } from "@prisma/compute-sdk/config"; @@ -40,170 +36,14 @@ export async function loadComputeConfig( return loadComputeConfigFromSdk(cwd, { signal }); } -/** Local build/run strategy implied by a configured framework. */ -export function computeFrameworkToBuildType( - framework: ComputeFramework, -): FrameworkBuildType { - return frameworkByKey(framework).buildType; -} - -export interface MergedDeployInput { - value: string; - annotation: string; -} - -export interface MergedComputeDeployInputs { - framework: MergedDeployInput | undefined; - entrypoint: MergedDeployInput | undefined; - httpPort: MergedDeployInput | undefined; - /** Region from config, applied only when the deploy creates a new app. */ - region: MergedDeployInput | undefined; - /** `--env` flags replace config env inputs entirely; they never merge. */ - envInputs: string[] | undefined; - /** True when env inputs came from the config; their file paths then resolve from the config directory. */ - envInputsFromConfig: boolean; - /** Config-provided app name; ranks below --app and PRISMA_APP_ID. */ - configAppName: MergedDeployInput | undefined; - /** App directory relative to the config directory, or undefined for the config directory. */ - appRoot: string | undefined; -} - -export function mergeComputeDeployInputs(options: { - cli: { - framework?: string; - entrypoint?: string; - httpPort?: string; - region?: string; - envInputs?: string[]; - }; - target: ComputeDeployTarget | null; - configFilename: string; -}): MergedComputeDeployInputs { - const { cli, target, configFilename } = options; - const configAnnotation = `set by ${configFilename}`; - - const framework = mergeStringInput( - cli.framework, - "set by --framework", - target?.framework ?? undefined, - configAnnotation, - ); - const entrypoint = mergeStringInput( - cli.entrypoint, - "set by --entry", - target?.entry ?? undefined, - configAnnotation, - ); - const httpPort = mergeStringInput( - cli.httpPort, - "set by --http-port", - target?.httpPort ? String(target.httpPort) : undefined, - configAnnotation, - ); - - const region = mergeStringInput( - cli.region, - "set by --region", - target?.region ?? undefined, - configAnnotation, - ); - - const cliEnvInputs = - cli.envInputs && cli.envInputs.length > 0 ? cli.envInputs : undefined; - const configEnvInputs = - target && target.envInputs.length > 0 ? target.envInputs : undefined; - const envInputs = cliEnvInputs ?? configEnvInputs; - - const configAppName = readConfigAppName(target, configAnnotation); - - return { - framework, - entrypoint, - httpPort, - region, - envInputs, - envInputsFromConfig: !cliEnvInputs && configEnvInputs !== undefined, - configAppName, - appRoot: target?.root ?? undefined, - }; -} - -function mergeStringInput( - cliValue: string | undefined, - cliAnnotation: string, - configValue: string | undefined, - configAnnotation: string, -): MergedDeployInput | undefined { - if (cliValue !== undefined) { - return { value: cliValue, annotation: cliAnnotation }; - } - if (configValue) { - return { value: configValue, annotation: configAnnotation }; - } - return undefined; -} - -function readConfigAppName( - target: ComputeDeployTarget | null, - configAnnotation: string, -): MergedDeployInput | undefined { - if (target?.name) { - return { value: target.name, annotation: configAnnotation }; - } - if (target?.key) { - return { value: target.key, annotation: configAnnotation }; - } - return undefined; -} - -export interface MergedComputeLocalInputs { - entrypoint: string | undefined; - /** Resolved build type, or undefined for auto detection. */ - buildType: string | undefined; - /** True when the build type came from the config framework, not a flag. */ - buildTypeFromConfig: boolean; - port: string | undefined; - /** App directory relative to the invocation directory, or undefined for the invocation directory. */ - appRoot: string | undefined; -} - -/** - * Merges CLI inputs for the local `app build` and `app run` commands with a - * selected config target. Explicit flags win; `--build-type auto` is the - * flag default and defers to the configured framework. - */ -export function mergeComputeLocalInputs(options: { - cli: { - entrypoint?: string; - buildType?: string; - port?: string; - }; - target: ComputeDeployTarget | null; -}): MergedComputeLocalInputs { - const { cli, target } = options; - const cliBuildType = - cli.buildType && cli.buildType !== "auto" ? cli.buildType : undefined; - const configBuildType = target?.framework - ? computeFrameworkToBuildType(target.framework) - : undefined; - - return { - entrypoint: cli.entrypoint ?? target?.entry ?? undefined, - buildType: cliBuildType ?? configBuildType, - buildTypeFromConfig: !cliBuildType && configBuildType !== undefined, - port: cli.port ?? (target?.httpPort ? String(target.httpPort) : undefined), - appRoot: target?.root ?? undefined, - }; -} - -/** The `app` subcommand used in error guidance text, e.g. "deploy" or "domain add". */ +/** The `service` subcommand used in error guidance text, e.g. "create" or "domain add". */ export type ComputeConfigCommandName = string; export function computeConfigErrorToCliError( error: ComputeConfigError | ComputeConfigTargetError, - commandName: ComputeConfigCommandName = "deploy", + commandName: ComputeConfigCommandName, ): CliError { - const command = `prisma-cli app ${commandName}`; + const command = `prisma-cli service ${commandName}`; return matchError(error, { ComputeConfigAmbiguousError: (ambiguous) => new CliError({ diff --git a/packages/cli/src/lib/app/env-file.ts b/packages/cli/src/lib/app/env-file.ts index ad0a2023..c4d428d1 100644 --- a/packages/cli/src/lib/app/env-file.ts +++ b/packages/cli/src/lib/app/env-file.ts @@ -11,7 +11,7 @@ export interface EnvFileAssignment { value: string; } -type EnvFileCommand = "add" | "update" | "deploy"; +type EnvFileCommand = "add" | "update"; interface ParsedEnvFileKey { key: string; @@ -34,11 +34,7 @@ export async function readEnvFileAssignments( `Failed to read env file "${filePath}"`, error instanceof Error ? error.message : "The file could not be read.", "Pass a readable dotenv file path.", - [ - command === "deploy" - ? "prisma-cli app deploy --env .env" - : `prisma-cli project env ${command} --file .env --role preview`, - ], + [`prisma-cli project env ${command} --file .env --role preview`], "app", ); } @@ -145,7 +141,7 @@ function validateEnvFileKey( command: EnvFileCommand, ): void { try { - validateKey(key, command === "deploy" ? "add" : command); + validateKey(key, command); } catch (error) { const reason = error instanceof Error && error.message.length > 0 diff --git a/packages/cli/src/lib/project/provider.ts b/packages/cli/src/lib/project/provider.ts index 1ccc0efc..950d2968 100644 --- a/packages/cli/src/lib/project/provider.ts +++ b/packages/cli/src/lib/project/provider.ts @@ -140,9 +140,9 @@ export function projectRemoveBlockedError( why: error?.error?.message ?? `Project "${projectId}" still has active deployments.`, - fix: "Remove the project's apps first, then retry the removal.", + fix: "Remove the project's services first, then retry the removal.", exitCode: 1, - nextSteps: [formatPrismaCliCommand(["app", "remove", "--app", ""])], + nextSteps: [formatPrismaCliCommand(["service", "remove", ""])], }); } diff --git a/packages/cli/src/lib/project/resolution.ts b/packages/cli/src/lib/project/resolution.ts index 90540272..b54916e3 100644 --- a/packages/cli/src/lib/project/resolution.ts +++ b/packages/cli/src/lib/project/resolution.ts @@ -271,9 +271,9 @@ function projectAmbiguousCliError( const firstMatch = matches[0]; const nextSteps = ["prisma-cli project list"]; if (firstMatch) { - // Surface the matched id verbatim so the user can see the exact - // shape of the disambiguation flag instead of guessing. - nextSteps.push(`prisma-cli app deploy --project ${firstMatch.id}`); + // Surface the matched id verbatim so the user can copy the exact + // shape of a disambiguating reference instead of guessing. + nextSteps.push(`prisma-cli project link ${firstMatch.id}`); } return new CliError({ diff --git a/packages/cli/src/lib/project/setup.ts b/packages/cli/src/lib/project/setup.ts index f3596502..1a9683a3 100644 --- a/packages/cli/src/lib/project/setup.ts +++ b/packages/cli/src/lib/project/setup.ts @@ -85,10 +85,7 @@ function localStateWriteFailedError( debug: formatDebugDetails(error.cause), meta: options.meta, exitCode: 1, - nextSteps: [ - "prisma-cli project link ", - "prisma-cli app deploy --project ", - ], + nextSteps: ["prisma-cli project link "], }); } diff --git a/packages/cli/tests/agent.test.ts b/packages/cli/tests/agent.test.ts index 2b7638d1..491c5879 100644 --- a/packages/cli/tests/agent.test.ts +++ b/packages/cli/tests/agent.test.ts @@ -183,7 +183,7 @@ describe("prisma-cli agent install", () => { { kind: "run-command", label: "Verify the installed Prisma skills", - command: "npx -y @prisma/cli@latest agent status", + command: "npx -y @prisma/cli@next agent status", }, ]); }); @@ -202,7 +202,7 @@ describe("prisma-cli agent install", () => { { kind: "run-command", label: "Verify the installed Prisma skills", - command: "npx -y @prisma/cli@latest agent status --global", + command: "npx -y @prisma/cli@next agent status --global", }, ]); }); @@ -494,7 +494,7 @@ describe("prisma-cli agent status", () => { { kind: "run-command", label: "Install or refresh Prisma skills", - command: "npx -y @prisma/cli@latest agent install --global", + command: "npx -y @prisma/cli@next agent install --global", }, ]); }); @@ -514,7 +514,7 @@ describe("prisma-cli agent status", () => { { kind: "run-command", label: "Install or refresh Prisma skills", - command: "npx -y @prisma/cli@latest agent install", + command: "npx -y @prisma/cli@next agent install", }, ]); }); diff --git a/packages/cli/tests/compute-config.test.ts b/packages/cli/tests/compute-config.test.ts index 96cb2b1c..e6d2bad1 100644 --- a/packages/cli/tests/compute-config.test.ts +++ b/packages/cli/tests/compute-config.test.ts @@ -16,13 +16,9 @@ import { import { afterEach, describe, expect, it } from "vitest"; import { CliError } from "../src/errors"; import { - type ComputeDeployTarget, computeConfigErrorToCliError, - computeFrameworkToBuildType, type LoadedComputeConfig, loadComputeConfig, - mergeComputeDeployInputs, - mergeComputeLocalInputs, } from "../src/lib/app/compute-config"; const CONFIG_PATH = "/repo/prisma.compute.ts"; @@ -345,177 +341,6 @@ describe("selectComputeDeployTarget", () => { }); }); -describe("mergeComputeDeployInputs", () => { - const target = { - key: "web", - name: null, - region: "us-west-1", - root: "apps/web", - framework: "nextjs", - entry: null, - httpPort: 8080, - envInputs: [".env", "LOG_LEVEL=debug"], - build: null, - } as ComputeDeployTarget; - - it("uses config values when flags are absent", () => { - const merged = mergeComputeDeployInputs({ - cli: {}, - target, - configFilename: COMPUTE_CONFIG_FILENAME, - }); - - expect(merged.framework).toEqual({ - value: "nextjs", - annotation: "set by prisma.compute.ts", - }); - expect(merged.httpPort).toEqual({ - value: "8080", - annotation: "set by prisma.compute.ts", - }); - expect(merged.region).toEqual({ - value: "us-west-1", - annotation: "set by prisma.compute.ts", - }); - expect(merged.envInputs).toEqual([".env", "LOG_LEVEL=debug"]); - expect(merged.configAppName).toEqual({ - value: "web", - annotation: "set by prisma.compute.ts", - }); - expect(merged.appRoot).toBe("apps/web"); - }); - - it("prefers explicit flags over config values", () => { - const merged = mergeComputeDeployInputs({ - cli: { - framework: "bun", - entrypoint: "server.ts", - httpPort: "3000", - region: "eu-west-3", - envInputs: ["DATABASE_URL=postgresql://example"], - }, - target, - configFilename: COMPUTE_CONFIG_FILENAME, - }); - - expect(merged.framework).toEqual({ - value: "bun", - annotation: "set by --framework", - }); - expect(merged.entrypoint).toEqual({ - value: "server.ts", - annotation: "set by --entry", - }); - expect(merged.httpPort).toEqual({ - value: "3000", - annotation: "set by --http-port", - }); - expect(merged.region).toEqual({ - value: "eu-west-3", - annotation: "set by --region", - }); - // --env replaces config env inputs entirely; they never merge. - expect(merged.envInputs).toEqual(["DATABASE_URL=postgresql://example"]); - }); - - it("prefers the config name over the apps key", () => { - const merged = mergeComputeDeployInputs({ - cli: {}, - target: { ...target, name: "storefront" }, - configFilename: COMPUTE_CONFIG_FILENAME, - }); - - expect(merged.configAppName?.value).toBe("storefront"); - }); - - it("passes CLI values through without a config file", () => { - const merged = mergeComputeDeployInputs({ - cli: { framework: "hono" }, - target: null, - configFilename: COMPUTE_CONFIG_FILENAME, - }); - - expect(merged.framework).toEqual({ - value: "hono", - annotation: "set by --framework", - }); - expect(merged.entrypoint).toBeUndefined(); - expect(merged.region).toBeUndefined(); - expect(merged.envInputs).toBeUndefined(); - expect(merged.configAppName).toBeUndefined(); - expect(merged.appRoot).toBeUndefined(); - }); -}); - -describe("mergeComputeLocalInputs", () => { - const target = { - key: "api", - name: null, - region: null, - root: "apps/api", - framework: "hono", - entry: "src/index.ts", - httpPort: 8080, - envInputs: [], - build: null, - } as ComputeDeployTarget; - - it("maps the configured framework to a local build type", () => { - expect(computeFrameworkToBuildType("nextjs")).toBe("nextjs"); - expect(computeFrameworkToBuildType("hono")).toBe("bun"); - expect(computeFrameworkToBuildType("bun")).toBe("bun"); - expect(computeFrameworkToBuildType("tanstack-start")).toBe( - "tanstack-start", - ); - expect(computeFrameworkToBuildType("custom")).toBe("custom"); - }); - - it("uses config values when flags are absent or default", () => { - const merged = mergeComputeLocalInputs({ - cli: { buildType: "auto" }, - target, - }); - - expect(merged).toEqual({ - entrypoint: "src/index.ts", - buildType: "bun", - buildTypeFromConfig: true, - port: "8080", - appRoot: "apps/api", - }); - }); - - it("prefers explicit flags over config values", () => { - const merged = mergeComputeLocalInputs({ - cli: { entrypoint: "server.ts", buildType: "nextjs", port: "4000" }, - target, - }); - - expect(merged).toEqual({ - entrypoint: "server.ts", - buildType: "nextjs", - buildTypeFromConfig: false, - port: "4000", - appRoot: "apps/api", - }); - }); - - it("falls back to auto detection without a config target", () => { - const merged = mergeComputeLocalInputs({ - cli: { buildType: "auto" }, - target: null, - }); - - expect(merged).toEqual({ - entrypoint: undefined, - buildType: undefined, - buildTypeFromConfig: false, - port: undefined, - appRoot: undefined, - }); - }); -}); - describe("loadComputeConfig", () => { const tempDirs: string[] = []; @@ -890,6 +715,7 @@ describe("computeConfigErrorToCliError", () => { it("maps config errors to structured CliErrors", () => { const invalid = computeConfigErrorToCliError( new ComputeConfigInvalidError(CONFIG_PATH, ["bad"]), + "create", ); expect(invalid).toBeInstanceOf(CliError); expect(invalid.code).toBe("COMPUTE_CONFIG_INVALID"); @@ -897,15 +723,17 @@ describe("computeConfigErrorToCliError", () => { const required = computeConfigErrorToCliError( new ComputeConfigTargetRequiredError(CONFIG_PATH, ["web", "worker"]), + "create", ); expect(required.code).toBe("COMPUTE_CONFIG_TARGET_REQUIRED"); expect(required.nextSteps).toEqual([ - "prisma-cli app deploy web", - "prisma-cli app deploy worker", + "prisma-cli service create web", + "prisma-cli service create worker", ]); const unknown = computeConfigErrorToCliError( new ComputeConfigTargetUnknownError(CONFIG_PATH, "docs", ["web"]), + "create", ); expect(unknown.code).toBe("COMPUTE_CONFIG_TARGET_UNKNOWN"); expect(unknown.summary).toContain('"docs"'); diff --git a/packages/cli/tests/helpers/deploy-result.ts b/packages/cli/tests/helpers/deploy-result.ts deleted file mode 100644 index 4da9b6d0..00000000 --- a/packages/cli/tests/helpers/deploy-result.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { AppDeployAllResult, AppDeployResult } from "../../src/types/app"; - -/** - * Narrows a deploy result to the single-app shape; throws on deploy-all. - * Only type-only src imports here, so test files can import this statically - * without loading the CLI module graph before vi.doMock calls apply. - */ -export function asSingleDeployResult< - T extends { result: AppDeployResult | AppDeployAllResult }, ->(success: T): T & { result: AppDeployResult } { - if ("deployments" in success.result) { - throw new Error( - "Expected a single-app deploy result, got a deploy-all result.", - ); - } - return success as T & { result: AppDeployResult }; -} diff --git a/packages/cli/tests/init.test.ts b/packages/cli/tests/init.test.ts index 7ef3d76f..8d88a547 100644 --- a/packages/cli/tests/init.test.ts +++ b/packages/cli/tests/init.test.ts @@ -386,10 +386,10 @@ describe("init writes the config", () => { command: "npm install -D @prisma/compute-sdk", }), expect.objectContaining({ - command: "npx -y @prisma/cli@latest app deploy", + command: "npx -y @prisma/cli@next git connect", }), expect.objectContaining({ - command: "npx -y @prisma/cli@latest project link", + command: "npx -y @prisma/cli@next project link", }), ]); }); @@ -823,7 +823,7 @@ describe("init link step", () => { ).toEqual({ workspaceId: WORKSPACE_ID, projectId: "proj_123" }); expect(envelopeOf(result).nextActions).not.toContainEqual( expect.objectContaining({ - command: "npx -y @prisma/cli@latest project link", + command: "npx -y @prisma/cli@next project link", }), ); }); diff --git a/packages/cli/tests/project.test.ts b/packages/cli/tests/project.test.ts index 82cee224..c0680114 100644 --- a/packages/cli/tests/project.test.ts +++ b/packages/cli/tests/project.test.ts @@ -558,8 +558,8 @@ describe("prisma-cli project create", () => { expect(result.presented?.presentation.next).toEqual([ { kind: "run-command", - label: "prisma-cli app deploy", - command: "prisma-cli app deploy", + label: "prisma-cli git connect", + command: "prisma-cli git connect", }, ]); }); @@ -684,8 +684,8 @@ describe("prisma-cli project create", () => { nextActions: [ { kind: "run-command", - label: "prisma-cli app deploy", - command: "prisma-cli app deploy", + label: "prisma-cli git connect", + command: "prisma-cli git connect", }, ], }); diff --git a/packages/cli/tests/update-check.test.ts b/packages/cli/tests/update-check.test.ts index 7b3e3b42..f823e8c6 100644 --- a/packages/cli/tests/update-check.test.ts +++ b/packages/cli/tests/update-check.test.ts @@ -116,7 +116,7 @@ describe("update discovery and instructions", () => { argv: ["node", "/Users/alice/.npm/_npx/123/node_modules/.bin/prisma-cli"], expected: { type: "docs", - value: "https://www.prisma.io/docs/orm/tools/prisma-cli", + value: "https://www.prisma.io/docs", }, }, { @@ -128,7 +128,7 @@ describe("update discovery and instructions", () => { argv: ["node", "/repo/node_modules/.bin/prisma-cli"], expected: { type: "docs", - value: "https://www.prisma.io/docs/orm/tools/prisma-cli", + value: "https://www.prisma.io/docs", }, }, { @@ -137,7 +137,7 @@ describe("update discovery and instructions", () => { argv: ["node", "/Users/alice/.bun/install/cache/@prisma/cli/prisma-cli"], expected: { type: "docs", - value: "https://www.prisma.io/docs/orm/tools/prisma-cli", + value: "https://www.prisma.io/docs", }, }, { @@ -146,7 +146,7 @@ describe("update discovery and instructions", () => { argv: ["node", "/some/path/prisma-cli"], expected: { type: "docs", - value: "https://www.prisma.io/docs/orm/tools/prisma-cli", + value: "https://www.prisma.io/docs", }, }, ])("selects update instructions for $name", ({ env, argv, expected }) => { diff --git a/packages/prisma/README.md b/packages/prisma/README.md index 9d495f88..d9355839 100644 --- a/packages/prisma/README.md +++ b/packages/prisma/README.md @@ -15,15 +15,9 @@ `prisma` is the public beta of the new CLI for the Prisma Developer Platform. -It is the terminal surface managing your platform projects, branches, apps, -deployments, and environment variables. - -The command model is under active development to include tooling for your -schema, database, migration, and broader platform workflows. - -Looking for Prisma ORM commands such as `prisma generate`, `prisma migrate`, or -`prisma studio`? Use the [`prisma`](https://www.npmjs.com/package/prisma) -package. +It is one binary for the ORM, Composer, and the Prisma Developer +Platform: projects, branches, services, deployments, environment +variables, and the Prisma ORM schema and migration workflow. --- @@ -40,55 +34,59 @@ Run the binary exposed by this package: ```bash npx prisma --help npx prisma auth login -npx prisma app deploy +npx prisma project create my-app +npx prisma git connect git@github.com:owner/repo.git ``` +Deployments start from pushing the connected repository, the Console, or +`prisma composer deploy` — there is no standalone deploy command. + With `pnpm`: ```bash -pnpm add -D prisma +pnpm add -D prisma@next pnpm prisma auth login -pnpm prisma app deploy +pnpm prisma git connect ``` Useful next commands: ```bash -npx prisma app logs -npx prisma app open +npx prisma service list +npx prisma service logs npx prisma project env add DATABASE_URL=postgresql://example --role preview npx prisma project env add --file .env --role preview npx prisma project env list npx prisma project env list --role preview ``` -The beta package exposes `prisma-cli` so it can coexist with the existing -`prisma` executable. - --- ## Commands | Group | What it does | | --- | --- | -| `version` | Show the installed CLI build and host environment. | | `auth` | Log in, log out, and inspect the active Prisma account. | -| `project` | List projects, show the resolved project, and manage project environment variables. | -| `git` | Connect or disconnect a project from a GitHub repository. | +| `project` | List, create, link, and manage projects and their environment variables. | +| `git` | Connect or disconnect a project from a GitHub repository; pushes deploy. | | `branch` | List Prisma branches for the resolved project. | -| `database` | Create, inspect, and remove Prisma Postgres databases and their connection strings. | -| `bucket` | Create, list, and delete Tigris object-store buckets and their access keys. | -| `app` | Build, run, deploy, inspect, open, stream logs, promote, roll back, and remove apps. | +| `postgres` | Create, inspect, restore, and remove Prisma Postgres databases and their connections. | +| `bucket` | Create, list, and delete object-store buckets and their access keys. | +| `service` | Inspect services: deployments, logs, domains, promote, roll back, remove. | +| `build` | Stream platform build logs. | +| `composer` | Deploy, destroy, and develop Composer apps. | +| `contract`, `db`, `migrate`, `migration`, `format`, `orm init`, `lsp` | The Prisma ORM workflow. | +| `init` | Write a committed compute config for the project. | Common examples: ```bash -npx prisma version +npx prisma --version npx prisma auth whoami npx prisma project show npx prisma branch list -npx prisma app deploy --branch feat-login --framework nextjs -npx prisma app promote +npx prisma service list +npx prisma service deployment promote DEPLOYMENT_ID ``` ### Built for humans, CI, and agents @@ -105,9 +103,9 @@ npx prisma app promote ## Beta notes - Requires Node.js 22.18 or newer. -- This is a beta package and may change quickly. -- Official beta releases publish as `prisma`. -- The package binary is `prisma-cli`, not `prisma`, during beta. +- This is a release-candidate package and may change quickly. +- The 8.0.0 release candidates publish as `prisma` on the `next` dist-tag. +- The package binary is `prisma`. - Local project context is cached in `.prisma/local.json`, which is gitignored and not a declarative repo config file. --- @@ -115,9 +113,7 @@ npx prisma app promote ## Documentation - [CLI docs index](https://github.com/prisma/prisma-cli/blob/main/docs/README.md) -- [Resource model](https://github.com/prisma/prisma-cli/blob/main/docs/product/resource-model.md) - [Command principles](https://github.com/prisma/prisma-cli/blob/main/docs/product/command-principles.md) -- [Command spec](https://github.com/prisma/prisma-cli/blob/main/docs/product/command-spec.md) - [Output conventions](https://github.com/prisma/prisma-cli/blob/main/docs/product/output-conventions.md) - [Error conventions](https://github.com/prisma/prisma-cli/blob/main/docs/product/error-conventions.md)