From 134dee20918981aa7a6f361cfcbb4074c6ff7c6c Mon Sep 17 00:00:00 2001 From: Philip Olson Date: Thu, 13 Aug 2026 12:59:31 -0700 Subject: [PATCH] Improve neon init onboarding and preserve fields on .neon writes neon init had drifted from the current CLI: it probed for the retired neonctl alias (so it failed to detect an installed neon CLI and tried to reinstall), hand-edited .neon instead of using neon link (and never recorded the branch), and linked to doc pages that had since moved. This reworks the standard flow to detect and install neon, delegate org/project selection and the .neon write to `neon link --agent` (which records org, project, and branch), point the doc references at current pages, and suggest `neon psql` as a quick connection check. The --preview path is unchanged. Separately, writing .neon through link, checkout, or set-context now preserves fields it does not own, so a neon link no longer clobbers init's in-progress state; neon link --clear still resets the file. Co-authored-by: Isaac --- .changeset/neon-init-link-and-context.md | 10 + packages/cli/e2e/init.e2e.test.ts | 200 ++-- packages/cli/src/commands/link.ts | 4 +- packages/cli/src/context.test.ts | 110 +++ packages/cli/src/context.ts | 65 +- .../__snapshots__/agent_snapshot.test.ts.snap | 856 +++++++----------- packages/cli/src/init/agent_snapshot.test.ts | 9 +- packages/cli/src/init/auth.ts | 6 +- packages/cli/src/init/neonctl.ts | 80 +- packages/cli/src/init/phases/db.test.ts | 2 +- packages/cli/src/init/phases/db.ts | 4 +- .../src/init/phases/getting_started.test.ts | 45 +- .../cli/src/init/phases/getting_started.ts | 108 +-- packages/cli/src/init/phases/neon_auth.ts | 6 +- packages/cli/src/init/phases/skills.ts | 4 +- packages/cli/src/init/resolve_context.ts | 6 +- packages/cli/src/init/skills.test.ts | 14 +- packages/cli/src/init/skills.ts | 27 +- 18 files changed, 794 insertions(+), 762 deletions(-) create mode 100644 .changeset/neon-init-link-and-context.md diff --git a/.changeset/neon-init-link-and-context.md b/.changeset/neon-init-link-and-context.md new file mode 100644 index 00000000..d096f92a --- /dev/null +++ b/.changeset/neon-init-link-and-context.md @@ -0,0 +1,10 @@ +--- +"neon": minor +--- + +Improve `neon init` onboarding and make `.neon` context writes non-destructive: + +- Detect and install the `neon` CLI during init, not the retired `neonctl` alias. +- Use `neon link` to create/link the project and write `.neon` (branch included) instead of hand-editing it. +- Writing `.neon` via `link`, `checkout`, or `set-context` now preserves unrelated fields; `neon link --clear` still resets it. +- Update init's doc links, and suggest `neon psql` as a quick connection check. diff --git a/packages/cli/e2e/init.e2e.test.ts b/packages/cli/e2e/init.e2e.test.ts index b9c50782..1b179edc 100644 --- a/packages/cli/e2e/init.e2e.test.ts +++ b/packages/cli/e2e/init.e2e.test.ts @@ -10,12 +10,7 @@ import { tmpdir } from "node:os"; import { join } from "node:path"; import { configuredOrgId } from "@neon/e2e-harness"; import { afterAll, beforeAll, describe, expect, it } from "vitest"; -import { - createProject, - deleteProject, - runCli, - uniqueProjectName, -} from "./helpers.js"; +import { deleteProject, runCli, uniqueProjectName } from "./helpers.js"; /** * `neon init --agent` is a protocol rather than a command that does the work: it answers with @@ -78,43 +73,50 @@ type PhaseResponse = { }; describe.sequential("e2e — neon init emits commands that work", () => { - let projectId: string; - /** Projects the emitted `projects create` produced, removed in teardown. */ + /** Projects created by driving `neon link`, removed in teardown. */ const created: string[] = []; const orgId = configuredOrgId(); /** - * Everything runs here rather than in the checkout: `env pull` writes a connection string - * and password into it, and the phase would install skills here if the scrub above ever - * stopped working. Removed in teardown, credentials included. + * Everything runs here rather than in the checkout: `neon link` and `env pull` write the + * `.neon` context and a connection string into it, and the phase would install skills here + * if the scrub above ever stopped working. Removed in teardown, credentials included. */ const workdir = mkdtempSync(join(tmpdir(), "neon-init-e2e-")); const contextFile = join(workdir, ".neon"); - beforeAll(async () => { - // Make the workdir a pnpm project: the emitted install steps must follow - // it rather than the npm this suite used to assert, and the `.git` marker - // stops the lockfile walk from climbing into $TMPDIR's ancestors. + beforeAll(() => { + // Make the workdir a pnpm project: the emitted install step must follow it, and the + // `.git` marker stops the lockfile walk from climbing into $TMPDIR's ancestors. mkdirSync(join(workdir, ".git")); writeFileSync(join(workdir, "pnpm-lock.yaml"), ""); - - projectId = await createProject({ - name: uniqueProjectName("cli-init"), - }); - writeFileSync(contextFile, `${JSON.stringify({ orgId, projectId })}\n`); }); afterAll(async () => { rmSync(workdir, { recursive: true, force: true }); - for (const id of [...created, projectId]) { + for (const id of created) { if (id) await deleteProject(id); } }); - it("hands an agent a working org, project and env sequence", async () => { + /** Strip the emitted `CI= npx -y neon ` prefix and split into CLI args. */ + const emittedArgs = (command: string): string[] => { + expect(command.startsWith(EMITTED_PREFIX)).toBe(true); + return command.slice(EMITTED_PREFIX.length).split(/\s+/); + }; + + /** Run one `neon link --agent` turn against the real API, non-interactively. */ + const link = (args: string[]) => + runCli(["link", "--agent", ...args], { + env: { ...NO_AGENT_ENV, CI: "" }, + cwd: workdir, + contextFile, + }); + + it("hands an agent a link → env sequence that creates and connects a project", async () => { if (!orgId) { throw new Error( - "NEON_ORG_ID is required: the emitted commands take an --org-id, and substituting one is the point of this test.", + "NEON_ORG_ID is required: `neon link` takes an --org-id, and supplying one is the point of this test.", ); } @@ -137,82 +139,96 @@ describe.sequential("e2e — neon init emits commands that work", () => { expect(response.nextAction?.type).toBe("agent_action"); const steps = response.nextAction?.steps ?? []; const ids = steps.map((step) => step.id); - // The sequence a user is walked through. Pinned so a step disappearing from the - // flow fails here rather than quietly reducing what this test exercises. + // The standard flow delegates org/project selection to `neon link`. Pinned so a step + // disappearing from the flow fails here rather than quietly reducing what runs. expect(ids).toEqual( expect.arrayContaining([ - "select_org", - "select_or_create_project", - "create_project_if_needed", + "link_project", + "install_dependencies", "pull_env", + "verify_connection", ]), ); - const executed: string[] = []; - for (const step of steps) { - if (!step.command) continue; - - // Install steps belong to the user's package manager, not to us. Assert we - // addressed the workdir's pnpm rather than running an install on the machine. - if (!step.command.startsWith(EMITTED_PREFIX)) { - expect(step.command).toMatch(/^pnpm (install|add) ?/); - continue; - } - - const args = step.command - .slice(EMITTED_PREFIX.length) - .replace("", orgId) - .replace("", uniqueProjectName("init-emitted")) - .split(/\s+/); - - const result = await runCli(args, { - env: { ...NO_AGENT_ENV, CI: "" }, - cwd: workdir, - contextFile, - }); - expect(result.code, `${step.command}\n${result.stderr}`).toBe(0); - executed.push(step.id); - - if (step.id === "select_org") { - const orgs = JSON.parse(result.stdout) as { id: string }[]; - expect(orgs.map((org) => org.id)).toContain(orgId); - } - if (step.id === "select_or_create_project") { - // The phase tells the agent to filter this list, so it has to be parseable - // and it has to contain the project the agent would pick. - const projects = JSON.parse(result.stdout) as { id: string }[]; - expect(projects.map((project) => project.id)).toContain( - projectId, - ); - } - if (step.id === "create_project_if_needed") { - const { project } = JSON.parse(result.stdout) as { - project: { id: string; name: string }; - }; - created.push(project.id); - expect(project.name).toMatch(/^neon-ts-e2e-/); - } - if (step.id === "pull_env") { - // Exit 0 is not the outcome that matters: `env pull` succeeds when it - // resolves nothing. The whole sequence exists to leave a connection string - // on disk, so read the file it wrote. - const envFile = join(workdir, ".env.local"); - expect(existsSync(envFile)).toBe(true); - expect(readFileSync(envFile, "utf8")).toMatch( - /^DATABASE_URL="?postgresql:\/\/.+/m, - ); - } - } - - // Every command the flow emits for us must have run, or this test proved less than - // it claims. `pull_env` last: it is the step that produces the connection string the - // whole sequence exists to obtain. - expect(executed).toEqual([ - "select_org", - "select_or_create_project", - "create_project_if_needed", - "pull_env", + const linkStep = steps.find((step) => step.id === "link_project"); + const pullStep = steps.find((step) => step.id === "pull_env"); + expect(linkStep?.command).toBe(`${EMITTED_PREFIX}link --agent`); + expect(pullStep?.command).toBe(`${EMITTED_PREFIX}env pull`); + + // 1. The emitted link command runs and returns a state-machine response — either org + // selection or project selection, depending on how many orgs the key can see. + const first = await runCli(emittedArgs(linkStep?.command ?? ""), { + env: { ...NO_AGENT_ENV, CI: "" }, + cwd: workdir, + contextFile, + }); + expect(first.code, first.stderr).toBe(0); + const firstStatus = (JSON.parse(first.stdout) as { status: string }) + .status; + expect(["needs_org", "needs_project"]).toContain(firstStatus); + + // 2. Ask to create a project without a region → the CLI lists the regions to pick from. + const projectName = uniqueProjectName("init-link"); + const details = await link([ + "--org-id", + orgId, + "--project-name", + projectName, + ]); + expect(details.code, details.stderr).toBe(0); + const detailsResp = JSON.parse(details.stdout) as { + status: string; + regions?: { id: string; default: boolean }[]; + }; + expect(detailsResp.status).toBe("needs_project_details"); + const region = + detailsResp.regions?.find((r) => r.default) ?? + detailsResp.regions?.[0]; + expect(region, "link should return at least one region").toBeTruthy(); + + // 3. Create + link with the chosen region → status linked, and `.neon` written for us. + const linked = await link([ + "--org-id", + orgId, + "--project-name", + projectName, + "--region-id", + region?.id ?? "", ]); + expect(linked.code, linked.stderr).toBe(0); + const linkedResp = JSON.parse(linked.stdout) as { + status: string; + project?: { id: string }; + }; + // Track for teardown the moment we know the id, ahead of the assertions below. + if (linkedResp.project?.id) created.push(linkedResp.project.id); + expect(linkedResp.status).toBe("linked"); + + // `neon link` records org, project AND branch — the gap the old hand-edited .neon left. + const context = JSON.parse(readFileSync(contextFile, "utf8")) as { + orgId?: string; + projectId?: string; + branch?: string; + }; + expect(context.orgId).toBe(orgId); + expect(context.projectId).toBe(linkedResp.project?.id); + expect( + context.branch, + ".neon should pin the created project's branch", + ).toBeTruthy(); + + // 4. The emitted pull_env step writes a real connection string to disk. + const pull = await runCli(emittedArgs(pullStep?.command ?? ""), { + env: { ...NO_AGENT_ENV, CI: "" }, + cwd: workdir, + contextFile, + }); + expect(pull.code, pull.stderr).toBe(0); + const envFile = join(workdir, ".env.local"); + expect(existsSync(envFile)).toBe(true); + expect(readFileSync(envFile, "utf8")).toMatch( + /^DATABASE_URL="?postgresql:\/\/.+/m, + ); }); it("reports an unknown step instead of guessing", async () => { diff --git a/packages/cli/src/commands/link.ts b/packages/cli/src/commands/link.ts index 575e9afb..a73f8d95 100644 --- a/packages/cli/src/commands/link.ts +++ b/packages/cli/src/commands/link.ts @@ -12,10 +12,10 @@ import { isNeonApiError, messageFromBody } from "../api.js"; import { applyContext, type Context, + clearContextFile, contextBranch, readContextFile, setContext, - updateContextFile, } from "../context.js"; import { isCi } from "../env.js"; import { log } from "../log.js"; @@ -322,7 +322,7 @@ const canResolveNonInteractively = ( // ---------------------------------------------------------------------------- const clearContext = (contextFile: string): void => { - updateContextFile(contextFile, {}); + clearContextFile(contextFile); process.stdout.write( `Cleared ${contextFile}. The directory is no longer linked to a Neon org/project/branch.\n`, ); diff --git a/packages/cli/src/context.test.ts b/packages/cli/src/context.test.ts index d4b19d30..9d2ea843 100644 --- a/packages/cli/src/context.test.ts +++ b/packages/cli/src/context.test.ts @@ -11,9 +11,11 @@ import { afterEach, beforeEach, describe, expect, test } from "vitest"; import { applyContext, + clearContextFile, currentContextFile, ensureGitignored, isCurrentBranchProbe, + updateContextFile, walkContextFile, } from "./context.js"; @@ -353,3 +355,111 @@ describe("applyContext", () => { ); }); }); + +describe("updateContextFile foreign-key preservation", () => { + let workspace: string; + + beforeEach(() => { + workspace = mkdtempSync(join(tmpdir(), "neonctl-update-")); + }); + + afterEach(() => { + rmSync(workspace, { recursive: true, force: true }); + }); + + test("preserves foreign keys (e.g. init's _init) while writing managed fields", () => { + const file = join(workspace, ".neon"); + writeFileSync( + file, + JSON.stringify({ orgId: "org-old", _init: { features: ["auth"] } }), + ); + + updateContextFile(file, { + orgId: "org-new", + projectId: "proj-1", + branch: "main", + }); + + expect(JSON.parse(readFileSync(file, "utf-8"))).toEqual({ + orgId: "org-new", + projectId: "proj-1", + branch: "main", + _init: { features: ["auth"] }, + }); + }); + + test("drops managed fields absent from the write, keeps foreign ones", () => { + const file = join(workspace, ".neon"); + writeFileSync( + file, + JSON.stringify({ + orgId: "org-1", + projectId: "proj-1", + branch: "feat", + _init: { step: "getting-started" }, + }), + ); + + // Re-link the same project without a branch: the stale branch must clear, + // but the foreign _init must survive. + updateContextFile(file, { orgId: "org-1", projectId: "proj-1" }); + + expect(JSON.parse(readFileSync(file, "utf-8"))).toEqual({ + orgId: "org-1", + projectId: "proj-1", + _init: { step: "getting-started" }, + }); + }); + + test("replaces the legacy branchId rather than preserving it as foreign", () => { + const file = join(workspace, ".neon"); + writeFileSync( + file, + JSON.stringify({ projectId: "proj-1", branchId: "br-old" }), + ); + + updateContextFile(file, { projectId: "proj-1", branch: "main" }); + + expect(JSON.parse(readFileSync(file, "utf-8"))).toEqual({ + projectId: "proj-1", + branch: "main", + }); + }); + + test("writes managed fields as-is when the file does not yet exist", () => { + const file = join(workspace, ".neon"); + updateContextFile(file, { orgId: "org-1", projectId: "proj-1" }); + expect(JSON.parse(readFileSync(file, "utf-8"))).toEqual({ + orgId: "org-1", + projectId: "proj-1", + }); + }); +}); + +describe("clearContextFile", () => { + let workspace: string; + + beforeEach(() => { + workspace = mkdtempSync(join(tmpdir(), "neonctl-clear-")); + }); + + afterEach(() => { + rmSync(workspace, { recursive: true, force: true }); + }); + + test("wipes the file wholesale, dropping foreign keys too", () => { + const file = join(workspace, ".neon"); + writeFileSync( + file, + JSON.stringify({ + orgId: "org-1", + projectId: "proj-1", + _init: { features: ["auth"] }, + }), + ); + + clearContextFile(file); + + expect(JSON.parse(readFileSync(file, "utf-8"))).toEqual({}); + }); +}); diff --git a/packages/cli/src/context.ts b/packages/cli/src/context.ts index e23c7ea0..3610f705 100644 --- a/packages/cli/src/context.ts +++ b/packages/cli/src/context.ts @@ -205,15 +205,72 @@ export const enrichFromContext = ( } }; +/** + * The context fields these commands own. On write we replace exactly these keys + * from the supplied `context`; every *other* key already in the file (e.g. the + * ephemeral `_init` state `neon init` stashes, or anything a user hand-added) is + * carried forward untouched. `branchId` is listed as managed — not to preserve + * it, but so the legacy field is replaced/dropped like the others rather than + * lingering as a "foreign" key (see {@link Context.branchId}). + */ +const MANAGED_CONTEXT_KEYS = new Set([ + "orgId", + "projectId", + "branch", + "branchId", +]); + +/** The keys in an existing `.neon` that a context write must not disturb. */ +const readForeignKeys = (file: string): Record => { + let raw: unknown; + try { + raw = JSON.parse(readFileSync(file, "utf-8")); + } catch { + return {}; + } + if (typeof raw !== "object" || raw === null || Array.isArray(raw)) { + return {}; + } + const foreign: Record = {}; + for (const [key, value] of Object.entries(raw)) { + if (!MANAGED_CONTEXT_KEYS.has(key)) { + foreign[key] = value; + } + } + return foreign; +}; + +/** + * Persist the managed context fields to `.neon` while preserving any foreign + * keys already in the file. + * + * The managed keys ({@link MANAGED_CONTEXT_KEYS}) are governed entirely by + * `context`: a field absent from `context` is dropped from the file, so + * re-linking a project without a branch still clears a stale one. Everything + * else in the file — most importantly the ephemeral `_init` state that + * `neon init` writes — is read back and merged in, so a single `neon link` no + * longer clobbers an in-progress init. To wipe the file wholesale (foreign keys + * included), use {@link clearContextFile}. + */ export const updateContextFile = (file: string, context: Context) => { - writeFileSync(file, JSON.stringify(context, null, 2)); + const merged = { ...readForeignKeys(file), ...context }; + writeFileSync(file, JSON.stringify(merged, null, 2)); +}; + +/** + * Reset `.neon` to an empty context, dropping foreign keys too — the `--clear` + * "forget this directory" path, distinct from the field-preserving + * {@link updateContextFile}. + */ +export const clearContextFile = (file: string) => { + writeFileSync(file, JSON.stringify({}, null, 2)); }; /** * Shared primitive used by `link`, the deprecated `set-context`, and `checkout` - * to persist context. Mirrors the destructive write semantics of - * `updateContextFile` — any field not present in `context` is dropped from the - * file. + * to persist context. Delegates to {@link updateContextFile}, so the managed + * fields in `context` are written while foreign keys (like init's `_init`) are + * preserved. * * `.gitignore` scaffolding only happens when the context file is being * *created* (it didn't exist before this write). On updates to an existing diff --git a/packages/cli/src/init/__snapshots__/agent_snapshot.test.ts.snap b/packages/cli/src/init/__snapshots__/agent_snapshot.test.ts.snap index c6059cac..7f3899be 100644 --- a/packages/cli/src/init/__snapshots__/agent_snapshot.test.ts.snap +++ b/packages/cli/src/init/__snapshots__/agent_snapshot.test.ts.snap @@ -292,7 +292,7 @@ exports[`neon init --agent: every step, against every project shape > connected }, "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", + "prerequisite": "https://neon.com/docs/connect/choose-connection.md", "steps": [ { "id": "get_connection_string", @@ -345,32 +345,18 @@ exports[`neon init --agent: every step, against every project shape > connected "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -383,7 +369,7 @@ exports[`neon init --agent: every step, against every project shape > connected }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -408,7 +394,7 @@ exports[`neon init --agent: every step, against every project shape > connected "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ { "id": "run_migrations", @@ -417,7 +403,7 @@ exports[`neon init --agent: every step, against every project shape > connected }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -691,7 +677,7 @@ exports[`neon init --agent: every step, against every project shape > connected "label": "No, skip for now" } ], - "context": "Full documentation: https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "context": "Full documentation: https://neon.com/docs/auth/overview.md", "responseMapping": { "yes": { "command": "neon init --agent --data '{\\"step\\":\\"neon-auth\\",\\"agent\\":\\"cursor\\",\\"setup\\":true}'" @@ -718,7 +704,7 @@ exports[`neon init --agent: every step, against every project shape > connected "status": "in_progress", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "prerequisite": "https://neon.com/docs/auth/overview.md", "steps": [ { "id": "provision", @@ -946,8 +932,8 @@ exports[`neon init --agent: every step, against every project shape > connected --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -985,8 +971,8 @@ exports[`neon init --agent: every step, against every project shape > connected --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -1015,15 +1001,15 @@ exports[`neon init --agent: every step, against every project shape > connected } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -1084,15 +1070,15 @@ exports[`neon init --agent: every step, against every project shape > connected } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -1320,7 +1306,7 @@ exports[`neon init --agent: every step, against every project shape > drizzle > }, "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", + "prerequisite": "https://neon.com/docs/connect/choose-connection.md", "steps": [ { "id": "get_connection_string", @@ -1373,32 +1359,18 @@ exports[`neon init --agent: every step, against every project shape > drizzle > "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -1411,7 +1383,7 @@ exports[`neon init --agent: every step, against every project shape > drizzle > }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -1436,7 +1408,7 @@ exports[`neon init --agent: every step, against every project shape > drizzle > "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ { "id": "run_migrations", @@ -1445,7 +1417,7 @@ exports[`neon init --agent: every step, against every project shape > drizzle > }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -1719,7 +1691,7 @@ exports[`neon init --agent: every step, against every project shape > drizzle > "label": "No, skip for now" } ], - "context": "Full documentation: https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "context": "Full documentation: https://neon.com/docs/auth/overview.md", "responseMapping": { "yes": { "command": "neon init --agent --data '{\\"step\\":\\"neon-auth\\",\\"agent\\":\\"cursor\\",\\"setup\\":true}'" @@ -1746,7 +1718,7 @@ exports[`neon init --agent: every step, against every project shape > drizzle > "status": "in_progress", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "prerequisite": "https://neon.com/docs/auth/overview.md", "steps": [ { "id": "provision", @@ -1974,8 +1946,8 @@ exports[`neon init --agent: every step, against every project shape > drizzle > --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -2013,8 +1985,8 @@ exports[`neon init --agent: every step, against every project shape > drizzle > --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -2043,15 +2015,15 @@ exports[`neon init --agent: every step, against every project shape > drizzle > } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -2112,15 +2084,15 @@ exports[`neon init --agent: every step, against every project shape > drizzle > } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -2348,7 +2320,7 @@ exports[`neon init --agent: every step, against every project shape > fully-conf }, "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", + "prerequisite": "https://neon.com/docs/connect/choose-connection.md", "steps": [ { "id": "get_connection_string", @@ -2401,32 +2373,18 @@ exports[`neon init --agent: every step, against every project shape > fully-conf "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -2439,7 +2397,7 @@ exports[`neon init --agent: every step, against every project shape > fully-conf }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -2462,7 +2420,7 @@ exports[`neon init --agent: every step, against every project shape > fully-conf "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ { "id": "run_migrations", @@ -2471,7 +2429,7 @@ exports[`neon init --agent: every step, against every project shape > fully-conf }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -2735,7 +2693,7 @@ exports[`neon init --agent: every step, against every project shape > fully-conf "label": "No, skip for now" } ], - "context": "Full documentation: https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "context": "Full documentation: https://neon.com/docs/auth/overview.md", "responseMapping": { "yes": { "command": "neon init --agent --data '{\\"step\\":\\"neon-auth\\",\\"agent\\":\\"cursor\\",\\"setup\\":true}'" @@ -2760,7 +2718,7 @@ exports[`neon init --agent: every step, against every project shape > fully-conf "status": "in_progress", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "prerequisite": "https://neon.com/docs/auth/overview.md", "steps": [ { "id": "provision", @@ -2986,8 +2944,8 @@ exports[`neon init --agent: every step, against every project shape > fully-conf --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version" `; @@ -3023,8 +2981,8 @@ exports[`neon init --agent: every step, against every project shape > fully-conf --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version" `; @@ -3051,15 +3009,15 @@ exports[`neon init --agent: every step, against every project shape > fully-conf } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -3120,15 +3078,15 @@ exports[`neon init --agent: every step, against every project shape > fully-conf } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -3345,7 +3303,7 @@ exports[`neon init --agent: every step, against every project shape > greenfield }, "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", + "prerequisite": "https://neon.com/docs/connect/choose-connection.md", "steps": [ { "id": "get_connection_string", @@ -3398,32 +3356,18 @@ exports[`neon init --agent: every step, against every project shape > greenfield "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -3436,7 +3380,7 @@ exports[`neon init --agent: every step, against every project shape > greenfield }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -3461,7 +3405,7 @@ exports[`neon init --agent: every step, against every project shape > greenfield "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ { "id": "run_migrations", @@ -3470,7 +3414,7 @@ exports[`neon init --agent: every step, against every project shape > greenfield }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -3744,7 +3688,7 @@ exports[`neon init --agent: every step, against every project shape > greenfield "label": "No, skip for now" } ], - "context": "Full documentation: https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "context": "Full documentation: https://neon.com/docs/auth/overview.md", "responseMapping": { "yes": { "command": "neon init --agent --data '{\\"step\\":\\"neon-auth\\",\\"agent\\":\\"cursor\\",\\"setup\\":true}'" @@ -3771,7 +3715,7 @@ exports[`neon init --agent: every step, against every project shape > greenfield "status": "in_progress", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "prerequisite": "https://neon.com/docs/auth/overview.md", "steps": [ { "id": "provision", @@ -3999,8 +3943,8 @@ exports[`neon init --agent: every step, against every project shape > greenfield --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -4038,8 +3982,8 @@ exports[`neon init --agent: every step, against every project shape > greenfield --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -4068,15 +4012,15 @@ exports[`neon init --agent: every step, against every project shape > greenfield } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -4137,15 +4081,15 @@ exports[`neon init --agent: every step, against every project shape > greenfield } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -4378,7 +4322,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism }, "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", + "prerequisite": "https://neon.com/docs/connect/choose-connection.md", "steps": [ { "id": "get_connection_string", @@ -4431,32 +4375,18 @@ exports[`neon init --agent: every step, against every project shape > next-prism "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -4469,7 +4399,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -4494,7 +4424,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ { "id": "run_migrations", @@ -4503,7 +4433,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -4777,7 +4707,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism "label": "No, skip for now" } ], - "context": "Full documentation: https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "context": "Full documentation: https://neon.com/docs/auth/overview.md", "responseMapping": { "yes": { "command": "neon init --agent --data '{\\"step\\":\\"neon-auth\\",\\"agent\\":\\"cursor\\",\\"setup\\":true}'" @@ -4804,7 +4734,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism "status": "in_progress", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "prerequisite": "https://neon.com/docs/auth/overview.md", "steps": [ { "id": "provision", @@ -5032,8 +4962,8 @@ exports[`neon init --agent: every step, against every project shape > next-prism --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -5071,8 +5001,8 @@ exports[`neon init --agent: every step, against every project shape > next-prism --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -5101,15 +5031,15 @@ exports[`neon init --agent: every step, against every project shape > next-prism } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -5170,15 +5100,15 @@ exports[`neon init --agent: every step, against every project shape > next-prism } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -5411,7 +5341,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism }, "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", + "prerequisite": "https://neon.com/docs/connect/choose-connection.md", "steps": [ { "id": "get_connection_string", @@ -5464,32 +5394,18 @@ exports[`neon init --agent: every step, against every project shape > next-prism "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -5502,7 +5418,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -5527,7 +5443,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ { "id": "run_migrations", @@ -5536,7 +5452,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -5810,7 +5726,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism "label": "No, skip for now" } ], - "context": "Full documentation: https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "context": "Full documentation: https://neon.com/docs/auth/overview.md", "responseMapping": { "yes": { "command": "neon init --agent --data '{\\"step\\":\\"neon-auth\\",\\"agent\\":\\"cursor\\",\\"setup\\":true}'" @@ -5837,7 +5753,7 @@ exports[`neon init --agent: every step, against every project shape > next-prism "status": "in_progress", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "prerequisite": "https://neon.com/docs/auth/overview.md", "steps": [ { "id": "provision", @@ -6065,8 +5981,8 @@ exports[`neon init --agent: every step, against every project shape > next-prism --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -6104,8 +6020,8 @@ exports[`neon init --agent: every step, against every project shape > next-prism --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -6134,15 +6050,15 @@ exports[`neon init --agent: every step, against every project shape > next-prism } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -6203,15 +6119,15 @@ exports[`neon init --agent: every step, against every project shape > next-prism } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -6439,7 +6355,7 @@ exports[`neon init --agent: every step, against every project shape > node-app > }, "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", + "prerequisite": "https://neon.com/docs/connect/choose-connection.md", "steps": [ { "id": "get_connection_string", @@ -6492,32 +6408,18 @@ exports[`neon init --agent: every step, against every project shape > node-app > "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -6530,7 +6432,7 @@ exports[`neon init --agent: every step, against every project shape > node-app > }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -6555,7 +6457,7 @@ exports[`neon init --agent: every step, against every project shape > node-app > "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ { "id": "run_migrations", @@ -6564,7 +6466,7 @@ exports[`neon init --agent: every step, against every project shape > node-app > }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -6838,7 +6740,7 @@ exports[`neon init --agent: every step, against every project shape > node-app > "label": "No, skip for now" } ], - "context": "Full documentation: https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "context": "Full documentation: https://neon.com/docs/auth/overview.md", "responseMapping": { "yes": { "command": "neon init --agent --data '{\\"step\\":\\"neon-auth\\",\\"agent\\":\\"cursor\\",\\"setup\\":true}'" @@ -6865,7 +6767,7 @@ exports[`neon init --agent: every step, against every project shape > node-app > "status": "in_progress", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "prerequisite": "https://neon.com/docs/auth/overview.md", "steps": [ { "id": "provision", @@ -7093,8 +6995,8 @@ exports[`neon init --agent: every step, against every project shape > node-app > --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -7132,8 +7034,8 @@ exports[`neon init --agent: every step, against every project shape > node-app > --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -7162,15 +7064,15 @@ exports[`neon init --agent: every step, against every project shape > node-app > } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -7231,15 +7133,15 @@ exports[`neon init --agent: every step, against every project shape > node-app > } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -7472,7 +7374,7 @@ exports[`neon init --agent: every step, against every project shape > other-data }, "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", + "prerequisite": "https://neon.com/docs/connect/choose-connection.md", "steps": [ { "id": "get_connection_string", @@ -7525,32 +7427,18 @@ exports[`neon init --agent: every step, against every project shape > other-data "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -7563,7 +7451,7 @@ exports[`neon init --agent: every step, against every project shape > other-data }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -7588,7 +7476,7 @@ exports[`neon init --agent: every step, against every project shape > other-data "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ { "id": "run_migrations", @@ -7597,7 +7485,7 @@ exports[`neon init --agent: every step, against every project shape > other-data }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -7871,7 +7759,7 @@ exports[`neon init --agent: every step, against every project shape > other-data "label": "No, skip for now" } ], - "context": "Full documentation: https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "context": "Full documentation: https://neon.com/docs/auth/overview.md", "responseMapping": { "yes": { "command": "neon init --agent --data '{\\"step\\":\\"neon-auth\\",\\"agent\\":\\"cursor\\",\\"setup\\":true}'" @@ -7898,7 +7786,7 @@ exports[`neon init --agent: every step, against every project shape > other-data "status": "in_progress", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", + "prerequisite": "https://neon.com/docs/auth/overview.md", "steps": [ { "id": "provision", @@ -8126,8 +8014,8 @@ exports[`neon init --agent: every step, against every project shape > other-data --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -8165,8 +8053,8 @@ exports[`neon init --agent: every step, against every project shape > other-data --- stderr --- --- subprocesses --- -/neonctl --version -/npm view neonctl version +/neon --version +/npm view neon version /npx -y add-mcp https://mcp.neon.tech/mcp -g -n Neon -y -a cursor /skills --version /skills add neondatabase/agent-skills --skill neon --agent cursor -y @@ -8195,15 +8083,15 @@ exports[`neon init --agent: every step, against every project shape > other-data } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -8264,15 +8152,15 @@ exports[`neon init --agent: every step, against every project shape > other-data } } }, - "skillReferences": { - "gettingStarted": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", - "connectionMethods": "https://neon.com/docs/ai/skills/neon-postgres/references/connection-methods.md", - "neonAuth": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-auth.md", - "serverlessDriver": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-serverless.md", - "neonCli": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-cli.md", - "devtools": "https://neon.com/docs/ai/skills/neon-postgres/references/devtools.md", - "branching": "https://neon.com/docs/ai/skills/neon-postgres/references/branching.md", - "neonJs": "https://neon.com/docs/ai/skills/neon-postgres/references/neon-js.md" + "docReferences": { + "gettingStarted": "https://neon.com/docs/get-started/backend-overview.md", + "connectionMethods": "https://neon.com/docs/connect/choose-connection.md", + "neonAuth": "https://neon.com/docs/auth/overview.md", + "serverlessDriver": "https://neon.com/docs/serverless/serverless-driver.md", + "neonCli": "https://neon.com/docs/cli/install.md", + "devtools": "https://neon.com/docs/reference/api.md", + "branching": "https://neon.com/docs/introduction/branching.md", + "neonJs": "https://neon.com/docs/reference/javascript-sdk.md" } } --- stderr --- @@ -8332,32 +8220,18 @@ exports[`neon init --agent: nested and string-encoded --data payloads > JSON-enc "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -8375,7 +8249,7 @@ exports[`neon init --agent: nested and string-encoded --data payloads > JSON-enc }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -8400,32 +8274,18 @@ exports[`neon init --agent: nested and string-encoded --data payloads > nested o "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -8443,7 +8303,7 @@ exports[`neon init --agent: nested and string-encoded --data payloads > nested o }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -9570,7 +9430,7 @@ exports[`neon init --agent: the orchestrator picks the next phase > fully-config --- stderr --- --- subprocesses --- -/npx -y neonctl orgs list --output json" +/npx -y neon orgs list --output json" `; exports[`neon init --agent: the orchestrator picks the next phase > fully-configured — no --data 1`] = ` @@ -9602,7 +9462,7 @@ exports[`neon init --agent: the orchestrator picks the next phase > fully-config --- stderr --- --- subprocesses --- -/npx -y neonctl orgs list --output json +/npx -y neon orgs list --output json /skills --version" `; @@ -12064,32 +11924,18 @@ exports[`neon init --agent: the response depends on which agent is driving > cla "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -12102,7 +11948,7 @@ exports[`neon init --agent: the response depends on which agent is driving > cla }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -12559,32 +12405,18 @@ exports[`neon init --agent: the response depends on which agent is driving > cod "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -12597,7 +12429,7 @@ exports[`neon init --agent: the response depends on which agent is driving > cod }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -13054,32 +12886,18 @@ exports[`neon init --agent: the response depends on which agent is driving > cur "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -13092,7 +12910,7 @@ exports[`neon init --agent: the response depends on which agent is driving > cur }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { @@ -13565,32 +13383,18 @@ exports[`neon init --agent: the response depends on which agent is driving > non "status": "getting_started", "nextAction": { "type": "agent_action", - "prerequisite": "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + "prerequisite": "https://neon.com/docs/get-started/backend-overview.md", "steps": [ - { - "id": "select_org", - "description": "List the user's Neon organizations using the CLI command below. If only one org exists, use it automatically. If multiple orgs exist, ask the user which one to use. Remember the selected org ID for the next steps.", - "command": "CI= npx -y neon orgs list --output json" - }, - { - "id": "select_or_create_project", - "description": "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID). Ask the user whether they want to use an existing project or create a new one. If creating new, ask the user for a project name (suggest the current directory name). IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - "command": "CI= npx -y neon projects list --org-id --output json" - }, - { - "id": "create_project_if_needed", - "description": "If the user chose to create a new project, create it using the CLI command below (replace and ). If the user chose an existing project, skip this step.", - "command": "CI= npx -y neon projects create --name --org-id --output json" - }, - { - "id": "create_neon_context", - "description": "Update the .neon context file in the project root with the selected org and project IDs. IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved. If no .neon file exists, create one. The file is JSON. Add/update only the orgId and projectId fields: {\\"orgId\\": \\"\\", \\"projectId\\": \\"\\", ...existing fields}. This file is safe to commit — it contains no secrets." - }, { "id": "install_dependencies", - "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. This must be done before \`neon env pull\` because the project's Neon config file may import packages that need to be installed first.", + "description": "Check if node_modules exists in the project root. If not, install the project's dependencies. Run this step's \`command\` exactly as written — it already uses this project's package manager. Do not rewrite it to npm or any other manager. Do this before linking or pulling env: \`neon env pull\` (and link's own env pull) may import the project's Neon config file, which can require these packages.", "command": "npm install" }, + { + "id": "link_project", + "description": "Select or create the Neon project for this app and link the directory to it by running the CLI command below. It returns JSON with a \`status\` field that drives a short state machine; at each step re-run the returned \`next_command_template\` with the user's choice: \`needs_org\` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen \`--org-id\`; \`needs_project\` — ask whether to use an existing project (re-run \`next_command_template\` with \`--project-id\`) or create a new one (use \`create_option.next_command_template\` with \`--project-name\`, suggesting the current directory name); \`needs_project_details\` — pick a region from the list and re-run with \`--region-id\`. Repeat until \`status\` is \`linked\`. \`neon link\` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + "command": "CI= npx -y neon link --agent" + }, { "id": "pull_env", "description": "Now that the .neon context file is in place and dependencies are installed, run \`neon env pull\` to populate the project's environment variables. This automatically writes the database connection string (and any other Neon-managed env vars) to the correct env file. It reads the .neon context file to determine the project, and writes to the appropriate env file for the project. Ensure the target env file is listed in .gitignore.", @@ -13603,7 +13407,7 @@ exports[`neon init --agent: the response depends on which agent is driving > non }, { "id": "verify_connection", - "description": "Verify the database connection works by running a SQL query against the Neon database. Write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity." + "description": "Verify the database connection works by running a SQL query against the Neon database. Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes \`SELECT 1\` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call. As a quick preliminary sanity check you may also run \`CI= npx -y neon psql -- -c \\"SELECT 1\\"\`; it confirms the project is reachable but does not substitute for the driver check above." } ], "onComplete": { diff --git a/packages/cli/src/init/agent_snapshot.test.ts b/packages/cli/src/init/agent_snapshot.test.ts index 963a1d87..3b362baa 100644 --- a/packages/cli/src/init/agent_snapshot.test.ts +++ b/packages/cli/src/init/agent_snapshot.test.ts @@ -62,8 +62,14 @@ const CLI = /** Every executable the init flow shells out to, with a fixed answer. */ const STUBS: Record = { - // `neonctl --version` and `npm view neonctl version` agreeing is what makes + // `neon --version` and `npm view neon version` agreeing is what makes // `ensureNeonctl` report `already_current` instead of trying to install. + neon: `case "$1" in + --version) echo "2.45.0" ;; + *) exit 0 ;; +esac`, + // Legacy alias, still probed as a fallback by getNeonCliVersion; versioned + // so the fallback path also resolves cleanly if it's ever taken. neonctl: `case "$1" in --version) echo "2.45.0" ;; *) exit 0 ;; @@ -71,7 +77,6 @@ esac`, npm: `if [ "$1" = "view" ]; then echo "2.45.0"; fi exit 0`, npx: "exit 0", - neon: "exit 0", skills: `if [ "$1" = "--version" ]; then echo "1.0.0"; fi exit 0`, claude: `if [ "$1" = "--version" ]; then echo "1.0.0 (Claude Code)"; fi diff --git a/packages/cli/src/init/auth.ts b/packages/cli/src/init/auth.ts index 704060bb..5c06c7b8 100644 --- a/packages/cli/src/init/auth.ts +++ b/packages/cli/src/init/auth.ts @@ -25,11 +25,11 @@ export async function ensureNeonctlAuth( if (existingToken) return true; try { - // Use execa to authenticate with neonctl - await execa("npx", ["-y", "neonctl", "me"], { + // Run `neon me`, which triggers the OAuth flow when not signed in. + await execa("npx", ["-y", "neon", "me"], { // Shows OAuth URL and prompts to the user stdio: "inherit", - // Unset CI so neonctl doesn't refuse to open the browser (e.g. when run from agent chat) + // Unset CI so the CLI doesn't refuse to open the browser (e.g. when run from agent chat) env: { ...process.env, CI: undefined }, }); return true; diff --git a/packages/cli/src/init/neonctl.ts b/packages/cli/src/init/neonctl.ts index 0ae98d52..830a0b0e 100644 --- a/packages/cli/src/init/neonctl.ts +++ b/packages/cli/src/init/neonctl.ts @@ -6,12 +6,14 @@ import { } from "../utils/package_manager.js"; /** - * Returns the Neon CLI command prefix: "CI= npx -y neon". + * Returns the Neon CLI command prefix emitted to users and agents: + * `CI= npx -y neon`. * * The CLI reads NEON_API_HOST and NEON_OAUTH_HOST from the environment - * directly, so no extra flags are needed. The `neon` package ships both the - * `neon` and `neonctl` binaries; we surface the cleaner `neon` command in the - * examples emitted to users and agents. + * directly, so no extra flags are needed. The published package is `neon` + * (its binary is `neon`; the older `neonctl` alias is no longer shipped). `npx` + * runs it with zero global-install assumptions, and the leading `CI=` keeps the + * CLI non-interactive. * * Usage: `${neonctlCmd()} orgs list --output json` */ @@ -27,29 +29,38 @@ type NeonctlStatus = { }; /** - * Gets the currently available neonctl version. - * Tries the global binary first, then falls back to npx. + * The global binaries that indicate the Neon CLI is installed. The current + * package ships `neon`; `neonctl` is the legacy alias, kept in the probe so an + * older global install still counts as "installed" (and isn't reinstalled). */ -async function getNeonctlVersion(): Promise { - // Try global binary first (fast path) - try { - const result = await execa("neonctl", ["--version"], { - stdio: "pipe", - timeout: 5000, - }); - const match = result.stdout.trim().match(/(\d+\.\d+\.\d+)/); - if (match) return match[1]; - } catch { - // Not globally installed — that's fine +const NEON_CLI_BINARIES = ["neon", "neonctl"] as const; + +/** + * Gets the currently installed Neon CLI version, probing the `neon` binary + * first and falling back to the legacy `neonctl` alias. Returns null when the + * CLI isn't on PATH. + */ +async function getNeonCliVersion(): Promise { + for (const bin of NEON_CLI_BINARIES) { + try { + const result = await execa(bin, ["--version"], { + stdio: "pipe", + timeout: 5000, + }); + const match = result.stdout.trim().match(/(\d+\.\d+\.\d+)/); + if (match) return match[1]; + } catch { + // This binary isn't installed — try the next one. + } } return null; } /** - * Checks whether the neonctl CLI is globally installed and whether it's up to date. + * Checks whether the Neon CLI is globally installed and whether it's up to date. */ export async function checkNeonctl(): Promise { - const currentVersion = await getNeonctlVersion(); + const currentVersion = await getNeonCliVersion(); if (!currentVersion) { return { @@ -63,7 +74,7 @@ export async function checkNeonctl(): Promise { // Check latest version from npm registry let latestVersion: string | null = null; try { - const result = await execa("npm", ["view", "neonctl", "version"], { + const result = await execa("npm", ["view", "neon", "version"], { stdio: "pipe", timeout: 10000, }); @@ -111,17 +122,20 @@ function isLocalDevSymlink(): boolean { try { const home = process.env.HOME || process.env.USERPROFILE || ""; const nvmDir = process.env.NVM_DIR || `${home}/.nvm`; - // Check common global module locations for a symlink - const candidates = [ - `${nvmDir}/versions/node/${process.version}/lib/node_modules/neonctl`, - `${home}/.nvm/versions/node/${process.version}/lib/node_modules/neonctl`, + // Check common global module locations for a symlink, under both the + // current `neon` package name and the legacy `neonctl` one. + const roots = [ + `${nvmDir}/versions/node/${process.version}/lib/node_modules`, + `${home}/.nvm/versions/node/${process.version}/lib/node_modules`, ]; - for (const candidate of candidates) { - try { - const stat = lstatSync(candidate); - if (stat.isSymbolicLink()) return true; - } catch { - // path doesn't exist + for (const root of roots) { + for (const pkg of NEON_CLI_BINARIES) { + try { + const stat = lstatSync(`${root}/${pkg}`); + if (stat.isSymbolicLink()) return true; + } catch { + // path doesn't exist + } } } return false; @@ -137,7 +151,7 @@ function isLocalDevSymlink(): boolean { export async function ensureNeonctl(): Promise { // Skip install for local dev symlinks to avoid permission errors if (isLocalDevSymlink()) { - const version = await getNeonctlVersion(); + const version = await getNeonCliVersion(); return { status: "already_current", version: version ?? "dev", @@ -154,7 +168,7 @@ export async function ensureNeonctl(): Promise { } const pm = resolveInvokingPackageManager(); - const install = globalInstallCommand(pm, "neonctl"); + const install = globalInstallCommand(pm, "neon"); if (!install) { // The next step is installing a package manager, not falling back to // npx: npx ships with npm, so it is missing in exactly this case. @@ -172,7 +186,7 @@ export async function ensureNeonctl(): Promise { await execa(command, args, { stdio: "pipe", timeout: 60000 }); // Verify installation - const version = await getNeonctlVersion(); + const version = await getNeonCliVersion(); return { status: check.installed ? "updated" : "installed", version: version ?? undefined, diff --git a/packages/cli/src/init/phases/db.test.ts b/packages/cli/src/init/phases/db.test.ts index d7a58683..6b2bb491 100644 --- a/packages/cli/src/init/phases/db.test.ts +++ b/packages/cli/src/init/phases/db.test.ts @@ -75,7 +75,7 @@ describe("handleDbPhase", () => { expect(result.nextAction.steps).toHaveLength(3); expect(result.nextAction.steps[0].command).toContain("proj-xyz"); expect(result.nextAction.prerequisite).toContain( - "connection-methods", + "choose-connection", ); } }); diff --git a/packages/cli/src/init/phases/db.ts b/packages/cli/src/init/phases/db.ts index 3522e69f..1f440dec 100644 --- a/packages/cli/src/init/phases/db.ts +++ b/packages/cli/src/init/phases/db.ts @@ -1,5 +1,5 @@ import { neonctlCmd } from "../neonctl.js"; -import { SKILL_REFERENCE_URLS } from "../skills.js"; +import { DOC_REFERENCE_URLS } from "../skills.js"; import type { PhaseResponse } from "../types.js"; /** @@ -65,7 +65,7 @@ export async function handleDbPhase( project: { id: options.projectId }, nextAction: { type: "agent_action", - prerequisite: SKILL_REFERENCE_URLS.connectionMethods, + prerequisite: DOC_REFERENCE_URLS.connectionMethods, steps: [ { id: "get_connection_string", diff --git a/packages/cli/src/init/phases/getting_started.test.ts b/packages/cli/src/init/phases/getting_started.test.ts index 6a8f8793..f79a151c 100644 --- a/packages/cli/src/init/phases/getting_started.test.ts +++ b/packages/cli/src/init/phases/getting_started.test.ts @@ -33,13 +33,13 @@ describe("getting-started phase", () => { if (result.nextAction.type === "agent_action") { expect(result.nextAction.prerequisite).toContain( - "getting-started.md", + "backend-overview.md", ); expect(result.nextAction.onComplete.type).toBe("run_neon_init"); } }); - test("includes org selection, project selection, and connection string steps when no connection string", async () => { + test("uses `neon link` to select/create the project when no connection string", async () => { const result = await handleGettingStartedPhase({ agent: "claude", cwd: project.dir, @@ -48,21 +48,41 @@ describe("getting-started phase", () => { if (result.nextAction.type === "agent_action") { const stepIds = result.nextAction.steps.map((s) => s.id); - expect(stepIds).toContain("select_org"); - expect(stepIds).toContain("select_or_create_project"); - expect(stepIds).toContain("create_project_if_needed"); + // The standard flow delegates org/project/.neon to `neon link` instead + // of hand-rolled select/create/edit steps. + expect(stepIds).toContain("link_project"); expect(stepIds).toContain("pull_env"); - // Org step should list orgs first - const orgStep = result.nextAction.steps.find( - (s) => s.id === "select_org", + expect(stepIds).not.toContain("select_org"); + expect(stepIds).not.toContain("create_project_if_needed"); + expect(stepIds).not.toContain("create_neon_context"); + + const linkStep = result.nextAction.steps.find( + (s) => s.id === "link_project", ); - expect(orgStep?.command).toContain("neon orgs list"); - expect(orgStep?.description).toContain("CLI"); - // Create step should include --org-id + expect(linkStep?.command).toContain("link --agent"); + expect(linkStep?.description).toContain("next_command_template"); + } + }); + + test("preview mode keeps the manual org/project selection and .neon write", async () => { + const result = await handleGettingStartedPhase({ + agent: "claude", + cwd: project.dir, + hasConnectionString: false, + preview: true, + }); + + if (result.nextAction.type === "agent_action") { + const stepIds = result.nextAction.steps.map((s) => s.id); + expect(stepIds).toContain("select_org"); + expect(stepIds).toContain("create_project_if_needed"); + expect(stepIds).toContain("create_neon_context"); + expect(stepIds).not.toContain("link_project"); + // Preview creation is pinned to the beta region. const createStep = result.nextAction.steps.find( (s) => s.id === "create_project_if_needed", ); - expect(createStep?.command).toContain("--org-id"); + expect(createStep?.command).toContain("--region-id aws-us-east-2"); } }); @@ -75,6 +95,7 @@ describe("getting-started phase", () => { if (result.nextAction.type === "agent_action") { const stepIds = result.nextAction.steps.map((s) => s.id); + expect(stepIds).not.toContain("link_project"); expect(stepIds).not.toContain("select_org"); expect(stepIds).not.toContain("select_or_create_project"); expect(stepIds).not.toContain("pull_env"); diff --git a/packages/cli/src/init/phases/getting_started.ts b/packages/cli/src/init/phases/getting_started.ts index 6cba14f4..30dbc091 100644 --- a/packages/cli/src/init/phases/getting_started.ts +++ b/packages/cli/src/init/phases/getting_started.ts @@ -6,7 +6,7 @@ import { resolvePackageManager, } from "../../utils/package_manager.js"; import { neonctlCmd } from "../neonctl.js"; -import { ensureSkillsUpToDate, SKILL_REFERENCE_URLS } from "../skills.js"; +import { DOC_REFERENCE_URLS, ensureSkillsUpToDate } from "../skills.js"; import type { PhaseResponse } from "../types.js"; export type GettingStartedPhaseOptions = { @@ -43,6 +43,19 @@ export async function handleGettingStartedPhase( const installPm = resolvePackageManager(options.cwd); if (!options.hasConnectionString) { + // Install dependencies first, before linking or pulling env. `neon env pull` + // (below, and link's own auto-pull when it creates a project) imports the + // project's neon.ts when one exists, which can require its packages installed. + steps.push({ + id: "install_dependencies", + description: [ + "Check if node_modules exists in the project root. If not, install the project's dependencies.", + DO_NOT_SUBSTITUTE_HINT, + "Do this before linking or pulling env: `neon env pull` (and link's own env pull) may import the project's Neon config file, which can require these packages.", + ].join(" "), + command: formatInstallCommand(installPm), + }); + if (options.preview) { // Public beta: platform features are only in AWS us-east-2 for now steps.push( @@ -78,63 +91,42 @@ export async function handleGettingStartedPhase( command: `${neonctlCmd()} projects create --name --org-id --region-id aws-us-east-2 --output json`, }, ); + + // Preview keeps the manual .neon write: `neon link`'s project listing + // can't express the beta eligibility filter (region + created-after) used + // above, so the org/project IDs are recorded by hand here. + steps.push({ + id: "create_neon_context", + description: [ + "Update the .neon context file in the project root with the selected org and project.", + "IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new fields into the existing content. Do NOT overwrite the file — other fields (like _init) must be preserved.", + "If no .neon file exists, create one.", + 'The file is JSON. Set orgId and projectId, and — when you just created the project — set branch to the default branch name from the `projects create` response: {"orgId": "", "projectId": "", "branch": "", ...existing fields}. For an existing project, omit branch (env pull falls back to the default branch).', + "This file is safe to commit — it contains no secrets.", + ].join(" "), + }); } else { - // Standard mode: let user choose existing or create new - steps.push( - { - id: "select_org", - description: [ - "List the user's Neon organizations using the CLI command below.", - "If only one org exists, use it automatically.", - "If multiple orgs exist, ask the user which one to use.", - "Remember the selected org ID for the next steps.", - ].join(" "), - command: `${neonctlCmd()} orgs list --output json`, - }, - { - id: "select_or_create_project", - description: [ - "List existing Neon projects in the selected organization using the CLI command below (replace with the selected org ID).", - "Ask the user whether they want to use an existing project or create a new one.", - "If creating new, ask the user for a project name (suggest the current directory name).", - "IMPORTANT: Always include --org-id when creating a project to avoid interactive prompts.", - ].join(" "), - command: `${neonctlCmd()} projects list --org-id --output json`, - }, - { - id: "create_project_if_needed", - description: [ - "If the user chose to create a new project, create it using the CLI command below (replace and ).", - "If the user chose an existing project, skip this step.", - ].join(" "), - command: `${neonctlCmd()} projects create --name --org-id --output json`, - }, - ); + // Standard: hand org/project selection-or-creation AND the .neon write to + // `neon link --agent`. Its JSON state machine walks the agent through org, + // project, and (when creating) region, and records org + project + branch in + // .neon itself — no hand-editing, and a new project's default branch is pinned + // for us. On create it also pulls env; that is safe because dependencies were + // installed above, and the explicit pull_env step below still covers the + // existing-project path (where link pins no branch and so does not pull). + steps.push({ + id: "link_project", + description: [ + "Select or create the Neon project for this app and link the directory to it by running the CLI command below.", + "It returns JSON with a `status` field that drives a short state machine; at each step re-run the returned `next_command_template` with the user's choice:", + "`needs_org` — show the listed organizations and have the user pick one (auto-select if there is only one), then re-run with the chosen `--org-id`;", + "`needs_project` — ask whether to use an existing project (re-run `next_command_template` with `--project-id`) or create a new one (use `create_option.next_command_template` with `--project-name`, suggesting the current directory name);", + "`needs_project_details` — pick a region from the list and re-run with `--region-id`.", + "Repeat until `status` is `linked`. `neon link` writes the org, project, and (for a newly created project) branch into the .neon context file — do NOT edit .neon by hand.", + ].join(" "), + command: `${neonctlCmd()} link --agent`, + }); } - // Create/update .neon context file - steps.push({ - id: "create_neon_context", - description: [ - "Update the .neon context file in the project root with the selected org and project IDs.", - "IMPORTANT: If a .neon file already exists, you MUST read it first, then merge the new orgId and projectId into the existing content. Do NOT overwrite the file — other fields (like _init, branch, etc.) must be preserved.", - "If no .neon file exists, create one.", - 'The file is JSON. Add/update only the orgId and projectId fields: {"orgId": "", "projectId": "", ...existing fields}.', - "This file is safe to commit — it contains no secrets.", - ].join(" "), - }); - - // Install project dependencies (required before env pull — config files may import packages) - steps.push({ - id: "install_dependencies", - description: [ - "Check if node_modules exists in the project root. If not, install the project's dependencies.", - DO_NOT_SUBSTITUTE_HINT, - "This must be done before `neon env pull` because the project's Neon config file may import packages that need to be installed first.", - ].join(" "), - command: formatInstallCommand(installPm), - }); - // Pull environment variables (connection string, etc.) from Neon steps.push({ id: "pull_env", @@ -254,8 +246,8 @@ export async function handleGettingStartedPhase( id: "verify_connection", description: [ "Verify the database connection works by running a SQL query against the Neon database.", - "Write and run a short script that connects using DATABASE_URL from the project's env file and executes `SELECT 1` (or queries a table from the migration if migrations were run).", - "Do NOT use the Neon CLI or MCP tools for this — use a direct database connection to verify end-to-end connectivity.", + "Primary check (definitive): write and run a short script that connects using DATABASE_URL from the project's env file and executes `SELECT 1` (or queries a table from the migration if migrations were run). Use a direct database connection — this proves the app's own driver and DATABASE_URL work end-to-end, so do NOT replace it with a CLI or MCP call.", + `As a quick preliminary sanity check you may also run \`${neonctlCmd()} psql -- -c "SELECT 1"\`; it confirms the project is reachable but does not substitute for the driver check above.`, ].join(" "), }); @@ -264,7 +256,7 @@ export async function handleGettingStartedPhase( status: "getting_started", nextAction: { type: "agent_action", - prerequisite: SKILL_REFERENCE_URLS.gettingStarted, + prerequisite: DOC_REFERENCE_URLS.gettingStarted, steps, onComplete: buildOnComplete(options), }, diff --git a/packages/cli/src/init/phases/neon_auth.ts b/packages/cli/src/init/phases/neon_auth.ts index e9104e3b..e80d9f35 100644 --- a/packages/cli/src/init/phases/neon_auth.ts +++ b/packages/cli/src/init/phases/neon_auth.ts @@ -1,5 +1,5 @@ import { neonctlCmd } from "../neonctl.js"; -import { ensureSkillsUpToDate, SKILL_REFERENCE_URLS } from "../skills.js"; +import { DOC_REFERENCE_URLS, ensureSkillsUpToDate } from "../skills.js"; import type { PhaseResponse } from "../types.js"; export type NeonAuthPhaseOptions = { @@ -36,7 +36,7 @@ export async function handleNeonAuthPhase( { value: "yes", label: "Yes, set up Neon Auth" }, { value: "no", label: "No, skip for now" }, ], - context: `Full documentation: ${SKILL_REFERENCE_URLS.neonAuth}`, + context: `Full documentation: ${DOC_REFERENCE_URLS.neonAuth}`, responseMapping: { yes: { args: [ @@ -72,7 +72,7 @@ export async function handleNeonAuthPhase( status: "in_progress", nextAction: { type: "agent_action", - prerequisite: SKILL_REFERENCE_URLS.neonAuth, + prerequisite: DOC_REFERENCE_URLS.neonAuth, steps: [ { id: "provision", diff --git a/packages/cli/src/init/phases/skills.ts b/packages/cli/src/init/phases/skills.ts index 0c521097..11f11900 100644 --- a/packages/cli/src/init/phases/skills.ts +++ b/packages/cli/src/init/phases/skills.ts @@ -1,5 +1,5 @@ import { getSkillsAgentName } from "../agents.js"; -import { SKILL_REFERENCE_URLS } from "../skills.js"; +import { DOC_REFERENCE_URLS } from "../skills.js"; import type { Editor, PhaseResponse } from "../types.js"; export type SkillsPhaseOptions = { @@ -73,7 +73,7 @@ export async function handleSkillsPhase( }, }, }, - skillReferences: SKILL_REFERENCE_URLS, + docReferences: DOC_REFERENCE_URLS, }; } diff --git a/packages/cli/src/init/resolve_context.ts b/packages/cli/src/init/resolve_context.ts index 425d14b8..43a72efd 100644 --- a/packages/cli/src/init/resolve_context.ts +++ b/packages/cli/src/init/resolve_context.ts @@ -58,7 +58,7 @@ export async function resolveNeonContext( try { const result = await execa( "npx", - ["-y", "neonctl", "orgs", "list", "--output", "json"], + ["-y", "neon", "orgs", "list", "--output", "json"], { stdio: "pipe", timeout: 30000, @@ -80,7 +80,7 @@ export async function resolveNeonContext( "npx", [ "-y", - "neonctl", + "neon", "projects", "list", "--org-id", @@ -105,7 +105,7 @@ export async function resolveNeonContext( "npx", [ "-y", - "neonctl", + "neon", "connection-string", "--project-id", project.id, diff --git a/packages/cli/src/init/skills.test.ts b/packages/cli/src/init/skills.test.ts index 74d7f7f7..18c517aa 100644 --- a/packages/cli/src/init/skills.test.ts +++ b/packages/cli/src/init/skills.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from "vitest"; -import { SKILL_REFERENCE_URLS } from "./skills.js"; +import { DOC_REFERENCE_URLS } from "./skills.js"; -describe("SKILL_REFERENCE_URLS", () => { +describe("DOC_REFERENCE_URLS", () => { test("contains gettingStarted URL", () => { - expect(SKILL_REFERENCE_URLS.gettingStarted).toBe( - "https://neon.com/docs/ai/skills/neon-postgres/references/getting-started.md", + expect(DOC_REFERENCE_URLS.gettingStarted).toBe( + "https://neon.com/docs/get-started/backend-overview.md", ); }); @@ -20,13 +20,13 @@ describe("SKILL_REFERENCE_URLS", () => { "neonJs", ]; for (const key of expectedKeys) { - expect(SKILL_REFERENCE_URLS).toHaveProperty(key); - expect(SKILL_REFERENCE_URLS[key]).toMatch(/^https:\/\/neon\.com\//); + expect(DOC_REFERENCE_URLS).toHaveProperty(key); + expect(DOC_REFERENCE_URLS[key]).toMatch(/^https:\/\/neon\.com\//); } }); test("all URLs end with .md", () => { - for (const url of Object.values(SKILL_REFERENCE_URLS)) { + for (const url of Object.values(DOC_REFERENCE_URLS)) { expect(url).toMatch(/\.md$/); } }); diff --git a/packages/cli/src/init/skills.ts b/packages/cli/src/init/skills.ts index f32cfd3b..5ea27646 100644 --- a/packages/cli/src/init/skills.ts +++ b/packages/cli/src/init/skills.ts @@ -54,18 +54,21 @@ export function getSkillList(preview?: boolean): string[] { return preview ? [...BASE_SKILLS, ...PREVIEW_SKILLS] : BASE_SKILLS; } -const SKILL_BASE_URL = - "https://neon.com/docs/ai/skills/neon-postgres/references"; - -export const SKILL_REFERENCE_URLS: Record = { - gettingStarted: `${SKILL_BASE_URL}/getting-started.md`, - connectionMethods: `${SKILL_BASE_URL}/connection-methods.md`, - neonAuth: `${SKILL_BASE_URL}/neon-auth.md`, - serverlessDriver: `${SKILL_BASE_URL}/neon-serverless.md`, - neonCli: `${SKILL_BASE_URL}/neon-cli.md`, - devtools: `${SKILL_BASE_URL}/devtools.md`, - branching: `${SKILL_BASE_URL}/branching.md`, - neonJs: `${SKILL_BASE_URL}/neon-js.md`, +// Canonical docs URLs surfaced to agents as `prerequisite`/`context` hints. The +// old `/docs/ai/skills/neon-postgres/references/*.md` skill files were retired +// and now redirect here, so we point at the canonical pages directly rather than +// rely on the redirect hop. +const DOCS_BASE_URL = "https://neon.com/docs"; + +export const DOC_REFERENCE_URLS: Record = { + gettingStarted: `${DOCS_BASE_URL}/get-started/backend-overview.md`, + connectionMethods: `${DOCS_BASE_URL}/connect/choose-connection.md`, + neonAuth: `${DOCS_BASE_URL}/auth/overview.md`, + serverlessDriver: `${DOCS_BASE_URL}/serverless/serverless-driver.md`, + neonCli: `${DOCS_BASE_URL}/cli/install.md`, + devtools: `${DOCS_BASE_URL}/reference/api.md`, + branching: `${DOCS_BASE_URL}/introduction/branching.md`, + neonJs: `${DOCS_BASE_URL}/reference/javascript-sdk.md`, }; /**