Skip to content

Fold the claimable path into the neon skill and gate it behind an account check - #69

Merged
andrelandgraf merged 49 commits into
mainfrom
update-claimable-postgres-api
Aug 25, 2026
Merged

Fold the claimable path into the neon skill and gate it behind an account check#69
andrelandgraf merged 49 commits into
mainfrom
update-claimable-postgres-api

Conversation

@andrelandgraf

@andrelandgraf andrelandgraf commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

Problem

The neon skill opens Getting Started with npx neon@latest init --agent. That command needs a Neon account. An agent working for someone who has never signed in runs it anyway and stalls at Awaiting authentication in web browser.

The repo had a no-account skill, claimable-postgres, but it documented a different service. Its API is POST https://neon.new/api/v1/database, which hands back a connection_string and a claim_url. Claimable Neon is the protocol published at claimable.neon.tech/auth.md: the agent exchanges an identity assertion for a temporary Neon project and can request Neon Auth and the Data API next to Postgres. A human claims that project into their org later.

Nothing routed an agent from the neon skill to either one and nothing told an agent when to stop and ask for a sign-in instead of provisioning something throwaway.

Diagnosis

neon claim is not in the published CLI. Gating on whether the command runs does not work, because neon claim --help on neon@4.4.0 prints the top-level help, lists no claim command and exits 0:

$ npx neon@latest claim --help
neon <command> [options]

Commands:
neon auth
└────────────────>    Authenticate [aliases: login]
neon profile
└────────────────>    Manage named sets of Neon credentials [aliases: profiles]
...
$ echo $?
0

An agent that reads exit 0 as "the command exists" goes on to run neon claim create. On neon@4.4.0 that call prints nothing and does not return. One run was killed still running at 60 seconds, a second run with stdin closed at 25 seconds, and neither had produced a byte of output.

So the gate reads the help text: if neon claim --help does not list create, take the REST fallback. That test survives the release. Once claim ships, the same call prints the claim help with create in it and the CLI path turns on with no change to the skill.

What an agent now follows

The account check, once, in Getting Started

Before `npx neon@latest init --agent`, check whether the CLI is already authenticated:

- `NEON_API_KEY` is set
- `npx neon@latest profile list -o json` lists a profile whose `account` is not `-`

A DEFAULT row with account: "-" and file: "missing" is not an account. Neither is a machine where neon is not installed or profile list cannot run. If none of the signals hold, the skill sends the agent to "Starting without a Neon account".

NEON_PROFILE is not a signal. It names a profile that may not exist.

Starting without a Neon account

Three behaviors, in order:

  1. Credentials found by the check get used.
  2. A browser wait or an auth failure means stop and ask the user to run neon auth or mint an API key. Prefer that over Claimable Neon.
  3. If they cannot do either right now, ask before using Claimable Neon and continue only on a yes.

Requests for neon.new, Claimable Postgres, claimable.neon.tech, instant Postgres or a no-signup database land in the same place. neon init --agent and neon auth are off this path entirely; both need a human account.

The reference path

skills/neon/references/claimable-neon.md:

  1. Install the CLI: npm i -g neon@latest
  2. If neon claim --help does not list create, skip to the REST fallback below
  3. Write a neon.ts declaring the services you need, or pass --service on create. Postgres is always requested.
  4. Create the project: neon claim create --env-pull (add --service data-api --service auth without a neon.ts)
  5. If create did not write env, pull it: neon env pull
  6. Use the neon-postgres skill for connections, schemas and queries. Install it if it is missing: neon skills -s neon-postgres

neon claim create reads neon.ts when it is present, writes to an existing .env otherwise .env.local and gitignores that file. --api-key and --profile are refused. Before the claim, Postgres is granted and Auth and the Data API are granted when requested. Functions, Object Storage and the AI Gateway come back refused. The agent reports what it was given rather than retrying or stripping the refusals.

CLI and HTTP name the same things differently

The reference states both sides, because an agent on the REST fallback reads auth.md and an agent on the CLI reads printed output.

