neon 8.0.11 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,10 +63,10 @@ leaves `neon` running the other install, such as npm. While duplicates remain, t
63
63
  Run the following command to authenticate a connection to Neon:
64
64
 
65
65
  ```bash
66
- neon auth
66
+ neon login
67
67
  ```
68
68
 
69
- The `auth` command launches a browser window where you can authorize the Neon CLI to access your Neon account. Running a Neon CLI command without authenticating with [neon auth](https://neon.com/docs/cli/auth) automatically launches the browser authentication process.
69
+ `neon auth` is an alias of `neon login`. The `login` command launches a browser window where you can authorize the Neon CLI to access your Neon account. Running a Neon CLI command without authenticating with [neon login](https://neon.com/docs/cli/auth) automatically launches the browser authentication process, except for `neon me`, which reports that you are not signed in.
70
70
 
71
71
  Alternatively, you can authenticate a connection with a Neon API key using the `--api-key` option when running a Neon CLI command. For example, an API key is used with the following `neon projects list` command:
72
72
 
@@ -76,7 +76,7 @@ neon projects list --api-key <neon_api_key>
76
76
 
77
77
  For information about obtaining an Neon API key, see [Authentication](https://neon.com/docs/reference/api/get-started), in the _Neon API Reference_.
78
78
 
79
- To check which account and credential a command uses, run `neon me` with the same `--profile` or `--api-key` option and environment as that command. The `Authentication` row names the source, such as `OAuth (profile DEFAULT)`, `API key (profile work)`, `API key (--api-key)`, or `API key (NEON_API_KEY)`.
79
+ To check which account and credential a command uses, run `neon me` with the same `--profile` or `--api-key` option and environment as that command. The `Authentication` row names the source, such as `OAuth (profile DEFAULT)`, `API key (profile work)`, `API key (--api-key)`, or `API key (NEON_API_KEY)`. When no credential is usable, `neon me` exits 1 with `Not signed in` and the `neon login` command to run; it never starts a sign-in itself.
80
80
 
81
81
  ## Create a project without an account
82
82
 
@@ -658,13 +658,15 @@ neon config init --services data-api
658
658
  # Repeat the flag instead, and shorten it — every services flag takes all three spellings
659
659
  neon config init -s auth -s functions
660
660
 
661
- # Explicitly ask for the bare starter policy
662
- neon config init --services none
661
+ # Postgres only: the starter policy, with no prompt
662
+ neon config init --services postgres
663
663
 
664
664
  # Scaffold but print the install command instead of running it
665
665
  neon config init --no-install
666
666
  ```
667
667
 
668
+ `postgres` declares nothing, since every branch has Postgres, so it can stand alone or sit next to other services. `neon init --services` takes the same values.
669
+
668
670
  Object storage is spelled `object-storage` here, matching [`env pull --service`](#env-pull) and the rest of the CLI. The old `storage` still works and warns; it will be removed.
669
671
 
670
672
  Choosing **Functions** also writes the handler the policy points at, since `source` is only resolved when `apply` bundles it — a declared function with no file on disk fails at deploy:
@@ -740,9 +742,8 @@ The branch is chosen with `--branch <id|name>`; without it the project's default
740
742
 
741
743
  **Apply-only flags** (also available on `deploy`):
742
744
 
743
- - `--update-existing` — auto-confirm overriding existing remote settings on the branch. Without it, drift on settings already present remotely (compute, TTL, `protected`) is reported as a **conflict** and `apply` makes no changes until you resolve it or pass this flag.
745
+ - `--update-existing` (`-y`, `--yes`) — auto-confirm overriding existing remote settings on the branch. Without it, drift on settings already present remotely (compute, TTL, `protected`) is reported as a **conflict** and `apply` makes no changes until you resolve it or pass this flag.
744
746
  - `--allow-protected` — auto-confirm applying to a branch Neon marks as protected. Without it, `apply` refuses to touch a protected branch.
745
-
746
747
  **Output**: `status` prints the project, branch, and reverse-engineered config. `plan` / `apply` render a **`git diff`-style report** (matching [`neon diff`](#diff)): service changes (Neon Auth, Data API, buckets, functions) list as green `+` additions, while **branch setting changes** (TTL, `protected`, compute) show grouped under a `~ <branch>` header, one sorted `field → value` line each. A bare `apply` that hits drift on settings already present remotely prints those as a sorted **before→after** diff (`current → desired`, old in red / new in green) and exits non-zero until you pass `--update-existing`. Pass `--output json` (or `--output yaml`) to emit the full machine-readable result (`PushResult`) instead, for piping into other tools or CI.
747
748
 
748
749
  **`config status --current-branch`** (alias `neon status --current-branch`) prints _only_ the branch pinned in the local `.neon` file — no network, no auth, no analytics — and exits non-zero when none is pinned. This behavior lets it safely drive a shell prompt. Example [starship](https://starship.rs) segment:
@@ -831,7 +832,7 @@ The target directory must be empty unless you pass `--force` (a lone `.git` is i
831
832
 
832
833
  Recommended installs the Neon plugin for every detected agent (global config, project folders, and the host CLI). Plugin-capable agents get the plugin; the rest get skills and MCP. If none are detected, it installs the default Neon skills for Cursor and Codex in this directory (`./.agents/skills`) and does not configure MCP. It then links a project when the CLI is authenticated, and writes a default `neon.ts` (Postgres only) using the package manager already in the directory.
833
834
 
834
- Unauthenticated `-y` skips linking and prints the next step: sign up at https://neon.com/signup, then `neon auth`, `neon link`, or `neon claim create` (no account, expires in 72 hours unless claimed). `-y` never opens a browser. `-y` with `--project-id` or other account flags links when the CLI is already signed in; otherwise it errors and names `neon auth` or `--claimable`.
835
+ Unauthenticated `-y` skips linking and prints the next step: sign up at https://neon.com/signup, then `neon login`, `neon link`, or `neon claim create` (no account, expires in 72 hours unless claimed). `-y` never opens a browser. `-y` with `--project-id` or other account flags links when the CLI is already signed in; otherwise it errors and names `neon login` or `--claimable`.
835
836
 
836
837
  Custom asks how to add Neon to coding agents (plugin, skills and MCP separately, or skip), then how to get a project (sign in and link, or a claimable project when you are not signed in), then which services `neon.ts` should declare. Skills and MCP use separate agent pickers, and either can be skipped. Postgres is listed first as always included. The package manager is inferred from the directory; Custom asks only when none is detected. `--skill` selects skills (not the plugin) and skips that picker. MCP flags (`--mcp-config-location`, `--mcp-auth`, `--mcp-project-scoped`) select skills and MCP. `--mcp-config-location` is where the config is written: `global` maps to `neon mcp`, and `project` maps to `neon mcp --project`. With `-y`, the location defaults to `global`; interactive Custom asks. If some selected agents cannot write that location, init warns and skips MCP for those agents while continuing with the supported agents. It fails when none of the selected agents support the location. `--mcp-project-scoped` limits MCP tools to the linked Neon project by passing its ID to `neon mcp --project-id`. Omitted is false, including in Custom; there is no prompt. `--no-agent-setup` skips agent setup.
837
838
 
@@ -1198,18 +1199,18 @@ Credential Manager, Linux Secret Service) only when its `profiles.json` pointer
1198
1199
  That is per profile. Reads never migrate.
1199
1200
 
1200
1201
  ```bash
1201
- neon auth --keyring # sign DEFAULT into the OS keyring
1202
- neon auth --keyring --profile work # sign work into the OS keyring
1202
+ neon login --keyring # sign DEFAULT into the OS keyring
1203
+ neon login --keyring --profile work # sign work into the OS keyring
1203
1204
  neon profile create work --keyring # create a named profile in the keyring
1204
1205
  neon profile remove work --yes # drop a keyring profile, then create it again as a file
1205
1206
  ```
1206
1207
 
1207
- File to keyring is `neon auth --keyring` or `neon profile create … --keyring`: a new
1208
+ File to keyring is `neon login --keyring` or `neon profile create … --keyring`: a new
1208
1209
  sign-in, then the previous credential is revoked and the owned file is deleted.
1209
- `create` on an existing name always revokes after a successful write. `auth` revokes
1210
+ `create` on an existing name always revokes after a successful write. `login` revokes
1210
1211
  when it writes to the keyring, including a re-login that follows an existing pointer.
1211
- `auth` that overwrites a file does not. Keyring to file is `remove`, then create or
1212
- auth again. `create` and `auth` without `--keyring` follow an existing `"keyring"`
1212
+ `login` that overwrites a file does not. Keyring to file is `remove`, then create or
1213
+ log in again. `create` and `login` without `--keyring` follow an existing `"keyring"`
1213
1214
  pointer, so a keyring profile cannot leave the OS store until `remove` succeeds.
1214
1215
 
1215
1216
  `--api-key` and `NEON_API_KEY` skip both stores. A GitHub-release `neon-<platform>`
@@ -1218,7 +1219,7 @@ Use the npm-installed `neon`. Older releases treat the sentinel as a relative pa
1218
1219
 
1219
1220
  A `"keyring"` pointer whose OS item cannot be read is not treated as signed-out. Commands that
1220
1221
  would otherwise open a browser fail: could not read the OS keyring item. Unlock it and
1221
- retry, or run `neon auth --profile DEFAULT`. To reset the profile: `neon profile remove DEFAULT --yes`.
1222
+ retry, or run `neon login --profile DEFAULT`. To reset the profile: `neon profile remove DEFAULT --yes`.
1222
1223
  A missing `credentials.json` with no `profiles.json` is still
1223
1224
  signed-out, and those commands start OAuth.
1224
1225
 
@@ -1258,7 +1259,7 @@ the key never leaves the CLI.
1258
1259
  **A profile is one kind or the other, never both.** `type` in the credentials file states which:
1259
1260
 
1260
1261
  ```json
1261
- // oauth: what a plain `create` (or `neon auth --profile`) writes. An absent `type` means this.
1262
+ // oauth: what a plain `create` (or `neon login --profile`) writes. An absent `type` means this.
1262
1263
  { "access_token": "…", "refresh_token": "…", "expires_at": 1786…, "user_id": "…" }
1263
1264
 
1264
1265
  // api_key: what `--api-key` writes
@@ -1299,7 +1300,7 @@ Passing both flags fails rather than picking a winner: `--api-key` supplies a cr
1299
1300
 
1300
1301
  When both are only environment variables the key wins, which keeps a CI pipeline that injects `NEON_API_KEY` working even if a `NEON_PROFILE` leaks into the environment — but the disregarded profile is named on stderr rather than passed over silently.
1301
1302
 
1302
- `neon auth` and the `profile` subcommands are outside all of this, because they read the same flags to mean something else: `neon auth --profile work` names where to write a credential, and `neon profile create work --api-key …` names one to store.
1303
+ `neon login` and the `profile` subcommands are outside all of this, because they read the same flags to mean something else: `neon login --profile work` names where to write a credential, and `neon profile create work --api-key …` names one to store.
1303
1304
 
1304
1305
  `neon init` forwards `--profile` and `--config-dir` to agent and config children and uses them directly for its link flow. An explicit `--api-key` is passed to authenticated children through `NEON_API_KEY`, not argv.
1305
1306
 
@@ -1387,7 +1388,7 @@ Id Name Project Created At Last Used At Last
1387
1388
 
1388
1389
  | Command | Subcommands | Description |
1389
1390
  | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ---------------------------------- |
1390
- | [auth](https://neon.com/docs/reference/cli-auth) | | Authenticate |
1391
+ | [login](https://neon.com/docs/reference/cli-auth) (`auth`) | | Authenticate |
1391
1392
  | claim (`claimable`) | `create`, `status`, `accept`, `list`, `delete` | Manage claimable projects |
1392
1393
  | profile | `list`, `create`, `rotate-key`, `remove` | Manage named sets of credentials |
1393
1394
  | api-keys | `list`, `create`, `revoke` | Manage API keys |
@@ -1449,7 +1450,7 @@ Global options are supported with any Neon CLI command.
1449
1450
 
1450
1451
  - <a id="config-dir"></a>`--config-dir`
1451
1452
 
1452
- Specifies the path to the `neon` configuration directory, which holds the `credentials.json` written by `neon auth` and, when a second profile exists or DEFAULT is keyring, `profiles.json`. The default is `$XDG_CONFIG_HOME/neon`, or `~/.config/neon`; run `neon --help` to see the resolved path. This option is only necessary if you keep your configuration somewhere else.
1453
+ Specifies the path to the `neon` configuration directory, which holds the `credentials.json` written by `neon login` and, when a second profile exists or DEFAULT is keyring, `profiles.json`. The default is `$XDG_CONFIG_HOME/neon`, or `~/.config/neon`; run `neon --help` to see the resolved path. This option is only necessary if you keep your configuration somewhere else.
1453
1454
 
1454
1455
  The directory was called `neonctl` before the CLI was renamed. An existing one is still read, and is used **in place** — nothing is moved or copied, so there is never a second credentials file to go stale. A directory you pass explicitly is used exactly as given and never falls back to the legacy name, so pointing a CI run at a scratch directory cannot pick up local credentials.
1455
1456
 
@@ -1462,7 +1463,7 @@ Global options are supported with any Neon CLI command.
1462
1463
  Selects a named set of credentials, for holding more than one Neon account at a time. A profile is a pointer to a credentials file, recorded in `profiles.json` next to it.
1463
1464
 
1464
1465
  ```bash
1465
- neon auth --profile work # create it, or sign in again
1466
+ neon login --profile work # create it, or sign in again
1466
1467
  neon profile list # names, accounts, and where each one's credentials live
1467
1468
  neon projects list --profile work
1468
1469
  NEON_PROFILE=work neon projects list
@@ -1472,7 +1473,7 @@ Global options are supported with any Neon CLI command.
1472
1473
 
1473
1474
  - <a id="api-key"></a>`--api-key`
1474
1475
 
1475
- Specifies your Neon API key. You can authenticate using a Neon API key when running a Neon CLI command instead of using `neon auth`. For information about obtaining an Neon API key, see [Authentication](https://neon.com/docs/reference/api/get-started), in the _Neon API Reference_.
1476
+ Specifies your Neon API key. You can authenticate using a Neon API key when running a Neon CLI command instead of using `neon login`. For information about obtaining an Neon API key, see [Authentication](https://neon.com/docs/reference/api/get-started), in the _Neon API Reference_.
1476
1477
 
1477
1478
  ```bash
1478
1479
  neon <command> --api-key <neon_api_key>
@@ -1,4 +1,4 @@
1
- import "./profiles-CvnFEQyd.js";
1
+ import "./profiles-DIB1av2Q.js";
2
2
  //#region ../../internals/cli-core/dist/auth_selection.js
3
3
  /**
4
4
  * # Which credential an invocation authenticates with
@@ -32,8 +32,8 @@ import "./profiles-CvnFEQyd.js";
32
32
  * the environment. It warns instead of staying silent, because a disregarded account
33
33
  * selection is precisely what nobody noticed last time.
34
34
  *
35
- * `auth` and the `profile` subcommands do not use any of this. They read the same flags with
36
- * different meanings — `neon auth --profile work` names where to *write* a credential, and
35
+ * `login` and the `profile` subcommands do not use any of this. They read the same flags with
36
+ * different meanings — `neon login --profile work` names where to *write* a credential, and
37
37
  * `neon profile create work --api-key …` names one to *store* — so their callers skip
38
38
  * selection entirely rather than passing exemptions down here.
39
39
  */
@@ -1,6 +1,6 @@
1
1
  import { t as writeSecretFile } from "./secure_file-BucZj4yQ.js";
2
2
  import { a as isOwnedCredentialPath } from "./paths-DMq0Lt7a.js";
3
- import { f as profilesFilePath, v as CRED_STORAGE_FILE, y as CRED_STORAGE_KEYRING } from "./profiles-CvnFEQyd.js";
3
+ import { f as profilesFilePath, v as CRED_STORAGE_FILE, y as CRED_STORAGE_KEYRING } from "./profiles-DIB1av2Q.js";
4
4
  import { tryLoadKeyring } from "../keyring.js";
5
5
  import { existsSync, readFileSync, rmSync } from "node:fs";
6
6
  import { dirname } from "node:path";
@@ -202,7 +202,7 @@ var KeyringUnavailableError = class extends Error {
202
202
  };
203
203
  var KeyringUnreadableError = class extends Error {
204
204
  constructor(profile) {
205
- const replace = `\`neon auth --profile ${profile}\``;
205
+ const replace = `\`neon login --profile ${profile}\``;
206
206
  super(`Could not read the OS keyring item for profile "${profile}". Unlock the keyring and retry, or run ${replace}. To reset the profile: \`neon profile remove ${profile} --yes\`.`);
207
207
  this.name = "KeyringUnreadableError";
208
208
  }
@@ -82,7 +82,7 @@ const inspectProfiles = (dir) => {
82
82
  *
83
83
  * A malformed file is reported through `onWarn` and treated as absent, because for a *read* the
84
84
  * worst case is a named profile turning up missing, which is recoverable — whereas throwing
85
- * would lock the user out of `neon auth` itself. Writing is the opposite: see
85
+ * would lock the user out of `neon login` itself. Writing is the opposite: see
86
86
  * {@link upsertProfile}, which refuses rather than rebuilding a file it cannot read.
87
87
  */
88
88
  const readProfiles = (dir, onWarn = () => {}) => {
@@ -96,7 +96,7 @@ const readProfiles = (dir, onWarn = () => {}) => {
96
96
  *
97
97
  * Call this **before** anything that writes a credential, opens a browser, or spends an API
98
98
  * call. {@link upsertProfile} refuses too, but it runs last: by then `create` has already
99
- * overwritten `credentials.<name>.json` and revoked the key it replaced, and `neon auth
99
+ * overwritten `credentials.<name>.json` and revoked the key it replaced, and `neon login
100
100
  * --profile` has already signed in over it — a refusal that arrives after the destruction it
101
101
  * exists to prevent. The path resolution itself is the unsound part, since with the metadata
102
102
  * unreadable the conventional filename is a guess about which account that file belongs to.
@@ -32,8 +32,8 @@ import "./profiles.js";
32
32
  * the environment. It warns instead of staying silent, because a disregarded account
33
33
  * selection is precisely what nobody noticed last time.
34
34
  *
35
- * `auth` and the `profile` subcommands do not use any of this. They read the same flags with
36
- * different meanings — `neon auth --profile work` names where to *write* a credential, and
35
+ * `login` and the `profile` subcommands do not use any of this. They read the same flags with
36
+ * different meanings — `neon login --profile work` names where to *write* a credential, and
37
37
  * `neon profile create work --api-key …` names one to *store* — so their callers skip
38
38
  * selection entirely rather than passing exemptions down here.
39
39
  */
@@ -13,7 +13,7 @@ import { isAbsolute, relative, resolve } from "node:path";
13
13
  * ```
14
14
  * ~/.config/neon/
15
15
  * ├── credentials.json # this IS the DEFAULT profile, not a copy of it
16
- * ├── credentials.work.json # created by `neon auth --profile work`
16
+ * ├── credentials.work.json # created by `neon login --profile work`
17
17
  * └── profiles.json # created only once a second profile exists
18
18
  * ```
19
19
  *
@@ -105,7 +105,7 @@ const inspectProfiles = (dir) => {
105
105
  *
106
106
  * A malformed file is reported through `onWarn` and treated as absent, because for a *read* the
107
107
  * worst case is a named profile turning up missing, which is recoverable — whereas throwing
108
- * would lock the user out of `neon auth` itself. Writing is the opposite: see
108
+ * would lock the user out of `neon login` itself. Writing is the opposite: see
109
109
  * {@link upsertProfile}, which refuses rather than rebuilding a file it cannot read.
110
110
  */
111
111
  const readProfiles = (dir, onWarn = () => {}) => {
@@ -119,7 +119,7 @@ const readProfiles = (dir, onWarn = () => {}) => {
119
119
  *
120
120
  * Call this **before** anything that writes a credential, opens a browser, or spends an API
121
121
  * call. {@link upsertProfile} refuses too, but it runs last: by then `create` has already
122
- * overwritten `credentials.<name>.json` and revoked the key it replaced, and `neon auth
122
+ * overwritten `credentials.<name>.json` and revoked the key it replaced, and `neon login
123
123
  * --profile` has already signed in over it — a refusal that arrives after the destruction it
124
124
  * exists to prevent. The path resolution itself is the unsound part, since with the metadata
125
125
  * unreadable the conventional filename is a guess about which account that file belongs to.
package/dist/analytics.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as OAUTH, t as storeFor } from "./_chunks/credential_io-D8AR-jvB.js";
1
+ import { a as OAUTH, t as storeFor } from "./_chunks/credential_io-ByNuojoE.js";
2
2
  import { getCliAgent, getGithubEnvVars, isCi } from "./env.js";
3
3
  import { log } from "./log.js";
4
4
  import pkg_default from "./pkg.js";
@@ -31,8 +31,8 @@ const authFailureMessage = (context) => {
31
31
  if (context?.source === "profile-api-key") return `Authentication failed: the Neon API rejected profile "${profile}"'s API key${where}. Replace it with \`neon profile create ${profile} --mint\`, or store another with \`neon profile create ${profile} --api-key -\`.`;
32
32
  if (context?.source === "claimable") return `Authentication failed: Claimable Neon rejected the linked project's short-lived access token${where}. Retry the command to exchange the saved identity assertion again; if it still fails, run \`neon claim status\`.`;
33
33
  if (context?.source === "stored-credentials") {
34
- if (context.storage === "keyring") return `Authentication failed: the Neon API rejected profile "${profile}"'s stored session (OS keyring). Sign in again with \`neon auth --profile ${profile}\`.`;
35
- return `Authentication failed: the Neon API rejected profile "${profile}"'s stored session${where}. Sign in again with \`neon auth --profile ${profile}\`.`;
34
+ if (context.storage === "keyring") return `Authentication failed: the Neon API rejected profile "${profile}"'s stored session (OS keyring). Sign in again with \`neon login --profile ${profile}\`.`;
35
+ return `Authentication failed: the Neon API rejected profile "${profile}"'s stored session${where}. Sign in again with \`neon login --profile ${profile}\`.`;
36
36
  }
37
37
  return "Authentication failed: the Neon API rejected the API key. Check --api-key or NEON_API_KEY.";
38
38
  };
@@ -1,4 +1,4 @@
1
- import { t as storeFor } from "./_chunks/credential_io-D8AR-jvB.js";
1
+ import { t as storeFor } from "./_chunks/credential_io-ByNuojoE.js";
2
2
  import { log } from "./log.js";
3
3
  import { authFailureMessage, getAuthContext, locationFromContext } from "./auth_context.js";
4
4
  import { AuthRefreshError } from "./auth.js";
@@ -49,7 +49,7 @@ const recoverFrom401 = async (canRetry) => {
49
49
  } catch (err) {
50
50
  if (err instanceof AuthRefreshError) {
51
51
  log.error(err.message);
52
- if (err.terminal) log.error(`Run \`neon auth --profile ${context.profile ?? "DEFAULT"}\` to sign in again.`);
52
+ if (err.terminal) log.error(`Run \`neon login --profile ${context.profile ?? "DEFAULT"}\` to sign in again.`);
53
53
  return false;
54
54
  }
55
55
  log.debug("Refresh after 401 failed: %s", err instanceof Error ? err.message : "unknown error");
@@ -1,15 +1,15 @@
1
1
  import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
2
- import { a as OAUTH, i as API_KEY, l as interpretCredentials, s as credentialLabel, t as storeFor } from "../_chunks/credential_io-D8AR-jvB.js";
2
+ import { a as OAUTH, i as API_KEY, l as interpretCredentials, s as credentialLabel, t as storeFor } from "../_chunks/credential_io-ByNuojoE.js";
3
3
  import { isCi } from "../env.js";
4
4
  import { log } from "../log.js";
5
5
  import { getApiClient, isNeonApiError } from "../api.js";
6
6
  import { setAuthContext } from "../auth_context.js";
7
7
  import { a as isOwnedCredentialPath } from "../_chunks/paths-DMq0Lt7a.js";
8
8
  import { currentContextFile, isAskCommand, isClaimCommand, isConfigAdd, isConfigInit, isCurrentBranchProbe, isFeedbackCommand, isGitLocalCommand, isInspectDbUrl, isMcpCommand, isMcpOauth, isPluginsCommand, isProfileCommand, isSkillsCommand, isUnfollowedGitHookSync, readContextFile } from "../context.js";
9
- import { _ as upsertProfile, d as newProfileLocation, g as selectProfileName, h as resolveProfile, i as assertValidProfileName, l as locationForName, m as readProfiles, n as KEYRING_CREDENTIALS, p as profilesUsingPath, r as assertProfilesUsable, s as isKeyringPointer, t as DEFAULT_PROFILE, u as locationOf } from "../_chunks/profiles-CvnFEQyd.js";
9
+ import { _ as upsertProfile, d as newProfileLocation, g as selectProfileName, h as resolveProfile, i as assertValidProfileName, l as locationForName, m as readProfiles, n as KEYRING_CREDENTIALS, p as profilesUsingPath, r as assertProfilesUsable, s as isKeyringPointer, t as DEFAULT_PROFILE, u as locationOf } from "../_chunks/profiles-DIB1av2Q.js";
10
10
  import { extendTokenSet } from "../utils/auth.js";
11
11
  import { AuthRefreshError, auth, classifyRefreshFailure, refreshToken } from "../auth.js";
12
- import { i as selectCredential, n as displacedProfileWarning, t as credentialInputs } from "../_chunks/auth_selection-pitMFzDe.js";
12
+ import { i as selectCredential, n as displacedProfileWarning, t as credentialInputs } from "../_chunks/auth_selection-YX5_KZgD.js";
13
13
  import { ClaimableClient, ClaimableServiceError } from "../claimable/api.js";
14
14
  import { assertionHasExpired, claimableCredentialsExist, claimableCredentialsPath, readLinkedClaimableCredentials, shouldUseClaimableCredentials } from "../claimable/state.js";
15
15
  import { withExclusiveLock } from "../refresh_lock.js";
@@ -45,8 +45,8 @@ const locationForAuth = (configDir, name, keyring, options = {}) => {
45
45
  if (options.create === true) return newProfileLocation(configDir, name, "file");
46
46
  return locationForName(configDir, name);
47
47
  };
48
- const command = "auth";
49
- const aliases = ["login"];
48
+ const command = "login";
49
+ const aliases = ["auth"];
50
50
  const describe = "Sign in with a browser. See --help for API keys and profiles";
51
51
  const wrapAuthHelp = (text) => wrapHelpText(text, helpWidth());
52
52
  const authHelpEpilogue = () => {
@@ -54,9 +54,9 @@ const authHelpEpilogue = () => {
54
54
  return helpEpilogue(wrapAuthHelp("Non-interactive (CI, scripts, agents):"), wrapAuthHelp("Use an existing API key or an API-key profile."), ` ${cli} projects list --profile agent`, wrapAuthHelp(`${cli} profile create <name> --mint needs a browser during setup, then stores an API key and drops the session. It cannot run in CI. Default key is account-wide; --org-id or --project-id (not both) restricts it.`), wrapAuthHelp(`A profile holds a browser session or an API key. Select it with --profile <name> or NEON_PROFILE. List profiles with ${cli} profile list.`), wrapAuthHelp("On commands that use a credential, --api-key or --profile overrides NEON_API_KEY and NEON_PROFILE. Pass either --api-key or --profile, not both. When neither flag is passed and both NEON_API_KEY and NEON_PROFILE are set, the key wins and stderr names the ignored profile. When no flag or environment variable selects a credential, DEFAULT is used."), wrapAuthHelp(`${cli} profile create <name> replaces an existing profile of that name and tries to revoke the credential it held. An imported key with no recorded id stays live. Pick a new name to keep the old profile.`), wrapAuthHelp(`See ${cli} profile --help and ${cli} profile create --help.`));
55
55
  };
56
56
  const builder = (yargs) => yargs.option("context-file", { hidden: true }).option("keyring", {
57
- describe: "Store the credential in the OS keyring. Per profile; later auth without the flag stays there. See `neon profile list`.",
57
+ describe: "Store the credential in the OS keyring. Per profile; a later login without the flag stays there. See `neon profile list`.",
58
58
  type: "boolean"
59
- }).example("$0 auth", "Sign in with a browser").example("$0 auth --profile work", "Save a browser session in profile work").example("$0 projects list --api-key \"$KEY\"", "Use an existing API key for this command").example("NEON_API_KEY=\"$KEY\" $0 projects list", "Use an existing API key from the environment").example("$0 profile create agent --api-key \"$KEY\"", "Store an existing API key").example("echo \"$KEY\" | $0 profile create agent --api-key -", "Store a key read from stdin").example("$0 profile create ci --mint", "Sign in once in a browser and store a new API key").epilogue(authHelpEpilogue());
59
+ }).example("$0 login", "Sign in with a browser").example("$0 login --profile work", "Save a browser session in profile work").example("$0 projects list --api-key \"$KEY\"", "Use an existing API key for this command").example("NEON_API_KEY=\"$KEY\" $0 projects list", "Use an existing API key from the environment").example("$0 profile create agent --api-key \"$KEY\"", "Store an existing API key").example("echo \"$KEY\" | $0 profile create agent --api-key -", "Store a key read from stdin").example("$0 profile create ci --mint", "Sign in once in a browser and store a new API key").epilogue(authHelpEpilogue());
60
60
  const handler = async (args) => {
61
61
  await authFlow(args);
62
62
  };
@@ -160,7 +160,7 @@ const fetchIdentity = async (apiClient) => {
160
160
  ...email ? { email } : {}
161
161
  };
162
162
  } catch (err) {
163
- if (isNeonApiError(err) && err.status === 401) throw new Error("Signed in, but the Neon API rejected the new access token. Try `neon auth` again.");
163
+ if (isNeonApiError(err) && err.status === 401) throw new Error("Signed in, but the Neon API rejected the new access token. Try `neon login` again.");
164
164
  log.warning("Signed in, but could not look up the account: %s", err instanceof Error ? err.message : String(err));
165
165
  return {};
166
166
  }
@@ -317,7 +317,7 @@ const ensureAuth = async (props) => {
317
317
  const isLocalDev = props._[0] === "dev";
318
318
  const isBootstrap = props._[0] === "bootstrap";
319
319
  const isMcp = isMcpCommand(props);
320
- if (props._[0] === "auth") {
320
+ if (props._[0] === "login" || props._[0] === "auth") {
321
321
  props.apiClient = getApiClient({
322
322
  apiKey: props.apiKey,
323
323
  apiHost: props.apiHost
@@ -337,7 +337,7 @@ const ensureAuth = async (props) => {
337
337
  try {
338
338
  token = await client.exchange(stored.identityAssertion);
339
339
  } catch (error) {
340
- if (error instanceof ClaimableServiceError && error.code === "project_claimed") throw new Error("This project was claimed. Run `neon claim status` to drop the local assertion, then `neon auth` or `neon link`.");
340
+ if (error instanceof ClaimableServiceError && error.code === "project_claimed") throw new Error("This project was claimed. Run `neon claim status` to drop the local assertion, then `neon login` or `neon link`.");
341
341
  throw error;
342
342
  }
343
343
  props.apiKey = token.accessToken;
@@ -449,6 +449,12 @@ const ensureAuth = async (props) => {
449
449
  log.debug("mcp: no usable credentials; minting requires auth or --oauth");
450
450
  return;
451
451
  }
452
+ if (props._[0] === "me") {
453
+ const state = loaded === null ? "has no stored credential" : "holds a session that has expired";
454
+ process.stderr.write(`Not signed in: profile "${selection.profile}" ${state}. Run \`${getCliName()} login --profile ${selection.profile}\` to sign in, or use an API key with --api-key or NEON_API_KEY.\n`);
455
+ process.exitCode = 1;
456
+ return;
457
+ }
452
458
  const apiKey = await authFlow({
453
459
  ...props,
454
460
  profile: selection.profile
@@ -3,6 +3,7 @@ import { isCi } from "../env.js";
3
3
  import { log } from "../log.js";
4
4
  import { isNeonApiError } from "../api.js";
5
5
  import { applyContext, contextBranch, readContextFile } from "../context.js";
6
+ import { isClaimableEnvTarget } from "../claimable/state.js";
6
7
  import { getCliName } from "../utils/cli_name.js";
7
8
  import { loadEnvFileIntoProcess } from "../env_file.js";
8
9
  import { createBranch, pickBranchInteractively } from "../utils/branch_picker.js";
@@ -91,13 +92,19 @@ const handler = async (props) => {
91
92
  props.id = renamed;
92
93
  }
93
94
  }
95
+ const orgRead = isClaimableEnvTarget({
96
+ apiHost: props.apiHost,
97
+ contextFile: props.contextFile,
98
+ configDir: props.configDir ?? ""
99
+ }) ? void 0 : resolveOrgId(props, projectId);
100
+ orgRead?.catch(() => void 0);
94
101
  const { branchId, branchName, created, policyApplied, policyFailure } = await resolveBranchId(props, projectId, {
95
102
  hooks,
96
103
  git,
97
104
  event,
98
105
  cwd
99
106
  });
100
- const orgId = await resolveOrgId(props, projectId);
107
+ const orgId = await (orgRead ?? resolveOrgId(props, projectId));
101
108
  applyContext(props.contextFile, {
102
109
  projectId,
103
110
  ...orgId ? { orgId } : {},
@@ -119,6 +126,10 @@ const handler = async (props) => {
119
126
  projectId,
120
127
  branch: branchId,
121
128
  envPull: props.envPull
129
+ }, {
130
+ branchId,
131
+ branchName,
132
+ usedDefault: false
122
133
  });
123
134
  const needsCreateAfter = created && hooks?.create?.after;
124
135
  if (config && (hooks?.checkout?.after || needsCreateAfter)) {
@@ -3,7 +3,7 @@ import { isCi } from "../env.js";
3
3
  import { log } from "../log.js";
4
4
  import { getApiClient } from "../api.js";
5
5
  import { applyContext, contextBranch, readContextFile } from "../context.js";
6
- import { t as credentialInputs } from "../_chunks/auth_selection-pitMFzDe.js";
6
+ import { t as credentialInputs } from "../_chunks/auth_selection-YX5_KZgD.js";
7
7
  import { ClaimableClient, ClaimableServiceError } from "../claimable/api.js";
8
8
  import { assertionHasExpired, listClaimableCredentials, readClaimableCredentials, readLinkedClaimableCredentials, removeClaimableCredentials, writeClaimableCredentials } from "../claimable/state.js";
9
9
  import { NEON_SERVICES, deprecatedServiceMessage, parseServices, servicesFlagValue, servicesOption } from "../neon_services.js";
@@ -460,7 +460,7 @@ const finishClaimedContext = (props, projectId, contextMatches) => {
460
460
  ...contextBranch(context) ? { branch: contextBranch(context) } : {}
461
461
  });
462
462
  }
463
- log.info("Dropped the local identity assertion. The next command needs `neon auth` or `neon link`.");
463
+ log.info("Dropped the local identity assertion. The next command needs `neon login` or `neon link`.");
464
464
  };
465
465
  //#endregion
466
466
  export { CLAIM_CREATE_FIELDS, CLAIM_LIST_FIELDS, aliases, builder, claimCreateFields, claimableCapabilities, command, create, describe, handler, claim_exports as t };
@@ -4,8 +4,8 @@ import { log } from "../log.js";
4
4
  import { getApiClient } from "../api.js";
5
5
  import { contextBranch, ensureDirectoryGitignored, readContextFile } from "../context.js";
6
6
  import { getCliName } from "../utils/cli_name.js";
7
- import { NEON_SERVICE_LABELS, deprecatedServiceMessage, parseServices, servicesFlagValue, servicesOption } from "../neon_services.js";
8
- import { CONFIG_INIT_NONE_MEANS, CONFIG_INIT_SERVICES, CONFIG_INIT_UNAVAILABLE, FUNCTION_FILENAME, FUNCTION_SLUG, FUNCTION_TEMPLATE, REQUIRED_PACKAGES, renderFunctionSource, renderNeonConfig, renderNeonConfigFromView } from "../config_template.js";
7
+ import { NEON_SERVICES, NEON_SERVICE_LABELS, deprecatedServiceMessage, servicesFlagValue, servicesOption } from "../neon_services.js";
8
+ import { FUNCTION_FILENAME, FUNCTION_SLUG, FUNCTION_TEMPLATE, REQUIRED_PACKAGES, parseConfigInitServices, renderFunctionSource, renderNeonConfig, renderNeonConfigFromView } from "../config_template.js";
9
9
  import { editNeonConfig } from "../config_edit.js";
10
10
  import { toNeonConfigView } from "../config_format.js";
11
11
  import { declaredNeonServices } from "../config_services.js";
@@ -88,6 +88,7 @@ const envFlag = { env: {
88
88
  /** Apply-only flags, exported so `deploy` can reuse the exact same surface. */
89
89
  const applyFlags = {
90
90
  "update-existing": {
91
+ alias: ["y", "yes"],
91
92
  describe: "Auto-confirm overriding existing remote settings on the branch",
92
93
  type: "boolean",
93
94
  default: false
@@ -152,13 +153,7 @@ const missingDependencies = (cwd) => {
152
153
  * starter policy, which is what `config init` has always written.
153
154
  */
154
155
  const resolveServices = async (props) => {
155
- if (props.services !== void 0) return parseServices(props.services, {
156
- allowed: CONFIG_INIT_SERVICES,
157
- whyUnavailable: CONFIG_INIT_UNAVAILABLE,
158
- flag: "--services",
159
- noneMeans: CONFIG_INIT_NONE_MEANS,
160
- onDeprecated: (used, canonical) => log.warning(deprecatedServiceMessage(used, canonical))
161
- });
156
+ if (props.services !== void 0) return parseConfigInitServices(props.services, (used, canonical) => log.warning(deprecatedServiceMessage(used, canonical)));
162
157
  if (props.pickServices) return props.pickServices();
163
158
  if (isCi() || !process.stdout.isTTY) return [];
164
159
  return pickServicesInteractively();
@@ -475,10 +470,9 @@ const builder = (argv) => argv.usage("$0 config <sub-command> [options]").option
475
470
  },
476
471
  services: servicesOption({
477
472
  key: "services",
478
- allowed: CONFIG_INIT_SERVICES,
479
- noneMeans: CONFIG_INIT_NONE_MEANS,
473
+ allowed: NEON_SERVICES,
480
474
  describe: "Services the scaffolded neon.ts declares",
481
- also: "Omitted: pick interactively on a terminal, starter policy in CI or without a TTY."
475
+ also: "postgres alone writes the starter policy; every branch has Postgres. Omitted: pick interactively on a terminal, starter policy in CI or without a TTY."
482
476
  }),
483
477
  "from-branch": {
484
478
  describe: "Seed neon.ts from a branch's live Neon state instead of asking. Uses the branch pinned in .neon, or --branch <name|id>, or the project's default branch. The only mode of `config init` that calls the Neon API.",
@@ -4,11 +4,11 @@ import { isClaimableEnvTarget } from "../claimable/state.js";
4
4
  import { getCliName } from "../utils/cli_name.js";
5
5
  import { readEnvFile, resolveEnvFilePath } from "../env_file.js";
6
6
  import { l as functionBaseUrlKey } from "../_chunks/env-HYNFtxu5.js";
7
- import { branchIdResolve } from "../utils/enrichers.js";
8
- import { bundleEntry } from "../utils/esbuild.js";
9
7
  import { a as resolveDevEnv } from "../_chunks/env-BWqJqBDJ.js";
10
8
  import { findConfigFunctionBySource, resolveFunctionsFromConfig } from "../dev/functions.js";
11
9
  import { resolveWatchInputs } from "../dev/inputs.js";
10
+ import { branchIdResolve } from "../utils/enrichers.js";
11
+ import { bundleEntry } from "../utils/esbuild.js";
12
12
  import { existsSync, mkdirSync, rmSync, statSync, writeFileSync } from "node:fs";
13
13
  import { basename, dirname, join, relative, resolve } from "node:path";
14
14
  import { fileURLToPath } from "node:url";
@@ -7,10 +7,10 @@ import { deprecatedServiceMessage, parseServices, servicesFlagValue, servicesOpt
7
7
  import { mergeEnvFile, readEnvFile, resolveEnvFilePath } from "../env_file.js";
8
8
  import { t as NEON_ENV_VAR_KEYS, u as isFunctionBaseUrlKey } from "../_chunks/env-HYNFtxu5.js";
9
9
  import { ENV_PULL_KEY_HELP, ENV_PULL_SERVICES, envKeysForSelection, envPullFlagValue, ownedEnvServiceKeys, parseEnvPullKeys } from "../env_services.js";
10
+ import { i as dropClaimableUnsupported, o as resolveNeonEnvVars } from "../_chunks/env-BWqJqBDJ.js";
10
11
  import { fillSingleProject, resolveBranchRef } from "../utils/enrichers.js";
11
12
  import { warnAiGateway } from "../utils/ai_gateway_notice.js";
12
13
  import { announceTargetBranch } from "../utils/branch_notice.js";
13
- import { i as dropClaimableUnsupported, o as resolveNeonEnvVars } from "../_chunks/env-BWqJqBDJ.js";
14
14
  import { formatPulledEnv } from "./env_output.js";
15
15
  import { existsSync } from "node:fs";
16
16
  import chalk from "chalk";
@@ -1,8 +1,7 @@
1
1
  import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
2
2
  import { getCliName } from "../utils/cli_name.js";
3
3
  import { helpCsv, helpEpilogue } from "../utils/help_text.js";
4
- import { servicesOption } from "../neon_services.js";
5
- import { CONFIG_INIT_NONE_MEANS, CONFIG_INIT_SERVICES } from "../config_template.js";
4
+ import { NEON_SERVICES, servicesOption } from "../neon_services.js";
6
5
  import { coerceAgentFlag } from "../utils/agent_flag.js";
7
6
  import { initPluginAgents, initSkillsMcpAgents } from "../init/plan.js";
8
7
  import { listSkillIds } from "../skills/catalog.js";
@@ -52,10 +51,9 @@ const builder = (yargs) => yargs.usage("$0 init [options]").option("context-file
52
51
  describe: "Create neon.ts after linking. Use --no-config to skip. Omitted in Custom: you will be asked"
53
52
  }).option("services", servicesOption({
54
53
  key: "services",
55
- allowed: CONFIG_INIT_SERVICES,
54
+ allowed: NEON_SERVICES,
56
55
  describe: "Services to declare in neon.ts",
57
- noneMeans: CONFIG_INIT_NONE_MEANS,
58
- also: "Implies creating neon.ts. Cannot be combined with --no-config."
56
+ also: "postgres alone writes the starter policy; every branch has Postgres. Implies creating neon.ts. Cannot be combined with --no-config."
59
57
  })).option("org-id", {
60
58
  describe: "Forwarded to link: organization ID to link to",
61
59
  type: "string"
@@ -11,8 +11,8 @@ import { Parser } from "yargs/helpers";
11
11
  */
12
12
  const commandManifest = [
13
13
  {
14
- command: "auth",
15
- aliases: ["login"],
14
+ command: "login",
15
+ aliases: ["auth"],
16
16
  describe: "Sign in with a browser. See --help for API keys and profiles",
17
17
  load: () => import("./auth.js")
18
18
  },
@@ -139,7 +139,7 @@ const setupNeonMcp = async (options) => {
139
139
  cwd
140
140
  }) : void 0;
141
141
  if (plan.auth === "api-key" && !existing) {
142
- if (!options.apiClient || !options.apiKey) throw new Error(`Authentication required. Run \`${getCliName()} auth\`, pass --api-key or use --oauth to install without a Neon credential.`);
142
+ if (!options.apiClient || !options.apiKey) throw new Error(`Authentication required. Run \`${getCliName()} login\`, pass --api-key or use --oauth to install without a Neon credential.`);
143
143
  if (!canPickAgentsInteractively() && options.yes !== true && (options.agent ?? []).length === 0) throw new Error("No interactive terminal. Pass -y to mint into every detected agent, --agent <name> to name them or --oauth to install without minting.");
144
144
  }
145
145
  let auth;
@@ -1,14 +1,14 @@
1
1
  import { t as __exportAll } from "../_chunks/rolldown-runtime-8H4AJuhK.js";
2
2
  import { t as writeSecretFile } from "../_chunks/secure_file-BucZj4yQ.js";
3
- import { c as describeScope, d as scopeOf, l as interpretCredentials, n as KEYRING_SERVICE, o as apiKeyCredentials, r as keyringAccount, s as credentialLabel, t as storeFor } from "../_chunks/credential_io-D8AR-jvB.js";
3
+ import { c as describeScope, d as scopeOf, l as interpretCredentials, n as KEYRING_SERVICE, o as apiKeyCredentials, r as keyringAccount, s as credentialLabel, t as storeFor } from "../_chunks/credential_io-ByNuojoE.js";
4
4
  import { isCi } from "../env.js";
5
5
  import { log } from "../log.js";
6
6
  import { getApiClient, isNeonApiError } from "../api.js";
7
7
  import { setAuthContext } from "../auth_context.js";
8
8
  import { a as isOwnedCredentialPath, n as credentialsPath } from "../_chunks/paths-DMq0Lt7a.js";
9
- import { _ as upsertProfile, a as canDropProfilesFile, c as listProfiles, d as newProfileLocation, f as profilesFilePath, g as selectProfileName, h as resolveProfile, i as assertValidProfileName, l as locationForName, m as readProfiles, n as KEYRING_CREDENTIALS, o as credentialsDisplay, p as profilesUsingPath, r as assertProfilesUsable, s as isKeyringPointer, u as locationOf, v as CRED_STORAGE_FILE, y as CRED_STORAGE_KEYRING } from "../_chunks/profiles-CvnFEQyd.js";
9
+ import { _ as upsertProfile, a as canDropProfilesFile, c as listProfiles, d as newProfileLocation, f as profilesFilePath, g as selectProfileName, h as resolveProfile, i as assertValidProfileName, l as locationForName, m as readProfiles, n as KEYRING_CREDENTIALS, o as credentialsDisplay, p as profilesUsingPath, r as assertProfilesUsable, s as isKeyringPointer, u as locationOf, v as CRED_STORAGE_FILE, y as CRED_STORAGE_KEYRING } from "../_chunks/profiles-DIB1av2Q.js";
10
10
  import { auth, revokeToken } from "../auth.js";
11
- import { t as credentialInputs } from "../_chunks/auth_selection-pitMFzDe.js";
11
+ import { t as credentialInputs } from "../_chunks/auth_selection-YX5_KZgD.js";
12
12
  import { readOutgoingCredential, retirePreviousCredential, revokeTokenSet, withdrawKey } from "../retire_credential.js";
13
13
  import { authFlow, usableCredential } from "./auth.js";
14
14
  import { identityFromAuthDetails, isApiKeyMethod, mintedKeyName, notAnApiKeyMessage } from "../profile_keys.js";
@@ -70,7 +70,7 @@ const builder = (argv) => argv.usage("$0 profile <sub-command> [options]").comma
70
70
  throw new Error(`--force is no longer a flag. \`neon profile create ${name}\` always replaces an existing profile and revokes the credential it held. Drop --force.`);
71
71
  }
72
72
  return true;
73
- }).example("$0 profile create work", "Sign in with the browser, like `neon auth --profile work`").example("$0 profile create work --api-key \"$KEY\"", "Store a key you already have").example("echo \"$KEY\" | $0 profile create work --api-key -", "Or pipe it, so it never reaches the process arguments").example("$0 profile create ci --mint --org-id org-abc-123", "One browser sign-in, then an org-scoped key and no session left behind").example("$0 profile create work --keyring", "Store the credential in the OS keyring instead of a file"), async (args) => await create(args)).command("rotate-key <name>", "Mint a fresh API key for a profile, at the same scope, and revoke the one it replaces", (y) => y.positional("name", {
73
+ }).example("$0 profile create work", "Sign in with the browser, like `neon login --profile work`").example("$0 profile create work --api-key \"$KEY\"", "Store a key you already have").example("echo \"$KEY\" | $0 profile create work --api-key -", "Or pipe it, so it never reaches the process arguments").example("$0 profile create ci --mint --org-id org-abc-123", "One browser sign-in, then an org-scoped key and no session left behind").example("$0 profile create work --keyring", "Store the credential in the OS keyring instead of a file"), async (args) => await create(args)).command("rotate-key <name>", "Mint a fresh API key for a profile, at the same scope, and revoke the one it replaces", (y) => y.positional("name", {
74
74
  describe: "Profile to rotate",
75
75
  type: "string",
76
76
  demandOption: true
@@ -17,6 +17,7 @@ const handler = async (args) => {
17
17
  await me(args);
18
18
  };
19
19
  const me = async (props) => {
20
+ if (!props.apiClient) return;
20
21
  const { data } = await props.apiClient.getCurrentUserInfo();
21
22
  if (props.output === "json" || props.output === "yaml") {
22
23
  writer(props).end(data, { fields: [
@@ -1,4 +1,4 @@
1
- import { NEON_SERVICES } from "./neon_services.js";
1
+ import { NEON_SERVICES, parseServices } from "./neon_services.js";
2
2
  //#region src/config_template.ts
3
3
  /**
4
4
  * The published npm packages a `neon.ts` project needs — the `@neon/*` org names.
@@ -23,13 +23,15 @@ const REQUIRED_PACKAGES = [CONFIG_PACKAGE, ENV_PACKAGE];
23
23
  */
24
24
  const CONFIG_INIT_SERVICES = NEON_SERVICES.filter((service) => service !== "postgres");
25
25
  /**
26
- * What `config init --services none` produces. One constant because it is both the help text
27
- * and what tells the parser `none` is a value here — passing the literal at each call site
28
- * lets the two drift into documenting something the parser does not accept.
26
+ * Parse `--services` on `init` and `config init` into the services to declare. `postgres` is
27
+ * accepted, alone or with others, and declares nothing: `--services postgres` is how a
28
+ * script asks for the Postgres-only starter policy.
29
29
  */
30
- const CONFIG_INIT_NONE_MEANS = "the bare starter policy";
31
- /** Why a policy cannot declare a real Neon service, for the refusal message. */
32
- const CONFIG_INIT_UNAVAILABLE = { postgres: "every branch has Postgres, so a policy has nothing to declare for it" };
30
+ const parseConfigInitServices = (raw, onDeprecated) => parseServices(raw, {
31
+ allowed: NEON_SERVICES,
32
+ flag: "--services",
33
+ ...onDeprecated ? { onDeprecated } : {}
34
+ }).filter((service) => service !== "postgres");
33
35
  /** Slug, display name, and source path of the function scaffolded for `functions`. */
34
36
  const FUNCTION_SLUG = "hello";
35
37
  const FUNCTION_NAME = "Hello World";
@@ -200,4 +202,4 @@ const renderFunctionSource = (slug, language) => {
200
202
  };
201
203
  const FUNCTION_TEMPLATE = renderFunctionSource(FUNCTION_SLUG, "ts");
202
204
  //#endregion
203
- export { BUCKET_NAME, CONFIG_INIT_NONE_MEANS, CONFIG_INIT_SERVICES, CONFIG_INIT_UNAVAILABLE, CONFIG_PACKAGE, ENV_PACKAGE, FUNCTION_FILENAME, FUNCTION_NAME, FUNCTION_SLUG, FUNCTION_TEMPLATE, REQUIRED_PACKAGES, renderFunctionSource, renderKey, renderNeonConfig, renderNeonConfigFromView };
205
+ export { BUCKET_NAME, CONFIG_INIT_SERVICES, CONFIG_PACKAGE, ENV_PACKAGE, FUNCTION_FILENAME, FUNCTION_NAME, FUNCTION_SLUG, FUNCTION_TEMPLATE, REQUIRED_PACKAGES, parseConfigInitServices, renderFunctionSource, renderKey, renderNeonConfig, renderNeonConfigFromView };
@@ -1,2 +1,2 @@
1
- import { t as storeFor } from "./_chunks/credential_io-D8AR-jvB.js";
1
+ import { t as storeFor } from "./_chunks/credential_io-ByNuojoE.js";
2
2
  export { storeFor };
package/dist/index.js CHANGED
@@ -154,7 +154,7 @@ async function handleError(msg, err, canRetry) {
154
154
  log.error(err.message);
155
155
  if (err.terminal) {
156
156
  const context = getAuthContext();
157
- log.error(`Run \`neon auth --profile ${context?.profile ?? "DEFAULT"}\` to sign in again.`);
157
+ log.error(`Run \`neon login --profile ${context?.profile ?? "DEFAULT"}\` to sign in again.`);
158
158
  }
159
159
  sendError(err, "AUTH_FAILED");
160
160
  return false;
@@ -10,7 +10,7 @@ const resolveInitConfigChoice = (input) => {
10
10
  };
11
11
  if (input.yes) return {
12
12
  kind: "write",
13
- services: ["none"]
13
+ services: ["postgres"]
14
14
  };
15
15
  if (input.flag === true) return { kind: "write" };
16
16
  if (input.canAsk) return { kind: "ask" };
@@ -21,10 +21,6 @@ const configPlanFromResolution = (resolution, accepted) => {
21
21
  if (resolution.kind === "skip") return { kind: "skip" };
22
22
  return resolution;
23
23
  };
24
- const isBareInitServices = (services) => {
25
- if (services === void 0 || services.length === 0) return true;
26
- return services.every((service) => service === "none");
27
- };
28
24
  const shouldRefreshEnvAfterNewConfig = (input) => input.wroteNewFile && typeof input.projectId === "string" && input.projectId.length > 0 && typeof input.branch === "string" && input.branch.length > 0;
29
25
  const shouldPullEnvAfterInitConfig = (input) => !input.extraServices && !input.alreadyPulled && shouldRefreshEnvAfterNewConfig({
30
26
  wroteNewFile: input.wroteNewFile,
@@ -32,4 +28,4 @@ const shouldPullEnvAfterInitConfig = (input) => !input.extraServices && !input.a
32
28
  ...input.branch !== void 0 ? { branch: input.branch } : {}
33
29
  });
34
30
  //#endregion
35
- export { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution, isBareInitServices, resolveInitConfigChoice, shouldPullEnvAfterInitConfig, shouldRefreshEnvAfterNewConfig };
31
+ export { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution, resolveInitConfigChoice, shouldPullEnvAfterInitConfig, shouldRefreshEnvAfterNewConfig };
package/dist/init/copy.js CHANGED
@@ -49,8 +49,8 @@ const SERVICES_MESSAGE = "Which services should neon.ts declare? (space to toggl
49
49
  const PACKAGE_MANAGER_MESSAGE = "Which package manager should install the Neon dependencies?";
50
50
  const NO_AGENTS_FALLBACK_STATUS = "No coding agents detected. Installing the default Neon skills for Cursor and Codex in this directory.";
51
51
  const NO_AGENT_SETUP_CONFLICT = "--no-agent-setup cannot be combined with --agent, --skill, or MCP flags.";
52
- const NON_TTY_LINK_NEEDS_AUTH = "No interactive terminal. Sign in with `neon auth`, then re-run, or pass --claimable.";
53
- const YES_LINK_NEEDS_AUTH = "-y cannot sign in. Sign in with `neon auth`, then re-run, or pass --claimable.";
52
+ const NON_TTY_LINK_NEEDS_AUTH = "No interactive terminal. Sign in with `neon login`, then re-run, or pass --claimable.";
53
+ const YES_LINK_NEEDS_AUTH = "-y cannot sign in. Sign in with `neon login`, then re-run, or pass --claimable.";
54
54
  const MCP_SCOPED_NEEDS_PROJECT = "--mcp-project-scoped requires a linked project. Link a project first, or omit --mcp-project-scoped.";
55
55
  const namedAgentsUnavailable = (ids) => `--agent ${ids.join(", ")} cannot install this tooling. Pass agents that support it, or omit --agent.`;
56
56
  const mcpConfigLocationUnavailable = (ids, location) => location === "project" ? `--agent ${ids.join(", ")} cannot install project-level MCP config. Use --mcp-config-location global, or choose an agent that supports project config.` : `--agent ${ids.join(", ")} cannot install global MCP config. Choose an agent that supports global config.`;
@@ -80,7 +80,7 @@ const PROGRESS = {
80
80
  const unattendedUnauthedNext = () => [
81
81
  "Link a project with a Neon account and an authenticated CLI.",
82
82
  "Sign up: https://neon.com/signup",
83
- `${getCliName()} auth`,
83
+ `${getCliName()} login`,
84
84
  `${getCliName()} link`,
85
85
  "",
86
86
  "Or create a claimable project without an account. It expires in 72 hours unless claimed.",
@@ -1,7 +1,7 @@
1
- import { t as storeFor } from "../_chunks/credential_io-D8AR-jvB.js";
1
+ import { t as storeFor } from "../_chunks/credential_io-ByNuojoE.js";
2
2
  import { isCi } from "../env.js";
3
- import { h as resolveProfile, u as locationOf } from "../_chunks/profiles-CvnFEQyd.js";
4
- import { i as selectCredential, t as credentialInputs } from "../_chunks/auth_selection-pitMFzDe.js";
3
+ import { h as resolveProfile, u as locationOf } from "../_chunks/profiles-DIB1av2Q.js";
4
+ import { i as selectCredential, t as credentialInputs } from "../_chunks/auth_selection-YX5_KZgD.js";
5
5
  import { detectInstalledAgents, uniqueAgentIds } from "../mcp/agents.js";
6
6
  import "./agents.js";
7
7
  import { directoryIsEmpty } from "./plan.js";
package/dist/init/plan.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { getCliName } from "../utils/cli_name.js";
2
- import { NO_SERVICES } from "../neon_services.js";
3
2
  import { tryResolveAddMcpAgentId, uniqueAgentIds } from "../mcp/agents.js";
4
3
  import { mcpInstallableAgents } from "../mcp/targets.js";
5
4
  import { supportsSkills } from "./agents.js";
@@ -363,13 +362,13 @@ const planConfigInitStep = (input) => {
363
362
  "config",
364
363
  "init",
365
364
  "--services",
366
- input.services.length === 0 ? NO_SERVICES : input.services.join(",")
365
+ input.services.length === 0 ? "postgres" : input.services.join(",")
367
366
  ];
368
367
  if (input.yes) return [
369
368
  "config",
370
369
  "init",
371
370
  "--services",
372
- NO_SERVICES
371
+ "postgres"
373
372
  ];
374
373
  return ["config", "init"];
375
374
  };
package/dist/init/run.js CHANGED
@@ -6,8 +6,8 @@ import { recordCommandSuccessExtras, takeCommandSuccessExtras } from "../analyti
6
6
  import "../claimable/api.js";
7
7
  import { readLinkedClaimableCredentials } from "../claimable/state.js";
8
8
  import { getCliName } from "../utils/cli_name.js";
9
- import { deprecatedServiceMessage, parseServices, servicesFlagValue } from "../neon_services.js";
10
- import { CONFIG_INIT_NONE_MEANS, CONFIG_INIT_SERVICES, CONFIG_INIT_UNAVAILABLE } from "../config_template.js";
9
+ import { servicesFlagValue } from "../neon_services.js";
10
+ import { CONFIG_INIT_SERVICES, parseConfigInitServices } from "../config_template.js";
11
11
  import { hasNeonConfigFile, neonConfigFilename } from "../project.js";
12
12
  import { getAgentDisplayName } from "../mcp/agents.js";
13
13
  import { mcpInstallableAgents } from "../mcp/targets.js";
@@ -24,7 +24,7 @@ import { InitCancelled, raceSigint, restoreCursor } from "./cancelled.js";
24
24
  import { pickAgentSetupInteractively, pickInitAgentsInteractively, pickInitConfigInteractively, pickInitMcpAuthInteractively, pickInitMcpConfigLocationInteractively, pickInitModeInteractively, pickInitPackageManagerInteractively, pickInitProjectSetupInteractively, pickInitServicesInteractively, pickInitSkillsInteractively } from "./wizard.js";
25
25
  import { runToolingSteps } from "./tooling.js";
26
26
  import { create } from "../commands/claim.js";
27
- import { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution, isBareInitServices, resolveInitConfigChoice, shouldPullEnvAfterInitConfig } from "./choices.js";
27
+ import { INIT_CONFIG_SERVICES_CONFLICT, configPlanFromResolution, resolveInitConfigChoice, shouldPullEnvAfterInitConfig } from "./choices.js";
28
28
  import { detectInitEnvironment } from "./detect.js";
29
29
  import { createInitFunnel, emitInitStart, finishInitFunnel, initStartProperties } from "./funnel.js";
30
30
  import { assertAgentSetupFlags, hasInitMcpFlags, inferInitAgentSetup, resolveInitMode } from "./mode.js";
@@ -34,17 +34,6 @@ const isLinked = (contextFile) => {
34
34
  const projectId = readContextFile(contextFile).projectId;
35
35
  return typeof projectId === "string" && projectId.length > 0;
36
36
  };
37
- const parsedInitServices = (raw) => {
38
- const values = servicesFlagValue(raw);
39
- if (values === void 0) return;
40
- return parseServices(values, {
41
- allowed: CONFIG_INIT_SERVICES,
42
- whyUnavailable: CONFIG_INIT_UNAVAILABLE,
43
- flag: "--services",
44
- noneMeans: CONFIG_INIT_NONE_MEANS,
45
- onDeprecated: (used, canonical) => log.warning(deprecatedServiceMessage(used, canonical))
46
- });
47
- };
48
37
  const expandTelemetryServices = (services) => {
49
38
  if (services.includes("data-api") && !services.includes("auth")) return CONFIG_INIT_SERVICES.filter((service) => service === "auth" || services.includes(service));
50
39
  return [...services];
@@ -172,8 +161,9 @@ const runInit = async (props) => {
172
161
  ...props.forceAuth !== void 0 ? { forceAuth: props.forceAuth } : {},
173
162
  ...props.allowUnsafeTls !== void 0 ? { allowUnsafeTls: props.allowUnsafeTls } : {}
174
163
  };
175
- const servicesFlag = parsedInitServices(props.services);
164
+ const servicesFlag = servicesFlagValue(props.services);
176
165
  if (props.config === false && servicesFlag !== void 0) throw new Error(INIT_CONFIG_SERVICES_CONFLICT);
166
+ if (servicesFlag !== void 0) parseConfigInitServices(servicesFlag);
177
167
  const linkInputs = {
178
168
  ...props.orgId ? { orgId: props.orgId } : {},
179
169
  ...props.projectId ? { projectId: props.projectId } : {},
@@ -459,25 +449,22 @@ const runInit = async (props) => {
459
449
  const picked = await (props.pickServices ?? pickInitServicesInteractively)();
460
450
  configPlan = {
461
451
  kind: "write",
462
- services: picked.length === 0 ? ["none"] : picked
452
+ services: picked.length === 0 ? ["postgres"] : picked
463
453
  };
464
454
  }
465
455
  if (recommended && configPlan.kind === "write" && !existingConfig) configPlan = {
466
456
  kind: "write",
467
- services: servicesFlag ?? ["none"]
457
+ services: servicesFlag ?? ["postgres"]
468
458
  };
469
459
  let wroteNewFile = false;
470
460
  let extraServices = false;
471
461
  let selectedServices = null;
472
462
  if (configPlan.kind === "write") {
473
- const planned = existingConfig ? void 0 : configPlan.services ?? ["none"];
463
+ const planned = existingConfig ? void 0 : configPlan.services ?? ["postgres"];
474
464
  if (planned !== void 0) {
475
- extraServices = !isBareInitServices(planned);
476
- selectedServices = extraServices ? expandTelemetryServices(parseServices(planned, {
477
- allowed: CONFIG_INIT_SERVICES,
478
- flag: "--services",
479
- noneMeans: CONFIG_INIT_NONE_MEANS
480
- })) : [];
465
+ const declared = parseConfigInitServices(planned);
466
+ extraServices = declared.length > 0;
467
+ selectedServices = expandTelemetryServices(declared);
481
468
  funnel.services = selectedServices;
482
469
  wroteNewFile = true;
483
470
  } else selectedServices = null;
package/dist/mcp/mint.js CHANGED
@@ -4,7 +4,7 @@ import { getCliName } from "../utils/cli_name.js";
4
4
  import { mintedKeyName } from "../profile_keys.js";
5
5
  import { orgIdForProject } from "../commands/api_keys.js";
6
6
  //#region src/mcp/mint.ts
7
- const cannotMintMessage = "This CLI credential cannot mint API keys. Organization and project-scoped keys cannot create other keys. Sign in with `neon auth` or pass a personal API key.";
7
+ const cannotMintMessage = "This CLI credential cannot mint API keys. Organization and project-scoped keys cannot create other keys. Sign in with `neon login` or pass a personal API key.";
8
8
  function mintedKeyRevokeCommand(key) {
9
9
  return key.orgId ? `${getCliName()} api-keys revoke ${key.id} --org-id ${key.orgId}` : `${getCliName()} api-keys revoke ${key.id}`;
10
10
  }
@@ -40,8 +40,6 @@ const NEON_SERVICE_LABELS = {
40
40
  * vocabulary, and absent from help text, errors, and docs so nobody learns it fresh.
41
41
  */
42
42
  const DEPRECATED_SERVICE_ALIASES = { storage: "object-storage" };
43
- /** An explicit empty selection, for commands where "declare nothing" is a real answer. */
44
- const NO_SERVICES = "none";
45
43
  /**
46
44
  * What to tell someone still using a retired spelling. A message rather than a log call, so
47
45
  * the parser stays free of the CLI's writer and each command can surface it in its own voice.
@@ -57,18 +55,14 @@ const deprecatedServiceMessage = (used, canonical) => `"${used}" is the old name
57
55
  *
58
56
  * An unrecognized name is rejected rather than dropped: a typo would otherwise act on
59
57
  * everything *except* the service that was asked for, and report success. A name that is a
60
- * real service but not one this command supports says so specifically — "postgres is on
61
- * every branch" is a different problem from a typo, and has a different fix.
58
+ * real service but not one this command supports says so, since that is a different problem
59
+ * from a typo.
62
60
  */
63
61
  const parseServices = (raw, options) => {
64
- const { allowed, flag, noneMeans, whyUnavailable = {}, onDeprecated } = options;
65
- const supported = `Supported values: ${allowed.join(", ")}${noneMeans !== void 0 ? `, ${NO_SERVICES}` : ""}.`;
62
+ const { allowed, flag, onDeprecated } = options;
63
+ const supported = `Supported values: ${allowed.join(", ")}.`;
66
64
  const names = raw.flatMap((value) => value.split(",")).map((name) => name.trim()).filter((name) => name !== "");
67
65
  if (names.length === 0) throw new Error(`${flag} needs at least one service. ${supported}`);
68
- if (noneMeans !== void 0 && names.includes("none")) {
69
- if (new Set(names).size > 1) throw new Error(`${flag} ${NO_SERVICES} cannot be combined with other services.`);
70
- return [];
71
- }
72
66
  const deprecated = /* @__PURE__ */ new Map();
73
67
  const resolved = names.map((name) => {
74
68
  const canonical = DEPRECATED_SERVICE_ALIASES[name];
@@ -77,23 +71,19 @@ const parseServices = (raw, options) => {
77
71
  return canonical;
78
72
  });
79
73
  const unsupported = resolved.filter((name) => !allowed.some((service) => service === name));
80
- if (unsupported.length > 0) throw new Error(`${unsupportedMessage(unsupported, flag, whyUnavailable)} ${supported}`);
74
+ if (unsupported.length > 0) throw new Error(`${unsupportedMessage(unsupported, flag)} ${supported}`);
81
75
  for (const [used, canonical] of deprecated) onDeprecated?.(used, canonical);
82
76
  return NEON_SERVICES.filter((service) => allowed.includes(service) && resolved.includes(service));
83
77
  };
84
78
  /**
85
79
  * The sentences explaining why a selection was refused. A real Neon service this command
86
80
  * cannot act on is a different mistake from a typo — different cause, different fix — so the
87
- * two are never answered with the same word, and each service carries its reason where the
88
- * command supplied one.
81
+ * two are never answered with the same word.
89
82
  */
90
- const unsupportedMessage = (unsupported, flag, whyUnavailable) => {
83
+ const unsupportedMessage = (unsupported, flag) => {
91
84
  const known = unsupported.filter((name) => NEON_SERVICES.some((service) => service === name));
92
85
  const unknown = unsupported.filter((name) => !known.some((service) => service === name));
93
- return [unknown.length > 0 ? `Unknown service${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")}.` : void 0, ...known.map((service) => {
94
- const why = whyUnavailable[service];
95
- return `${service} is not something ${flag} can select${why ? `: ${why}` : ""}.`;
96
- })].filter((part) => part !== void 0).join(" ");
86
+ return [unknown.length > 0 ? `Unknown service${unknown.length === 1 ? "" : "s"} ${unknown.join(", ")}.` : void 0, ...known.map((service) => `${service} is not something ${flag} can select.`)].filter((part) => part !== void 0).join(" ");
97
87
  };
98
88
  /** Every spelling of the services flag, so a habit picked up on one command works on another. */
99
89
  const SERVICE_FLAG_NAMES = [
@@ -110,7 +100,6 @@ const servicesOption = (params) => ({
110
100
  alias: SERVICE_FLAG_NAMES.filter((name) => name !== params.key),
111
101
  describe: [
112
102
  `${params.describe}: ${params.allowed.join(", ")}.`,
113
- params.noneMeans !== void 0 ? `Pass "${NO_SERVICES}" for ${params.noneMeans}.` : void 0,
114
103
  "Repeat the flag or comma-separate.",
115
104
  params.also
116
105
  ].filter((part) => part !== void 0).join(" "),
@@ -124,4 +113,4 @@ const servicesOption = (params) => ({
124
113
  */
125
114
  const servicesFlagValue = (value) => Array.isArray(value) ? value.map(String) : void 0;
126
115
  //#endregion
127
- export { NEON_SERVICES, NEON_SERVICE_LABELS, NO_SERVICES, deprecatedServiceMessage, parseServices, servicesFlagValue, servicesOption };
116
+ export { NEON_SERVICES, NEON_SERVICE_LABELS, deprecatedServiceMessage, parseServices, servicesFlagValue, servicesOption };
@@ -1,4 +1,4 @@
1
- import { a as OAUTH, d as scopeOf, i as API_KEY, l as interpretCredentials, t as storeFor, u as isSameCredential } from "./_chunks/credential_io-D8AR-jvB.js";
1
+ import { a as OAUTH, d as scopeOf, i as API_KEY, l as interpretCredentials, t as storeFor, u as isSameCredential } from "./_chunks/credential_io-ByNuojoE.js";
2
2
  import { log } from "./log.js";
3
3
  import { getApiClient } from "./api.js";
4
4
  import { revokeToken } from "./auth.js";
@@ -1,4 +1,4 @@
1
- import { r as recordCredentialInputs } from "../_chunks/auth_selection-pitMFzDe.js";
1
+ import { r as recordCredentialInputs } from "../_chunks/auth_selection-YX5_KZgD.js";
2
2
  //#region src/utils/middlewares.ts
3
3
  /**
4
4
  * Forwarding Yargs's default would turn ambient configuration into an explicit child override.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neon",
3
- "version": "8.0.11",
3
+ "version": "8.1.0",
4
4
  "description": "CLI tool for Neon, the cloud backend primitives built around Lakebase Postgres",
5
5
  "keywords": [
6
6
  "neon",
@@ -64,9 +64,9 @@
64
64
  "yaml": "^2.9.0",
65
65
  "yargs": "17.7.2",
66
66
  "yoctocolors": "^2.1.2",
67
- "@neon/config": "1.8.4",
68
- "@neon/sdk": "7.0.1",
69
- "@neon/config-runtime": "1.7.6"
67
+ "@neon/config": "1.8.5",
68
+ "@neon/config-runtime": "1.7.7",
69
+ "@neon/sdk": "7.0.1"
70
70
  },
71
71
  "optionalDependencies": {
72
72
  "@napi-rs/keyring": "1.3.0",
@@ -100,9 +100,9 @@
100
100
  "typescript": "^5.9.0",
101
101
  "vitest": "^3.0.9",
102
102
  "@neon-internals/cli-core": "0.0.0",
103
- "@neon-internals/env-core": "0.0.27",
104
103
  "@neon/e2e-harness": "0.0.0",
105
- "@neon/functions": "0.11.0"
104
+ "@neon/functions": "0.11.0",
105
+ "@neon-internals/env-core": "0.0.28"
106
106
  },
107
107
  "publishConfig": {
108
108
  "access": "public",