@alter-ai/cli 0.3.0 → 0.3.1

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.
Files changed (3) hide show
  1. package/README.md +25 -188
  2. package/dist/cli.js +119 -44
  3. package/package.json +4 -2
package/README.md CHANGED
@@ -1,208 +1,45 @@
1
- # `@alter-ai/cli` — the Alter Vault command-line interface
1
+ # `@alter-ai/cli`
2
2
 
3
- `alter` is a command-line client for the Alter Vault dev portal. It authenticates with a Personal Access Token (PAT) minted from the dashboard and exposes the same dashboard operations as scriptable commands.
3
+ Command-line client for the Alter Vault dev portal. Authenticates with a Personal Access Token (PAT) and exposes the dashboard's resource model as scriptable commands.
4
+
5
+ 📖 **Full docs:** [docs.alterauth.com/reference/cli](https://docs.alterauth.com/reference/cli)
4
6
 
5
7
  ## Install
6
8
 
7
9
  ```bash
8
10
  npm install -g @alter-ai/cli
9
- # verify
10
11
  alter --version
11
12
  ```
12
13
 
13
- ## Quick start
14
-
15
- The fastest interactive sign-in is the browser-dance flow — `alter auth login` opens the dashboard, you click **Authorize**, and the CLI receives the freshly-minted token on a localhost listener:
16
-
17
- ```bash
18
- alter auth login
19
- # alter: opening browser at https://portal.alterauth.com/cli-auth
20
- # (waiting up to 2 minutes for you to approve)…
21
- # alter: signed in via browser-dance flow.
22
-
23
- alter auth status
24
- ```
25
-
26
- For headless / CI environments, mint a PAT manually from the dashboard (**Settings → Personal Access Tokens → New token**) and feed it to the CLI through one of the channels below:
27
-
28
- **Token file (recommended for local headless use):** keeps the value out of `process.argv` (visible to other users via `ps`) and out of shell history.
29
-
30
- ```bash
31
- umask 077 && echo "alter_pat_xxxxxxxxxxxxxxxxxxxxxxxx_yyyyyy" > ~/alter-pat.txt
32
- alter auth login --token-file ~/alter-pat.txt
33
- ```
34
-
35
- **Stdin:**
36
-
37
- ```bash
38
- pbpaste | alter auth login --token-stdin # macOS
39
- xclip -o -selection clipboard | alter auth login --token-stdin # Linux
40
- ```
41
-
42
- **Env var (CI):** skip persistence entirely. The SDK reads `ALTER_PAT` directly; it never lands in argv.
14
+ ## Sign in
43
15
 
44
16
  ```bash
45
- export ALTER_PAT="alter_pat_xxxxxxxxxxxxxxxxxxxxxxxx_yyyyyy"
46
- alter apps list
17
+ alter auth login # interactive browser flow
18
+ ALTER_PAT=alter_pat_... alter apps list # headless / CI
47
19
  ```
48
20
 
49
- **Inline `--token <pat>` is supported but discouraged** — the value lands in `process.argv` (visible to other local users via `ps aux`) and shell history. Use only on single-user machines and rotate afterwards.
50
-
51
21
  ## Commands
52
22
 
53
- The CLI mirrors the dashboard's resource model. Every namespace lives at `alter <namespace> <verb>`:
54
-
55
- ```
56
- auth login | status | logout Sign in / out + token introspection
57
- apps list | create | show | update | delete Manage applications
58
- keys list | mint | show | rotate | revoke | rename Manage runtime API keys
59
- agents list | create | show | update | revoke Managed-agent identities (+ mint-key, list-keys, revoke-key)
60
- providers list | list-catalog | create | show | update | delete OAuth provider integrations per app
61
- managed-secrets
62
- templates | list | show | create | delete | rotate | access | users |
63
- grants {list, list-for-agent, create, update, revoke} |
64
- groups {list, show} Managed-secret credentials, grants, and access (CRUD + autocomplete helpers)
65
- policy show-app View app-level policy (org-wide policy is dashboard-only)
66
- audit list | show | portal-actions | grant-events | traces Dev-portal audit log
67
- pats whoami Same as `auth status`, under the `pats` namespace
68
- link <app-id> | --status Pin an app to the current directory tree
69
- unlink Clear the workspace pin
70
- completion install | print Generate shell completions (bash/zsh/fish)
71
- self-update --to <v> | --dry-run Upgrade the CLI via npm
72
- sdk-passthrough request <method> <path> [...] Raw authenticated request (escape hatch for routes the CLI doesn't model)
73
- ```
74
-
75
- PAT lifecycle (mint, revoke) remains **dashboard-only** in v1 — a PAT cannot mint or revoke another PAT, including its own. Operators use the dashboard for those actions. Org-wide policy and identity-provider configuration are also dashboard-only per the destructive-action policy in CLAUDE.md.
76
-
77
- Every list / show command accepts `--output=json|table|jsonl` (default: `json` for pipelines, `table` for interactive). Object commands default to `json`. Use `--fields a,b,c` at the top level to project to specific keys (see [Field selection](#field-selection---fields)).
78
-
79
- ## Authentication
80
-
81
- The CLI resolves credentials in this order (highest precedence first):
82
-
83
- 1. **`ALTER_PAT` environment variable** — canonical CI / headless source.
84
- 2. **OS keychain** (macOS Keychain, Linux Secret Service / `gnome-keyring`, Windows Credential Manager) via the optional `keytar` native module. This is the default location after a successful `alter auth login`.
85
- 3. **Plaintext file** `~/.config/alter/auth.toml` (XDG-compliant, mode `0600`). Used as the fallback when `keytar` failed to build on the host (e.g. missing `libsecret-1-dev` on Linux). The CLI prints a warning at login time when it falls back to this path.
86
-
87
- The `--base-url` flag and the `ALTER_BASE_URL` environment variable both require an `https://` URL — non-HTTPS schemes (`http`, `file`, `gopher`, etc.) are rejected at login time so a misconfigured backend URL cannot exfiltrate the PAT in clear text or to an unintended target.
88
-
89
- If keytar isn't loading on your host, install the native build tools and re-install:
90
-
91
- ```bash
92
- # macOS
93
- xcode-select --install
94
- # Linux (Debian/Ubuntu — adjust for your distro)
95
- sudo apt install libsecret-1-dev gnome-keyring
96
- # Windows — install windows-build-tools or VS Build Tools
97
-
98
- npm install -g @alter-ai/cli
99
- ```
100
-
101
- ## Workspace config (`alter link`)
102
-
103
- If you work primarily on one app, run `alter link <app-id>` once in the project root. The CLI writes a tiny `.alter/config.yaml` that pins the default app for every subsequent `alter keys`, `alter agents`, `alter providers`, and `alter policy show-app` invocation in that directory tree. No more retyping the UUID.
104
-
105
- ```bash
106
- cd ~/code/my-product
107
- alter link app_abc123
108
- # alter: pinned app_id=app_abc123 in /Users/me/code/my-product/.alter/config.yaml
109
- # alter: appended `.alter/` to .gitignore so the pin isn't committed.
110
-
111
- # from anywhere in this tree, --app becomes optional:
112
- alter keys list
113
- alter agents create --name worker --type service
114
- alter policy show-app
115
-
116
- # show the current pin
117
- alter link --status
118
-
119
- # clear the pin
120
- alter unlink
121
23
  ```
122
-
123
- `app_id` precedence (highest first):
124
-
125
- 1. `--app <id>` on the command line
126
- 2. `ALTER_APP_ID` env var
127
- 3. The nearest `.alter/config.yaml` found by walking up from `process.cwd()`
128
- 4. Error: `no app selected` (exit code 2)
129
-
130
- Discovery walks up the directory tree until it finds an `.alter/` directory OR crosses your home directory (whichever comes first). The home-dir bound prevents a misplaced config in `$HOME` from silently pinning every shell.
131
-
132
- If your project lives in a git repo, `alter link` appends `.alter/` to `.gitignore` so the workspace pin doesn't get committed — same posture as `vercel link`. The pin is personal-to-the-checkout.
133
-
134
- ## Field selection (`--fields`)
135
-
136
- Narrow the JSON / JSONL output to specific top-level keys with `--fields a,b,c` at the top level — useful for scripts that only need one or two columns. Inert when paired with `--output=table` (the table columns are already a pre-defined slice). Missing fields render as `null` to keep the column visible.
137
-
138
- ```bash
139
- # List apps, keep only id + name
140
- alter apps list --fields id,name
141
- # [
142
- # { "id": "app_abc", "name": "demo" },
143
- # ...
144
- # ]
145
-
146
- # Single object — same projection rule
147
- alter apps show app_abc --fields id,name,environment
148
-
149
- # JSONL — one projected object per line
150
- alter audit list --fields timestamp,action --output=jsonl
24
+ auth login | status | logout
25
+ apps list | create | show | update | archive | unarchive | delete
26
+ keys list | mint | show | rotate | revoke | rename
27
+ agents list | create | show | update | revoke (+ mint-key, list-keys, revoke-key)
28
+ providers list | list-catalog | create | show | update | delete
29
+ managed-secrets list | show | create | rotate | delete | templates | access | users
30
+ grants {list, list-for-agent, create, update, revoke}
31
+ groups {list, show}
32
+ policy show-app
33
+ audit list | show | portal-actions | grant-events | traces
34
+ pats whoami
35
+ link / unlink pin an app to the current directory
36
+ completion install | print
37
+ self-update --to <v>
38
+ sdk-passthrough request <grant-id> --url <url>
151
39
  ```
152
40
 
153
- The `--fields` value is `,`-separated. Spaces around commas are ignored; spaces INSIDE a field name are rejected up front (catches the common `--fields 'id name'` typo with a clear error rather than silently dropping the second name).
154
-
155
- ## Exit codes
156
-
157
- `alter` returns a structured exit code so scripts can branch on the failure mode without parsing stderr text. Codes are stable contract — operators can rely on them across releases.
158
-
159
- | Code | Name | Meaning |
160
- |------|------------------|-----------------------------------------------------------------------------------------------|
161
- | 0 | OK | Command succeeded. |
162
- | 1 | ERROR | Generic runtime failure (uncategorized — including unknown SDK / network errors). |
163
- | 2 | USAGE | Bad flag, arg, or input format. Always paired with a stderr line naming the offending input. |
164
- | 3 | AUTH | Not signed in, or PAT revoked / expired. **Remediation:** re-run `alter auth login`. |
165
- | 4 | NOT_FOUND | Resource not found — 404 from the backend, or a referenced local file is missing. |
166
- | 5 | CONFLICT | 409 from the backend — most commonly a type-to-confirm mismatch or dependent-resource block. |
167
- | 6 | RATE_LIMIT | 429 from the backend — retry with backoff. |
168
- | 7 | FORBIDDEN | 403 from the backend — PAT is valid but lacks the required scope. **Remediation:** re-mint the PAT with broader scopes (or switch PATs); `alter auth login` alone does NOT help. |
169
- | 8 | CANCELLED | Operator declined an interactive prompt (type-to-confirm mismatch on a destructive action, "no" at a y/N gate). Distinct from `ERROR` (1) — the CLI did nothing wrong, the operator chose not to proceed. Pass `--yes` or `--confirm <name>` in CI to skip the prompt. |
170
-
171
- Example:
172
-
173
- ```bash
174
- # Probe whether an app exists without erroring on the not-found case.
175
- # Capture $? into a local variable BEFORE running anything else; ``$?``
176
- # is clobbered by every command, so a stray ``log_attempt`` between the
177
- # ``if`` and ``elif`` would silently break the not-found branch.
178
- alter apps show "$APP_ID" --output=json > /dev/null 2>&1
179
- status=$?
180
- if [ "$status" -eq 0 ]; then
181
- echo "app exists"
182
- elif [ "$status" -eq 4 ]; then
183
- echo "app not found"
184
- elif [ "$status" -eq 7 ]; then
185
- echo "PAT lacks dashboard_apps:read — re-mint with broader scopes"
186
- else
187
- echo "unexpected error" && exit 1
188
- fi
189
- ```
190
-
191
- Backend-thrown errors flow through `withClient` and get mapped from HTTP status to exit code automatically (401 → 3, 403 → 7, 404 → 4, 409 → 5, 429 → 6, everything else → 1). Validation errors raised by the CLI itself (e.g. malformed `--limit`) exit 2.
192
-
193
- ## Scope
194
-
195
- This CLI ships the full dev-portal command surface — `auth`, `apps`, `keys`, `agents`, `providers`, `managed-secrets`, `policy` (read-only at the app level), `audit`, `pats`, `link` / `unlink`, `completion`, `self-update`, and `sdk-passthrough` as a typed-route escape hatch. Backend routes are PAT-callable via `dashboard_*` scopes (see the [scope catalog](https://docs.alterauth.com/api-reference/scopes) for the full list).
196
-
197
- **Managed secrets — destructive verb tier:** `alter managed-secrets delete <secret-id>` cascade-revokes every grant and delegation tied to the secret, removes the stored credential from secret storage, and writes cascade audit log entries — irrecoverable. The route is gated by `dashboard_secrets:delete` (NOT bundled into `:write` or `:admin`) AND requires `?confirm=<slug>` matching the target secret's slug. The CLI prompts interactively when stdin is a TTY; CI must pass `--confirm <slug>` explicitly. Mirrors `alter apps delete`. Soft-delete operations on grants (`grants revoke`) use the recoverable `:write` tier.
198
-
199
- **Managed secrets — credential intake:** `create` and `rotate` accept the credential value through three channels, in decreasing safety order: `--credential-value -` reads one line from stdin (preferred for CI piping), `--credential-value @/path/to/file` reads from a file, and `--credential-value <value>` accepts the value inline with a stderr warning about shell-history leakage. Multi-field templates (those whose backend Pydantic model requires more than a single primary credential string) take `--credentials @file.json` (a JSON object of string fields, takes precedence) or repeated `--credential-field key=value` flags.
200
-
201
- **Dashboard-only operations** (intentional, not scope gaps):
41
+ All commands accept `--output=json|table|jsonl` and `--fields a,b,c`. See [scripting](https://docs.alterauth.com/reference/cli/scripting) for exit codes and CI patterns, and [authentication](https://docs.alterauth.com/reference/cli/authentication) for token storage details.
202
42
 
203
- - PAT mint / revoke — a PAT cannot manage another PAT, including its own.
204
- - Org-wide key policy (`/organizations/current/key-policy`) — reading the response body is a security-posture fingerprint, so the route refuses PAT auth on both reads and writes.
205
- - Identity-provider configuration — affects every grant in the org; never settable by a single scripted call.
206
- - App-level policy *writes* / *deletes* — only `policy show-app` is exposed by the CLI; mutations remain dashboard-only until a CLI use case emerges.
43
+ ## License
207
44
 
208
- When the CLI doesn't model a route you need, drop down to `alter sdk-passthrough request <METHOD> <path>` — it forwards the request with the current PAT and prints the raw JSON.
45
+ MIT
package/dist/cli.js CHANGED
@@ -1,8 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // src/cli.ts
4
- import { Command as Command14 } from "commander";
5
-
6
3
  // src/exit-codes.ts
7
4
  var EXIT_ERROR = 1;
8
5
  var EXIT_USAGE = 2;
@@ -176,7 +173,7 @@ async function maybePrintUpdateBanner(currentVersion, argv2 = process.argv.slice
176
173
  // package.json
177
174
  var package_default = {
178
175
  name: "@alter-ai/cli",
179
- version: "0.3.0",
176
+ version: "0.3.1",
180
177
  description: "Command-line interface for the Alter Vault dev portal \u2014 scripted dashboard automation.",
181
178
  type: "module",
182
179
  bin: {
@@ -192,7 +189,9 @@ var package_default = {
192
189
  dev: "tsx src/cli.ts",
193
190
  test: "vitest run",
194
191
  "test:watch": "vitest",
195
- typecheck: "tsc --noEmit",
192
+ "docs:check": "tsx scripts/check-docs-drift.ts",
193
+ "docs:print": "tsx scripts/check-docs-drift.ts --print",
194
+ typecheck: "tsc --noEmit && tsc -p tsconfig.scripts.json",
196
195
  lint: "eslint src/ tests/ --ext .ts",
197
196
  format: "prettier --write 'src/**/*.ts' 'tests/**/*.ts'"
198
197
  },
@@ -224,6 +223,9 @@ var package_default = {
224
223
  }
225
224
  };
226
225
 
226
+ // src/program.ts
227
+ import { Command as Command14 } from "commander";
228
+
227
229
  // src/commands/agents.ts
228
230
  import { Command } from "commander";
229
231
 
@@ -6839,7 +6841,7 @@ var DEFAULT_BASE_URL = "https://backend.alterauth.com";
6839
6841
  var PAT_API_PREFIX = "/api/v1/dev-portal";
6840
6842
  var HTTP_ERROR_THRESHOLD = 400;
6841
6843
  var DEFAULT_TIMEOUT_MS = 3e4;
6842
- var CLI_VERSION = "0.3.0";
6844
+ var CLI_VERSION = "0.3.1";
6843
6845
  var USER_AGENT = buildUserAgent();
6844
6846
  function buildUserAgent() {
6845
6847
  let osTag = "";
@@ -7770,6 +7772,31 @@ var ManagedSecretsNamespace = class {
7770
7772
  );
7771
7773
  return expectDict(body, "managed_secrets.rotate", 200);
7772
7774
  }
7775
+ /**
7776
+ * Set the per-secret user → agent delegation policy. Requires
7777
+ * ``dashboard_secrets:write``. Controls whether a group-typed grant on
7778
+ * this secret may be delegated to an agent (``allow_group_source``) and
7779
+ * the per-delegation TTL ceiling (``max_delegation_ttl_days``).
7780
+ *
7781
+ * REPLACE semantics — the backend overwrites the whole policy object,
7782
+ * so the command always sends the full intended state (omitting
7783
+ * ``max_delegation_ttl_days`` lets the backend apply its 90-day default).
7784
+ */
7785
+ async setDelegationPolicy(appId, secretId, options) {
7786
+ const app = encodePathParam(appId, "appId");
7787
+ const secret = encodePathParam(secretId, "secretId");
7788
+ const payload = filterUndefined({
7789
+ allow_group_source: options.allow_group_source,
7790
+ max_delegation_ttl_days: options.max_delegation_ttl_days
7791
+ });
7792
+ const body = await this.#client._call(
7793
+ "PUT",
7794
+ `/apps/${app}/managed-secrets/${secret}/delegation-policy`,
7795
+ "managed_secrets.set_delegation_policy",
7796
+ { jsonBody: payload }
7797
+ );
7798
+ return expectDict(body, "managed_secrets.set_delegation_policy", 200);
7799
+ }
7773
7800
  /**
7774
7801
  * List grants on a managed secret. Requires ``dashboard_secrets:read``.
7775
7802
  *
@@ -10686,7 +10713,7 @@ function buildKeysCommand() {
10686
10713
  }
10687
10714
  );
10688
10715
  keys.command("rotate").description(
10689
- "Rotate a key (new plaintext returned ONCE; old key enters grace until revoke). Requires dashboard_keys:admin scope."
10716
+ "Rotate a key (new plaintext returned ONCE; old key enters grace until revoke). Requires dashboard_keys:write scope."
10690
10717
  ).option("--app <app-id>", "App ID. Falls back to ALTER_APP_ID env or .alter/config.yaml").requiredOption("--key <key-id>", "Key ID", parseUuidArgument("--key")).option(
10691
10718
  "--scopes <list>",
10692
10719
  "Optional new scope set (defaults to the key's current scopes)"
@@ -11695,7 +11722,14 @@ function buildManagedSecretsCommand() {
11695
11722
  ).option(
11696
11723
  "--injection-rule <@file.json>",
11697
11724
  "Path-prefixed JSON file containing the additional_injections array"
11698
- ).option("--label <label>", "Base-grant display label").option("--account-identifier <id>", "Optional account identifier metadata").option("--account-display-name <name>", "Optional account display name metadata").option("--output <format>", "Output format: json|table (default: json)", "json").action(
11725
+ ).option("--label <label>", "Base-grant display label").option("--account-identifier <id>", "Optional account identifier metadata").option("--account-display-name <name>", "Optional account display name metadata").option(
11726
+ "--allow-group-delegation",
11727
+ "Allow members of a group-typed grant on this secret to delegate it to an agent (default: off)"
11728
+ ).option(
11729
+ "--max-delegation-ttl-days <days>",
11730
+ "Cap on a single delegation's lifetime, in days (1..1825, default 90)",
11731
+ parseBoundedInt("--max-delegation-ttl-days", 1, 5 * 365)
11732
+ ).option("--output <format>", "Output format: json|table (default: json)", "json").action(
11699
11733
  async (options) => {
11700
11734
  const format = coerceOutputFormat(options.output);
11701
11735
  const appId = resolveAppIdOrExit(options.app);
@@ -11718,7 +11752,9 @@ function buildManagedSecretsCommand() {
11718
11752
  "injectionRule",
11719
11753
  "label",
11720
11754
  "accountIdentifier",
11721
- "accountDisplayName"
11755
+ "accountDisplayName",
11756
+ "allowGroupDelegation",
11757
+ "maxDelegationTtlDays"
11722
11758
  ].filter((k) => {
11723
11759
  if (k === "credentialType") return options.credentialType !== "bearer_token";
11724
11760
  return options[k] !== void 0;
@@ -11804,6 +11840,16 @@ function buildManagedSecretsCommand() {
11804
11840
  if (options.accountDisplayName !== void 0) {
11805
11841
  body.account_display_name = options.accountDisplayName;
11806
11842
  }
11843
+ if (options.allowGroupDelegation !== void 0 || options.maxDelegationTtlDays !== void 0) {
11844
+ const delegationPolicy = {};
11845
+ if (options.allowGroupDelegation !== void 0) {
11846
+ delegationPolicy.allow_group_source = options.allowGroupDelegation;
11847
+ }
11848
+ if (options.maxDelegationTtlDays !== void 0) {
11849
+ delegationPolicy.max_delegation_ttl_days = options.maxDelegationTtlDays;
11850
+ }
11851
+ body.delegation_policy = delegationPolicy;
11852
+ }
11807
11853
  await withClient(async (client) => {
11808
11854
  const row = await client.managedSecrets.create(
11809
11855
  resolveAppIdOrExit(options.app),
@@ -11813,6 +11859,29 @@ function buildManagedSecretsCommand() {
11813
11859
  });
11814
11860
  }
11815
11861
  );
11862
+ root.command("set-delegation-policy <secret-id>").description(
11863
+ "Set the user \u2192 agent delegation policy on a managed secret. REPLACES the current policy (omitting --allow-group-delegation turns group delegation OFF). Requires dashboard_secrets:write."
11864
+ ).option("--app <app-id>", "App ID. Falls back to ALTER_APP_ID env or .alter/config.yaml").option(
11865
+ "--allow-group-delegation",
11866
+ "Allow members of a group-typed grant on this secret to delegate it to an agent (default: off)"
11867
+ ).option(
11868
+ "--max-delegation-ttl-days <days>",
11869
+ "Cap on a single delegation's lifetime, in days (1..1825; omit for the 90-day default)",
11870
+ parseBoundedInt("--max-delegation-ttl-days", 1, 5 * 365)
11871
+ ).option("--output <format>", "Output format: json|table (default: json)", "json").action(
11872
+ async (rawSecretId, options) => {
11873
+ const format = coerceOutputFormat(options.output);
11874
+ const appId = resolveAppIdOrExit(options.app);
11875
+ const secretId = parseUuidArgument("<secret-id>")(rawSecretId);
11876
+ await withClient(async (client) => {
11877
+ const row = await client.managedSecrets.setDelegationPolicy(appId, secretId, {
11878
+ allow_group_source: options.allowGroupDelegation === true,
11879
+ max_delegation_ttl_days: options.maxDelegationTtlDays
11880
+ });
11881
+ emit(format, row);
11882
+ });
11883
+ }
11884
+ );
11816
11885
  root.command("delete <secret-id>").description(
11817
11886
  "Cascade-delete a managed secret. Requires dashboard_secrets:delete scope (NOT bundled into :write). Cascade-revokes grants + delegations + audit anchors and vault-deletes the credential."
11818
11887
  ).option("--app <app-id>", "App ID").option(
@@ -12565,6 +12634,46 @@ function buildSelfUpdateCommand() {
12565
12634
  });
12566
12635
  }
12567
12636
 
12637
+ // src/program.ts
12638
+ function buildProgram() {
12639
+ const program2 = new Command14();
12640
+ program2.name("alter").description("Alter Vault command-line interface").version(package_default.version);
12641
+ program2.option(
12642
+ "--fields <list>",
12643
+ "Comma-separated top-level keys to keep in JSON output (e.g. ``--fields id,name``). Inert with --output=table."
12644
+ );
12645
+ program2.hook("preAction", (thisCommand) => {
12646
+ setGlobalFields(void 0);
12647
+ const raw = thisCommand.opts().fields;
12648
+ if (raw !== void 0) {
12649
+ try {
12650
+ setGlobalFields(parseFieldsList(raw));
12651
+ } catch (e) {
12652
+ process.stderr.write(
12653
+ `alter: ${e instanceof Error ? e.message : String(e)}
12654
+ `
12655
+ );
12656
+ process.exit(EXIT_USAGE);
12657
+ }
12658
+ }
12659
+ });
12660
+ program2.addCommand(buildAuthCommand());
12661
+ program2.addCommand(buildAppsCommand());
12662
+ program2.addCommand(buildKeysCommand());
12663
+ program2.addCommand(buildAgentsCommand());
12664
+ program2.addCommand(buildProvidersCommand());
12665
+ program2.addCommand(buildManagedSecretsCommand());
12666
+ program2.addCommand(buildPolicyCommand());
12667
+ program2.addCommand(buildAuditCommand());
12668
+ program2.addCommand(buildPatsCommand());
12669
+ program2.addCommand(buildLinkCommand());
12670
+ program2.addCommand(buildUnlinkCommand());
12671
+ program2.addCommand(buildCompletionCommand());
12672
+ program2.addCommand(buildSdkPassthroughCommand());
12673
+ program2.addCommand(buildSelfUpdateCommand());
12674
+ return program2;
12675
+ }
12676
+
12568
12677
  // src/cli.ts
12569
12678
  var COMMANDER_USAGE_CODES = /* @__PURE__ */ new Set([
12570
12679
  "commander.missingArgument",
@@ -12628,41 +12737,7 @@ function rewriteLegacySelfUpdateVersionFlag(argv2) {
12628
12737
  }
12629
12738
  return rewritten;
12630
12739
  }
12631
- var program = new Command14();
12632
- program.name("alter").description("Alter Vault command-line interface").version(package_default.version);
12633
- program.option(
12634
- "--fields <list>",
12635
- "Comma-separated top-level keys to keep in JSON output (e.g. ``--fields id,name``). Inert with --output=table."
12636
- );
12637
- program.hook("preAction", (thisCommand) => {
12638
- setGlobalFields(void 0);
12639
- const raw = thisCommand.opts().fields;
12640
- if (raw !== void 0) {
12641
- try {
12642
- setGlobalFields(parseFieldsList(raw));
12643
- } catch (e) {
12644
- process.stderr.write(
12645
- `alter: ${e instanceof Error ? e.message : String(e)}
12646
- `
12647
- );
12648
- process.exit(EXIT_USAGE);
12649
- }
12650
- }
12651
- });
12652
- program.addCommand(buildAuthCommand());
12653
- program.addCommand(buildAppsCommand());
12654
- program.addCommand(buildKeysCommand());
12655
- program.addCommand(buildAgentsCommand());
12656
- program.addCommand(buildProvidersCommand());
12657
- program.addCommand(buildManagedSecretsCommand());
12658
- program.addCommand(buildPolicyCommand());
12659
- program.addCommand(buildAuditCommand());
12660
- program.addCommand(buildPatsCommand());
12661
- program.addCommand(buildLinkCommand());
12662
- program.addCommand(buildUnlinkCommand());
12663
- program.addCommand(buildCompletionCommand());
12664
- program.addCommand(buildSdkPassthroughCommand());
12665
- program.addCommand(buildSelfUpdateCommand());
12740
+ var program = buildProgram();
12666
12741
  applyExitOverride(program);
12667
12742
  var argv = rewriteLegacySelfUpdateVersionFlag(process.argv);
12668
12743
  async function main() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alter-ai/cli",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Command-line interface for the Alter Vault dev portal — scripted dashboard automation.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,7 +16,9 @@
16
16
  "dev": "tsx src/cli.ts",
17
17
  "test": "vitest run",
18
18
  "test:watch": "vitest",
19
- "typecheck": "tsc --noEmit",
19
+ "docs:check": "tsx scripts/check-docs-drift.ts",
20
+ "docs:print": "tsx scripts/check-docs-drift.ts --print",
21
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.scripts.json",
20
22
  "lint": "eslint src/ tests/ --ext .ts",
21
23
  "format": "prettier --write 'src/**/*.ts' 'tests/**/*.ts'"
22
24
  },