Concept CLI prints HTTP returns
Claim URL verification_url verification_uri_complete
Device code user_code user_code
Code lifetime expires_in_seconds expires_in
Refused services denied_capabilities granted: false, reason: "requires_claim"

Opening the claim URL and continuing to Neon are separate

Opening the URL changes nothing. Continuing to Neon starts the transfer: DATABASE_URL rotates and existing access tokens are revoked. Auth and the Data API stay enabled when they were granted.

That distinction decides what the agent does next. On the CLI, neon claim status polls. On REST, the post-redemption token is the one that polls GET /v1/projects/{id}/claim, not the token from create. Once reconciled is true, the human signs in with neon auth and the agent runs neon link --agent and neon env pull for the new DATABASE_URL.

Of the REST errors, only invalid_grant, project_expired and project_claimed mean the stored identity assertion is dead. token_expired means re-exchange it.

REST fallback

Under the heading If neon claim is missing, so the step-2 gate has somewhere to jump to. The claimable resource is /v1/projects/{id} on https://claimable.neon.tech:

POST   https://claimable.neon.tech/v1/agent/identity
POST   https://claimable.neon.tech/v1/oauth2/token
GET    https://claimable.neon.tech/v1/projects/{id}/credentials
POST   https://claimable.neon.tech/v1/projects/{id}/claim
GET    https://claimable.neon.tech/v1/projects/{id}/claim
DELETE https://claimable.neon.tech/v1/projects/{id}
CLI REST
neon claim create POST /v1/agent/identity, then POST /v1/oauth2/token, then GET /v1/projects/{id}/credentials
neon claim accept --no-open POST /v1/projects/{id}/claim
neon claim status GET /v1/projects/{id}/claim
neon claim delete --yes DELETE /v1/projects/{id}

Request and response fields are not copied into the skill. The reference tells the agent to fetch https://claimable.neon.tech/auth.md for them, so a protocol change does not need a skill edit.

Also in here

  • skills/claimable-postgres/SKILL.md is deleted, with its README section and its skills.sh.json catalog row. The "Database Workflows" group description drops "Provision".
  • The neon README entry gains one sentence naming Claimable Neon and the skills table inside skills/neon/SKILL.md loses the claimable-postgres row.
  • The frontmatter description of the neon skill picks up the no-account triggers, including the old skill's ones: neon.new, npx neon-new, temporary postgres, no credit card database.
  • plugins/neon-postgres/ is the vendored copy, regenerated by npm run sync:plugins. It carries the same three changes: the edited neon skill, the new reference, the deleted skill.
  • The neon.ts example under "Neon Infrastructure as Code" now writes functions: {} and buckets: {}. The two // see the ... skill pointers on those lines are gone; aiGateway keeps its pointer.
  • Prettier reformatting where these edits landed: the skills table is column-padded, the skills.sh.json arrays collapse to one line and the neon.logs.fieldValues(...) call in the observability example wraps across four lines.

Verification

npm run validate:ci at 8a4200b: plugin copies in sync, versions in sync at 1.1.2, 7 skills valid, reference graph fully linked. The graph check reaches the new file through the absolute https://neon.com/docs/ai/skills/neon/references/claimable-neon.md link, which it resolves back to the on-disk path.

Against the published CLI:

  • npx neon@latest claim --help on neon@4.4.0: top-level help, zero occurrences of claim, exit 0. The step-2 gate sends an agent to REST today, which is the intended result.
  • npx neon@latest profile list -o json returns the documented shape, with account carrying an email on a signed-in profile.
  • npx neon@latest claim create on neon@4.4.0: no output, killed still running at 60 seconds, and again at 25 seconds on a second run with stdin closed.
  • curl -s -o /dev/null -w "%{http_code}" https://claimable.neon.tech/auth.md returns 200.

Not verified: no project was provisioned from this branch. The identity-assertion exchange, neon claim create --env-pull, the accept and poll loop, the revocation on continue and the post-reconciled neon link --agent plus neon env pull are written from auth.md and the CLI's own output, not from a run. The REST field names and error codes come from auth.md.

The evals/ suite covers neon-postgres-egress-optimizer only, so nothing here exercises the routing automatically.

For your attention

  • neon claim is not released, so every agent on this path lands in the REST fallback today. The help gate is what routes them there and it is also what turns the CLI path on later without another PR. Nothing in the repo pins a CLI version.
  • Step 6 installs neon-postgres with neon skills -s neon-postgres and that is not behind the gate. On neon@4.4.0, neon skills has only an update subcommand: the call prints help and exits 1 without installing anything. The agent can still fetch the skill over HTTP, but the command as written does nothing on the published CLI.
  • The reference link is absolute and 404s until the docs mirror picks up main. https://neon.com/docs/ai/skills/neon/references/claimable-neon.md is not live yet. An installed skill reads the file from disk, so this only affects an agent fetching the skill over HTTP.
  • Deleting claimable-postgres does not reach anyone who already installed it. Their copy still provisions through neon.new and https://neon.com/docs/ai/skills/claimable-postgres/SKILL.md keeps serving it until the mirror updates.
  • Downstream marketplaces still carry the deleted skill. OpenAI, Grok and JetBrains vendor their own copies per CONTRIBUTING.md and none of them update from here. Each needs its own mirror PR.
  • Claimable Neon sits last in the routing. The skill prefers neon auth or an API key whenever either is possible and asks the user before provisioning an unclaimed project. That ordering is a product call and this is the file to change it in if agent-first products should get the claimable path first.

@andrelandgraf
andrelandgraf force-pushed the update-claimable-postgres-api branch from 31164de to a013922 Compare August 13, 2026 14:22
@andrelandgraf andrelandgraf changed the title Document the claimable.neon.tech auth.md API in claimable-postgres Fold Claimable Neon into the neon skill Aug 13, 2026
@andrelandgraf
andrelandgraf force-pushed the update-claimable-postgres-api branch from 95eb004 to 1a26b00 Compare August 16, 2026 16:01
@andrelandgraf andrelandgraf changed the title Fold Claimable Neon into the neon skill Teach the neon skill the Claimable Neon path Aug 16, 2026
@andrelandgraf
andrelandgraf force-pushed the update-claimable-postgres-api branch from 567f617 to 6f9f267 Compare August 25, 2026 03:38
The skill documented the neon.new REST API, CLI, SDK, and Vite plugin. That
surface is replaced by a new service at https://claimable.neon.tech/v1 that
implements the auth.md agent identity protocol and provisions the Data API and
Neon Auth alongside Postgres.

Replaces the provisioning documentation with agent registration, the JWT bearer
token exchange, the capability decision model, the resource routes, and the
structured error envelope. Skill name and directory are unchanged.
A standalone claimable-postgres skill taught curl to a provisioning API.
Agents should start from the neon skill, install the CLI, write neon.ts,
and follow auth.md. Delete the skill and document that path in
skills/neon/references/claimable-neon.md.
The Claimable Neon reference is the new API only. neon.new remains a
trigger phrase on the neon skill so old-name queries still land here.
@andrelandgraf
andrelandgraf force-pushed the update-claimable-postgres-api branch from 6f9f267 to be13bc3 Compare August 25, 2026 15:09
@andrelandgraf andrelandgraf changed the title Teach the neon skill the Claimable Neon path Move Claimable Neon into the neon skill and drop claimable-postgres Aug 25, 2026

@thisistonydang thisistonydang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a comment about possible repetition that may make skill longer than needed, but flow lgtm overall.

Comment thread skills/neon/references/claimable-neon.md Outdated
@andrelandgraf andrelandgraf changed the title Move Claimable Neon into the neon skill and drop claimable-postgres Fold the claimable path into the neon skill and gate it behind an account check Aug 25, 2026
@andrelandgraf
andrelandgraf merged commit c623f99 into main Aug 25, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants