@ariestools/cli 0.1.20 → 0.1.22

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
@@ -1,6 +1,6 @@
1
1
  # @ariestools/cli
2
2
 
3
- Aries Tools CLI — a suite by Arie Trouw for AI-client tooling, sandboxed command execution, XL1 datalake provisioning, content hashing (strict + fuzzy + perceptual), XL1 wallet management, payload witnessing, and XYO protocol utilities.
3
+ Aries Tools CLI — a suite by Arie Trouw for AI-client tooling, XL1 datalake provisioning, content hashing (strict + fuzzy + perceptual), XL1 wallet management, payload witnessing, and XYO protocol utilities.
4
4
 
5
5
  ## Installation
6
6
 
@@ -15,7 +15,8 @@ pnpm add -g @ariestools/cli
15
15
  ```sh
16
16
  aries --help
17
17
  aries info
18
- aries hash --algorithm pdq ./photo.jpg
18
+ aries secrets status
19
+ ariesi hash --algorithm pdq ./photo.jpg
19
20
  ariesi plex libraries
20
21
  ariesi gate pair ticker BTC_USDT
21
22
  aries wallet create
@@ -33,9 +34,9 @@ private monorepo packages (`aries-datalake-plane`, etc.) installed.
33
34
  export ARIES_HOME=/tmp/aries-test-$$
34
35
 
35
36
  # Free ports by default (or pass --control-port / --plane-port)
36
- aries datalake dev up
37
+ aries datalake up
37
38
  aries datalake list
38
- aries datalake dev down
39
+ aries datalake down
39
40
  ```
40
41
 
41
42
  ### Programmatic client (no shell-out per request)
@@ -46,7 +47,7 @@ import {
46
47
  RestPayloadsClient,
47
48
  } from '@ariestools/cli/datalake'
48
49
 
49
- // After `aries datalake dev up` (or with baseUrl + authToken options)
50
+ // After `aries datalake up` (or with baseUrl + authToken options)
50
51
  const control = createDatalakeClient()
51
52
  const lakes = await control.list()
52
53
  // …
@@ -57,18 +58,22 @@ Private workspace packages stay private; runtime daemons ship under
57
58
 
58
59
  ## Top-level commands
59
60
 
61
+ The reference includes public `aries` commands and internal `ariesi` commands.
62
+ Internal commands require the private CLI build and an internal license tier;
63
+ the public installation cannot run them.
64
+
60
65
  ```text
61
66
  aries ai AI client tools
62
- aries bank Manage bank witness settings
67
+ ariesi bank Manage bank witness settings
63
68
  aries chain Run a local published-chain S3/REST server
64
- aries clamp Run commands inside a permission-controlled sandbox
65
69
  aries datalake Provision and manage on-demand XL1 datalakes
66
70
  ariesi gate Query the Gate exchange API (internal build)
67
- aries hash [file] Generate a hash (sha256, xyo, fuzzy, perceptual)
71
+ ariesi hash [file] Generate a hash (sha256, xyo, fuzzy, perceptual)
68
72
  aries info Display version and environment info
69
- aries npmjs Inspect and lint npmjs org packages
70
- aries pentair Manage Pentair ScreenLogic systems
73
+ ariesi npmjs Inspect and lint npmjs org packages
74
+ ariesi pentair Manage Pentair ScreenLogic systems
71
75
  ariesi plex Inspect and manage Plex Media Server (internal build)
76
+ aries secrets Secrets foundation, static AI instructions, and the human-only vault path
72
77
  aries wallet XL1 wallet — seed phrases, accounts, transactions, contacts
73
78
  aries witness Observe data and produce XYO-compliant payloads
74
79
  aries xyo XYO protocol utilities
@@ -81,11 +86,561 @@ Available on every command:
81
86
  | Option | Description |
82
87
  |---|---|
83
88
  | `-v, --verbose` | Enable verbose output |
89
+ | `--help-ai` | Print static AI-oriented help for a registered command path |
84
90
  | `--version` | Show version number |
85
91
  | `--help` | Show help |
86
92
 
87
93
  ---
88
94
 
95
+ ## `aries secrets` — Secrets foundation and the human-only vault path
96
+
97
+ The current implementation provides versioned, static discovery and status,
98
+ the read-only inventory listing, local bastion profile and provider
99
+ configuration, and eight human-only commands, `init`, `create`, `reveal`,
100
+ `set`, `generate`, `delete`, `list`, and `describe`, each documented in the
101
+ next sections:
102
+
103
+ ```sh
104
+ aries secrets status
105
+ aries secrets status --json
106
+ aries secrets --help-ai
107
+ aries secrets --help-ai --json
108
+ aries secrets init # human-only; no --json form
109
+ aries secrets create --name "Deploy token" --input-fd 3 3<file # human-only; value from fd 3, else the prompt
110
+ aries secrets reveal --secret-id sec_… # human-only; the value, once, to the terminal
111
+ aries secrets set --secret-id sec_… --expected-version <v> --input-fd 3 3<file # human-only; compare-and-swap replace
112
+ aries secrets generate --name "Signing key" --kind random-bytes --length 64 # human-only; drawn in-process, never printed
113
+ aries secrets delete --secret-id sec_… --expected-version <v> # human-only; compare-and-swap delete, not recoverable
114
+ aries secrets list # human-only; metadata only
115
+ aries secrets describe --secret-id sec_… # human-only; metadata only
116
+ ```
117
+
118
+ `status` reports the implementation phase (`human-only-storage`) plus three
119
+ live observations: `bastionConfigured` is true when the bastion profile store
120
+ holds at least one profile and `data.bastionStore` names the store path and
121
+ its state (`configured`, `empty`, or `unreadable` — a refused or corrupt store
122
+ is reported, never thrown); `data.providers` carries the negotiated state of
123
+ every provider entry on the selected profile; and `data.humanOnlyPath` states
124
+ whether the human-only path is available on this platform. `data.state` is
125
+ `not-initialized` until a vault exists on the selected profile and
126
+ `human-only-storage` once one does. There is no `initialized` state and no
127
+ authenticated operator: `init` performs no operator or recovery bootstrap, so
128
+ the realm stays provisional and nothing accepts a grant.
129
+
130
+ `aries --help-ai [--json]` discovers registered AI-help subtrees. AI help is
131
+ embedded package content and runs before `.env`, settings, licensing, provider,
132
+ or broker initialization. Its manifest marks future commands as `planned`, the
133
+ human-only commands as `human-only` (risk `human-only`, no `--json` option),
134
+ and carries a `humanOnlyPath` block: `brokered: false`, `humanAttested:
135
+ true`, the eight conditions every human-only command enforces, the platforms
136
+ on which they can be satisfied (`darwin`, `linux`), `unlock:
137
+ 'per-invocation'`, and `lease: 'not-available'`.
138
+
139
+ Agent-operational secret access is not implemented. This foundation cannot
140
+ connect to a bastion, create AI identities, authenticate with JWTs, manage
141
+ grants or approvals, or broker a secret to any program. The inventory listing
142
+ below observes presence metadata only: it initializes no provider and reads no
143
+ secret value. The bastion profile and provider commands record non-secret
144
+ configuration only: they contact no bastion and create no socket or vault.
145
+ The one path that touches a vault is human-only and unbrokered, described
146
+ under `aries secrets init`, `aries secrets create`, `aries secrets reveal`,
147
+ and the `set`, `generate`, `delete`, `list`, and `describe` sections below.
148
+
149
+ ### The refusal contract
150
+
151
+ All eight human-only commands — `init`, `create`, `reveal`, `set`,
152
+ `generate`, `delete`, `list`, and `describe` — refuse unless standard input
153
+ and standard output are both interactive terminals, the platform provides
154
+ `/dev/tty`, `stty`, and a process-ancestry probe (an allow-list, so `win32`
155
+ and any unknown platform are refused outright), no AI agent host is detected
156
+ through a documented environment signal or an agent binary in the process
157
+ ancestry (an ambiguous probe fails closed), and argv carries no
158
+ structured-output option (`--json`, `--no-json`) and no delivery option
159
+ (`--delivery`, `--destination`, `--output`, `--out`, `--out-file`, `--fd`,
160
+ `--env`, `--clipboard`, `--temp-file`, `--to`) anywhere — including before
161
+ the `secrets` word. A secret value still has two ways in, both of them input
162
+ channels rather than delivery: the masked prompt on the attached terminal,
163
+ and `--input-fd <fd>` on `create` and `set`, which reads the value from a
164
+ descriptor the caller opened. Every refusal is `HUMAN_CHANNEL_REQUIRED`
165
+ (exit 2) with a fixed message on standard error that never reflects an argv
166
+ value and nothing at all on standard output, and the two kinds differ in
167
+ what they record: a refusal by the channel gate — a pipe, a non-terminal, an
168
+ unsupported platform, a detected or ambiguous agent host — is recorded as a
169
+ human-attested `refused` audit event, while an argv refusal is caught by the
170
+ preflight before any store is opened and writes no audit event at all. The
171
+ gate conditions are evaluated in the order above, so a piped or captured
172
+ caller is refused before any `ps` probe runs. Passing the gate refuses the
173
+ non-interactive case; it is not proof of a human, because a pseudo-terminal
174
+ remains agent-drivable.
175
+
176
+ No MCP tool and no GUI reaches this path. The `aries mcp` servers register no
177
+ tool that names a secret and import nothing from the secrets action tree; the
178
+ Electron shell and the dashboard import nothing from that tree either — not
179
+ the human-only modules, not the barrel that re-exports them, not the provider
180
+ seam, and not the encrypted-file vault package — and neither declares
181
+ `@ariestools/cli-lib` as a dependency (the dashboard reads only
182
+ `secrets inventory list --json` by running the packed CLI, which reads no
183
+ value). The vault package itself is not a GUI or IPC API: the only consumers
184
+ of its unlock, create, re-key, and record primitives are the human-only
185
+ command modules that handle plaintext and the provider seam they load it
186
+ through. There is no socket, no daemon, and no lease — a command unlocks the
187
+ vault for that invocation and locks it again before it returns.
188
+
189
+ ### Storage layout under `~/.aries/secrets`
190
+
191
+ `ARIES_HOME` relocates `~/.aries` in full. Everything the CLI writes below it
192
+ is created `0600` inside `0700` directories. The three stores it owns —
193
+ `config/bastions.json`, `realms/<realmId>/secrets-index.json`, and
194
+ `audit/human-attested.jsonl` — are also checked when they are read: a group
195
+ or other permission bit, a foreign owner, a symlink, a non-regular file, or
196
+ an oversized one fails the command and names the `chmod` or `chown` fix
197
+ rather than repairing it. The vault files are written the same way and are
198
+ refused on a symlink, a non-regular file, or an oversized one, and their
199
+ directory is created `0700`. Two rows below are operator-authored and are
200
+ never written, moved, or permission-checked by the CLI: `inventory.json`,
201
+ read as declarations only, and `realms/<realmId>/denies.json`, which refuses
202
+ every secret-touching operation in this milestone by existing at all.
203
+
204
+ | Path | Contents |
205
+ | --- | --- |
206
+ | `config/bastions.json` | The bastion profile envelope: realms, bastions, endpoints, provider entries, and the active selection. Non-secret. `ARIES_SECRETS_BASTIONS` redirects it (absolute path). |
207
+ | `vaults/<providerId>/vault.json` | The encrypted-file vault header, format v1: plaintext parameters only — the vault ID, PBKDF2-SHA256 at 100,000 iterations, AES-256-GCM with a 12-byte IV, and the creation time. |
208
+ | `vaults/<providerId>/vault-password.json` | The password verifier: the PBKDF2 salt and a SHA-256 hash of the derived key. Never the password. |
209
+ | `vaults/<providerId>/records.json` | Every secret, as ciphertext with its authenticated metadata. The display name lives inside the encrypted body. |
210
+ | `realms/<realmId>/secrets-index.json` | The routing index: secret ID → `{ providerId, digest }`, and nothing else. |
211
+ | `realms/<realmId>/denies.json` | Deny records, consulted before every secret-touching operation. Nothing in this milestone writes it. |
212
+ | `audit/human-attested.jsonl` | The hash-chained, append-only human-attested audit log: one event per line, no secret value and no grant evidence. |
213
+ | `inventory.json` | The machine-wide managed-secret declarations, written by the operator and only read here. Presence metadata only. `ARIES_SECRETS_INVENTORY` redirects it. |
214
+
215
+ `broker.sock` is recorded on a local profile as the endpoint the future broker
216
+ would use; no socket is created, bound, or connected to in this build.
217
+
218
+ ## `aries secrets inventory` — Managed secrets visibility
219
+
220
+ ```sh
221
+ aries secrets inventory list
222
+ aries secrets inventory list --repo owner/myapp
223
+ aries secrets inventory list --source env --env-file ./deploy/.env --json
224
+ ```
225
+
226
+ `secrets` is always registered at the free tier, so every example works
227
+ unchanged in the internal `ariesi` build.
228
+
229
+ Managed secrets are declared in one schema at two scopes, each a JSON file
230
+ with a root-level `inventory` list:
231
+
232
+ - `~/.aries/secrets/inventory.json` (override with `ARIES_SECRETS_INVENTORY`;
233
+ `ARIES_HOME` relocates `~/.aries`) — machine-wide entries, each optionally
234
+ naming its `repos`. The legacy `~/.config/aries/secrets.json` is still read
235
+ when the new file is absent, with a notice on stderr and
236
+ `data.legacyInventoryPath` under `--json`; move it to the new path.
237
+ - `<repo>/.config/aries/secrets.json` — entries needed by that repository's
238
+ agents. These files are safe to commit: the closed entry shape
239
+ (`service`, `account`, optional `label`, `env`, and — global only — `repos`)
240
+ structurally rejects value-bearing fields, so a committed file can never
241
+ become a secret store.
242
+
243
+ ```json
244
+ {
245
+ "version": 1,
246
+ "inventory": [
247
+ {
248
+ "account": "ci-token",
249
+ "env": "GITHUB_TOKEN",
250
+ "label": "GitHub token",
251
+ "service": "github"
252
+ }
253
+ ]
254
+ }
255
+ ```
256
+
257
+ Presence is metadata only and never returns a value: on macOS the default
258
+ `auto` source probes the Keychain by `(service, account)` existence without
259
+ requesting the password; elsewhere (or with `--source env`) presence means the
260
+ mapped `env` variable is set and non-empty after `.env` loading. Repositories
261
+ are discovered below `ARIES_CODE_ROOT` (default `~/GitHub`). The `--json`
262
+ envelope follows the secrets result schema and contains identifiers and
263
+ presence booleans only — suitable as the dashboard panel's data source.
264
+
265
+ ## `aries secrets bastion` — Bastion profiles
266
+
267
+ ```sh
268
+ aries secrets bastion add --name "Laptop bastion"
269
+ aries secrets bastion list
270
+ aries secrets bastion show # active or sole profile
271
+ aries secrets bastion show "Laptop bastion" # by display name
272
+ aries secrets bastion show --bastion bpf_… # by profile ID
273
+ aries secrets bastion use "Laptop bastion"
274
+ aries secrets bastion remove "Laptop bastion"
275
+ aries secrets bastion list --json
276
+ ```
277
+
278
+ A bastion profile is a closed, versioned, non-secret record naming a realm,
279
+ a bastion, its endpoint, and its providers; it holds no password, token, or
280
+ key material. Profiles live in one envelope at
281
+ `~/.aries/secrets/config/bastions.json` (`ARIES_HOME` relocates `~/.aries`;
282
+ `ARIES_SECRETS_BASTIONS` redirects the file for tests and must be absolute),
283
+ written `0600` inside a `0700` directory. A file or directory with group or
284
+ other permission bits, a foreign owner, a file over 256 KiB, or an unparseable
285
+ file fails every command with `BASTION_CONFIGURATION_INVALID` (exit 9), naming
286
+ only the path and the fix. A redirected store is disclosed on stderr in human
287
+ output and as `data.bastionStore` under `--json`.
288
+
289
+ - `add --name <displayName> [--kind local-ipc]` mints the profile, realm, and
290
+ bastion identifiers, derives the audience, and records the inert socket path
291
+ `<secretsRoot>/broker.sock` without touching the filesystem. The first
292
+ profile written to an empty store becomes the active selection. Every new
293
+ profile starts with one `encrypted-file` provider entry (`encrypted-local`,
294
+ vault directory `<secretsRoot>/vaults/encrypted-local`); no vault is created.
295
+ `--kind remote` is refused with `CAPABILITY_UNSUPPORTED` until Phase 9. A
296
+ display name that collides with an existing profile ID or display name is an
297
+ error, never an overwrite.
298
+ - `list` reads the store only: it never contacts a bastion or starts a broker,
299
+ succeeds on a missing store with an empty table, and marks a `remote`
300
+ profile `unusable in this build`.
301
+ - `show [<profile>] [--bastion <profile>]` resolves by profile ID first, then
302
+ display name, else the active profile, else the sole profile; the result
303
+ names which namespace matched. With nothing selectable it fails with
304
+ `BASTION_NOT_SELECTED`. The endpoint is labeled `not used in this build`.
305
+ - `use <profile>` writes `activeProfileId` and nothing else. Selection is not
306
+ authorization; a `remote` profile is refused.
307
+ - `remove <profile>` deletes the local record and clears an active selection
308
+ that pointed at it. It revokes nothing: grants, delegations, and enrollments
309
+ at the removed realm remain in force and must be revoked at the bastion
310
+ separately, which the result states in both output forms.
311
+
312
+ `add`, `use`, and `remove` are mutating: they print the store path on stderr
313
+ for every write, and an agent must not run them without explicit operator
314
+ instruction (the AI-help manifest carries that rule). Every command takes
315
+ `--json`; the envelope follows the secrets result schema and typed failures
316
+ map to the secrets exit codes.
317
+
318
+ ---
319
+
320
+ ## `aries secrets provider` — Provider entries
321
+
322
+ ```sh
323
+ aries secrets provider list
324
+ aries secrets provider show # active or sole provider
325
+ aries secrets provider show backup # by provider ID
326
+ aries secrets provider add --id backup --kind encrypted-file
327
+ aries secrets provider add --id backup --kind encrypted-file --vault-path /srv/vaults/backup
328
+ aries secrets provider configure backup --vault-path /srv/vaults/backup
329
+ aries secrets provider use backup
330
+ aries secrets provider remove backup
331
+ aries secrets provider test # active or sole provider
332
+ aries secrets provider test backup --json
333
+ aries secrets provider list --bastion "Laptop bastion" --json
334
+ ```
335
+
336
+ A provider entry is the non-secret placement record on a bastion profile:
337
+ `providerId`, `kind`, and `configurationRef` (for `encrypted-file`, the
338
+ absolute vault directory, default `<secretsRoot>/vaults/<providerId>`). It
339
+ holds no password and no key material; the vault's own files hold those.
340
+ Every command takes the inherited `--bastion <profile>` (profile ID first,
341
+ then display name; omitted means the active profile, else the sole profile,
342
+ else `BASTION_NOT_SELECTED`) and `--json`, discloses the store as
343
+ `data.bastionStore`, and refuses a `remote` profile with
344
+ `CAPABILITY_UNSUPPORTED`.
345
+
346
+ - `add --id <providerId> --kind encrypted-file [--vault-path <dir>]` appends
347
+ one entry. The kind union is closed at the option table and again at the
348
+ record parser, so `memory` and `macos-keychain` are refused by both. A
349
+ duplicate ID is an error, never an overwrite. No vault and no directory is
350
+ created: initialization needs a password and is human-only.
351
+ - `list` prints every entry with `initialized` — whether `vault.json` exists
352
+ at `configurationRef`, a stat only, with no unlock and no header parse —
353
+ and marks the active provider.
354
+ - `show [<providerId>]` resolves by ID, else the active provider (set by
355
+ `use`), else the sole provider, and carries two fixed notes: unlock is
356
+ per-invocation with no lease, and compare-and-swap is cooperative (it holds
357
+ only among writers honoring the vault store lock).
358
+ - `configure <providerId> --vault-path <dir>` replaces `configurationRef`
359
+ only; the kind is immutable and nothing is created, moved, or unlocked.
360
+ - `remove <providerId>` deletes the entry and clears an active provider
361
+ selection that pointed at it. The vault directory is not deleted, which the
362
+ result states in both output forms. The last provider of a profile cannot
363
+ be removed; remove the profile instead.
364
+ - `use <providerId>` records `activeProviderId`, which satisfies `--provider`
365
+ on management commands only. Placement on `create` and `generate` still
366
+ requires `--provider` whenever the profile lists more than one provider;
367
+ there is no default provider.
368
+ - `test [<providerId>]` resolves like `show` and reports the adapter's
369
+ declared capabilities, `maximumSecretBytes`, a bounded health check, the
370
+ per-invocation unlock mode, and the cooperative compare-and-swap caveat.
371
+ It never prompts, unlocks, lists, or reads: the adapter is built around a
372
+ locked placeholder session, and a locked vault — the designed steady state
373
+ — succeeds with health `locked` and exit 0. Only an unavailable provider
374
+ fails (`PROVIDER_UNAVAILABLE`, exit 7): not initialized (`next.command`
375
+ names the human-only `init`), a corrupt header (reported with a redacted
376
+ diagnostic, never a path), or a health check that misses its deadline
377
+ (retryable). `status` runs the same negotiation for every provider entry
378
+ on the selected profile and reports `providerCount` and per-provider rows
379
+ under the same ok-when-locked rule; it still succeeds when every provider
380
+ is unavailable.
381
+
382
+ `--vault-path` must be absolute and is refused when equal to or inside the
383
+ resolved XL1 wallet root, or inside the directory named by `XL1_WALLET_HOME`
384
+ or `ARIES_WALLET_HOME` when either is set, so a vault never shares a
385
+ directory with a wallet store; the refusal names the rule, never the path.
386
+ `add`, `configure`, `remove`, and `use` are mutating: they print the store
387
+ path on stderr for every write, and an agent must not run them without
388
+ explicit operator instruction.
389
+
390
+ ## `aries secrets init` — Human-only vault creation
391
+
392
+ ```sh
393
+ aries secrets init # mints "Local bastion" when no profile exists
394
+ aries secrets init --name "Laptop bastion" # display name for the minted profile
395
+ aries secrets init --bastion "Laptop bastion" # an existing profile
396
+ aries secrets init --provider-id backup # another entry; added to the profile when absent
397
+ ```
398
+
399
+ `init` is the first human-only, unbrokered command. From an interactive
400
+ terminal it resolves the bastion profile (or mints a local one when none
401
+ exists), ensures an `encrypted-file` provider entry for `--provider-id`
402
+ (default `encrypted-local`, vault directory
403
+ `<secretsRoot>/vaults/<providerId>`), refuses an existing vault at that
404
+ entry's location (`VERSION_CONFLICT`, exit 8; the refusal names the rule,
405
+ never the path), prompts for the vault password twice on `/dev/tty` with
406
+ the vault's 12-character minimum, creates the vault, opens it once to confirm
407
+ it answers under that password, locks it again, and prints the profile,
408
+ provider, and vault summary. Unlock is per-invocation: no lease, session
409
+ file, or key survives the command. The password is read from the terminal
410
+ alone — never from an environment variable or a command-line argument.
411
+
412
+ `init` initializes one vault and one local profile only. It performs no
413
+ operator or recovery bootstrap: the realm stays provisional in the plan's
414
+ sense, nothing accepts a grant, and neither `status` nor `--help-ai`
415
+ describes the operator as authenticated.
416
+
417
+ Every human-only command enforces these rules, each covered by a test:
418
+
419
+ - standard input and standard output must both be interactive terminals; a
420
+ piped, redirected, or captured channel fails with `HUMAN_CHANNEL_REQUIRED`
421
+ (exit 2) on stderr and writes nothing to stdout;
422
+ - a detected AI agent host (Claude Code, Codex, Cursor, Aider, and the other
423
+ documented signals, or an agent binary in the process ancestry) is refused,
424
+ and an ambiguous probe fails closed;
425
+ - there is no `--json` and no delivery option; `--json`, `--no-json`,
426
+ `--delivery`, `--destination`, `--output`, `--fd`, `--env`, `--clipboard`,
427
+ `--temp-file`, or `--to` anywhere in argv — including before the `secrets`
428
+ word — is refused with a fixed message before yargs runs, and the refused
429
+ value is never reflected;
430
+ - the command is not mirrored as an MCP tool and is reachable over no IPC,
431
+ socket, or remote transport;
432
+ - every run, refusal, and failure appends a human-attested, unbrokered event
433
+ to `<secretsRoot>/audit/human-attested.jsonl`; an event that cannot be
434
+ written refuses the operation (`AUDIT_UNAVAILABLE`);
435
+ - the realm's deny records are consulted before a secret-touching operation
436
+ (`init` alone is exempt, because no realm exists before it mints one);
437
+ `create`, `reveal`, `set`, `generate`, `delete`, `list`, and `describe`
438
+ refuse with `POLICY_INVALID` (exit 5) when the deny set cannot be read,
439
+ which in this milestone includes any existing
440
+ `<secretsRoot>/realms/<realmId>/denies.json`, since nothing writes one yet;
441
+ - on `win32` every human-only command fails with `HUMAN_CHANNEL_REQUIRED` and
442
+ reason `platform-unsupported`, which `status` and the manifest state.
443
+
444
+ Agents must not invoke a human-only command, wrap it, or treat it as agent
445
+ access: it identifies no principal, evaluates no grant, and confers nothing
446
+ on any agent principal.
447
+
448
+ ## `aries secrets create` — Human-only secret storage
449
+
450
+ ```sh
451
+ aries secrets create --name "Deploy token" --input-fd 3 3<./token.txt # value from descriptor 3
452
+ aries secrets create --name "Deploy token" # masked prompt, typed twice
453
+ aries secrets create --name "API key" --provider backup # placement on a named entry
454
+ ```
455
+
456
+ `create` stores one secret in the operator's own vault. From an interactive
457
+ terminal it resolves the bastion profile (`--bastion`, else the active
458
+ profile, else the sole profile — it never mints one), places the secret on
459
+ `--provider` (required when the profile lists more than one provider,
460
+ implied when it lists exactly one; the active provider never satisfies
461
+ placement), consults the realm's deny records, appends the `intent` audit
462
+ event, prompts for the vault password on `/dev/tty`, collects the value,
463
+ writes the record, indexes it, locks the vault, and prints the secret ID
464
+ and version — never the value.
465
+
466
+ The value comes from exactly one of two sources. `--input-fd <n>` reads a
467
+ trusted producer's descriptor, which must be numbered 3 or higher, open,
468
+ and not a terminal: standard input is never accepted, because it may be
469
+ model-composed or captured in a transcript. The read is bounded at 65536
470
+ bytes and exactly one trailing newline is removed. Without `--input-fd`
471
+ the value is typed on the terminal, masked, and confirmed. In both cases
472
+ the record is stored as `text/plain`, and the descriptor is read before
473
+ the password prompt so a closed or reserved descriptor is refused early.
474
+ The display name (`--name`, at most 256 bytes, no control characters) is
475
+ stored inside the encrypted record body, where the vault's associated data
476
+ authenticates it.
477
+
478
+ The write spans two stores under two leases and is not atomic, so its order
479
+ is fixed: the provider record is created first, then the index entry. If
480
+ the index write fails, the record is deleted again under the same session
481
+ and the command reports the index failure with provider effect none; if
482
+ that deletion cannot be proven, the command reports
483
+ `PROVIDER_OUTCOME_UNKNOWN` (exit 7) naming the record's opaque ID, which
484
+ may then remain in the vault unindexed until it is reconciled.
485
+
486
+ ### The secret index
487
+
488
+ Each realm has one routing index at
489
+ `<secretsRoot>/realms/<realmId>/secrets-index.json`, written `0600` inside
490
+ a `0700` realm directory through the same journaled, atomic store that
491
+ holds the bastion profiles. It maps a secret ID to `{ providerId, digest }`
492
+ and nothing else: no display name, content type, byte length, or timestamp
493
+ ever lands in it, so the file discloses routing alone. The `digest` is
494
+ SHA-256 over the canonical JSON of `{ secretId, providerId, opaqueId }`,
495
+ computed at create and re-verified on every resolve; `opaqueId` equals the
496
+ secret ID by construction, because the human path mints a canonical
497
+ 22-character `sec_` token that the encrypted-file vault stores verbatim.
498
+ The digest is unkeyed: it detects an accidental edit or a truncated write,
499
+ and nothing more — any party with write access to the file can recompute
500
+ it. Phase 3 replaces it with a broker-held keyed MAC. Do not delete the
501
+ index: every secret it routes becomes unreachable by ID.
502
+
503
+ ## `aries secrets reveal` — Human-only reveal to the terminal
504
+
505
+ ```sh
506
+ aries secrets reveal --secret-id sec_… # the value, once, then a newline
507
+ aries secrets reveal --secret-id sec_… --bastion "Laptop" # an explicit profile
508
+ ```
509
+
510
+ `reveal` resolves `--secret-id` through the realm's secret index alone. A
511
+ missing entry is `INVALID_ARGUMENT` (exit 2); an entry naming a provider
512
+ the profile no longer lists, or one whose digest no longer verifies, is
513
+ `BASTION_CONFIGURATION_INVALID` (exit 9) — each fails closed, and no
514
+ provider is ever opened or searched to find a matching record. `--provider`
515
+ is refused with `INVALID_ARGUMENT` for the same reason: the index is the
516
+ only routing input, so a reference can never be redirected from the
517
+ command line. The command then consults the deny records, appends the
518
+ `intent` event, prompts for the vault password, reads the record, locks the
519
+ vault, appends the `completed` event, and writes the value exactly once to
520
+ standard output followed by one newline — nothing else is written there.
521
+ There is no other delivery: no destination, file, descriptor, environment,
522
+ clipboard, or temporary file, and no structured output. The value never
523
+ appears in an audit line or on standard error.
524
+
525
+ ## `aries secrets set` — Human-only compare-and-swap replace
526
+
527
+ ```sh
528
+ aries secrets set --secret-id sec_… --expected-version <v> --input-fd 3 3<./new.txt # value from descriptor 3
529
+ aries secrets set --secret-id sec_… --expected-version <v> # masked prompt, typed twice
530
+ ```
531
+
532
+ `set` replaces one secret's value in the operator's own vault. It resolves
533
+ `--secret-id` through the realm's secret index alone, exactly as `reveal`
534
+ does (`--provider` is refused with `INVALID_ARGUMENT`), consults the deny
535
+ records, appends the `intent` event, prompts for the vault password, collects
536
+ the new value from `--input-fd` (3 or higher; read before the password prompt)
537
+ or the masked terminal prompt with confirmation, and performs one
538
+ compare-and-swap replace: `--expected-version` must equal the record's
539
+ current version token exactly as the last `create`, `generate`, `set`, or
540
+ `describe` printed it, or the command fails with `VERSION_CONFLICT` (exit 8)
541
+ and nothing changes. The display name and content type are preserved from
542
+ the record. The reference does not change, so the index is untouched; the
543
+ command prints the new version and the superseded one, never the value. A
544
+ replace whose effect the provider cannot prove is `PROVIDER_OUTCOME_UNKNOWN`
545
+ (exit 7), naming the record and stating that the index still routes it.
546
+
547
+ ## `aries secrets generate` — Human-only in-process generation
548
+
549
+ ```sh
550
+ aries secrets generate --name "Signing key" --kind random-bytes --length 64
551
+ aries secrets generate --name "Webhook token" --kind base64url-token
552
+ aries secrets generate --name "Database password" --kind password --length 24 --provider backup
553
+ ```
554
+
555
+ `generate` draws a value in the operator's own process from Web Crypto and
556
+ stores it exactly as `create` would: placement on `--provider` (or the sole
557
+ provider), the deny consultation, the `intent` event, the password prompt,
558
+ the provider record first with the display name inside the encrypted body,
559
+ then the routing entry in the realm's index, with the same rollback when the
560
+ index write fails. It prints the secret ID, kind, size, and version — the
561
+ value is never printed, logged, audited, or returned, and exists only in the
562
+ record's ciphertext; read it back with `reveal`. `--kind` is a closed list
563
+ and `--length` counts the kind's unit inside an inclusive range:
564
+
565
+ | Kind | Stored as | `--length` | Default | Range |
566
+ | --- | --- | --- | --- | --- |
567
+ | `random-bytes` | `application/octet-stream`, raw bytes | bytes | 32 | 8–1024 |
568
+ | `base64url-token` | `text/plain` | characters | 32 | 8–512 |
569
+ | `password` | `text/plain` | characters | 32 | 8–256 |
570
+
571
+ `password` uses a fixed 70-symbol printable alphabet with the ambiguous
572
+ `0 O 1 l I` removed and no space, quote, backslash, `$`, backtick, or
573
+ redirection character; `base64url-token` uses the 64 base64url symbols. Both
574
+ are uniform: a byte that would bias the draw is rejected, never reduced. An
575
+ unlisted kind or an out-of-range length is `INVALID_ARGUMENT` (exit 2) before
576
+ anything runs.
577
+
578
+ ## `aries secrets delete` — Human-only compare-and-swap delete
579
+
580
+ ```sh
581
+ aries secrets delete --secret-id sec_… --expected-version <v>
582
+ ```
583
+
584
+ `delete` resolves `--secret-id` through the index alone, consults the deny
585
+ records, appends the `intent` event, prompts for the vault password, and
586
+ deletes the record under the `--expected-version` guard; a stale guard is
587
+ `VERSION_CONFLICT` (exit 8) and nothing changes. It then removes the routing
588
+ entry from the realm's index: the tombstone is the removal itself, so the ID
589
+ no longer resolves through any command and a later `describe` or `reveal`
590
+ stops at the index with `INVALID_ARGUMENT`. **The vault record is gone and is
591
+ not recoverable through aries**: the encrypted-file provider discards the
592
+ ciphertext and keeps no tombstone, which the receipt reports as
593
+ `unrecoverable`. The audit line records the secret ID and the fresh tombstone
594
+ version only. If the record is deleted but the index cannot be updated, the
595
+ command reports `PROVIDER_OUTCOME_UNKNOWN` (exit 7) naming both facts — the
596
+ record is gone, the index may still route the ID. Until you reconcile,
597
+ `describe` on that ID fails either at the vault with `RESOURCE_UNAVAILABLE`,
598
+ with `list` showing it as `missing`, or at the index with `INVALID_ARGUMENT`
599
+ if the entry did go after all.
600
+
601
+ ## `aries secrets list` — Human-only metadata listing
602
+
603
+ ```sh
604
+ aries secrets list # the active provider, or the sole provider
605
+ aries secrets list --provider backup # one provider entry
606
+ ```
607
+
608
+ `list` resolves the provider entry (`--provider`, else the active provider,
609
+ else the sole one), consults the deny records for the realm's catalog,
610
+ prompts for the vault password, and prints metadata alone: for every index
611
+ entry routed to that provider, the secret ID, version, incarnation, content
612
+ type, byte length, display name, and created and updated timestamps, read
613
+ from the vault's own description; an entry whose record the provider no
614
+ longer holds is shown as `missing`, one whose index digest does not verify
615
+ as `integrity-failed` (the vault is not consulted for it), and one whose
616
+ record the vault holds but will not describe as `undescribable` with the
617
+ failure code — a single unreadable record never hides the rest of the
618
+ catalog. Entries routed to other providers on the profile are counted, not
619
+ listed. The
620
+ command also enumerates the provider's own records and reports every record
621
+ the index does not route to that provider as `unindexed`, with its opaque
622
+ ID, version, byte length, and timestamps — never its value or display name.
623
+ An unindexed record is reachable by no aries command until it is reconciled,
624
+ because the index is the only routing input. No value is ever printed.
625
+
626
+ ## `aries secrets describe` — Human-only metadata for one secret
627
+
628
+ ```sh
629
+ aries secrets describe --secret-id sec_…
630
+ ```
631
+
632
+ `describe` resolves `--secret-id` through the index alone (`--provider` is
633
+ refused), consults the deny records, prompts for the vault password, and
634
+ prints the record's current version, incarnation, created and updated
635
+ timestamps, content type, byte length, and display name — never the value,
636
+ which is decrypted only to measure it and wiped inside the library. A
637
+ record the vault does not hold is `RESOURCE_UNAVAILABLE` (exit 7); an ID the
638
+ index does not route is `INVALID_ARGUMENT` (exit 2) before any vault is
639
+ opened. The printed version is the `--expected-version` for the next `set`
640
+ or `delete`.
641
+
642
+ ---
643
+
89
644
  ## `aries chain` — Local published-chain server
90
645
 
91
646
  ```sh
@@ -120,17 +675,17 @@ CA file for another HTTPS S3-compatible endpoint.
120
675
 
121
676
  ---
122
677
 
123
- ## `aries bank` — Manage bank witness settings
678
+ ## `ariesi bank` — Manage bank witness settings
124
679
 
125
680
  ```sh
126
- aries bank capitalone config get
127
- aries bank capitalone config set base-url https://api-sandbox.capitalone.com
128
- aries bank capitalone config set token-url https://api-sandbox.capitalone.com/oauth2/token
129
- aries bank capitalone config set client-id "$CAPITALONE_CLIENT_ID"
130
- aries bank capitalone config set client-secret "$CAPITALONE_CLIENT_SECRET"
131
- aries bank capitalone config set accounts-path /accounts
132
- aries bank capitalone config set balances-path '/accounts/{accountId}/balances'
133
- aries bank capitalone config set transactions-path '/accounts/{accountId}/transactions'
681
+ ariesi bank capitalone config get
682
+ ariesi bank capitalone config set base-url https://api-sandbox.capitalone.com
683
+ ariesi bank capitalone config set token-url https://api-sandbox.capitalone.com/oauth2/token
684
+ ariesi bank capitalone config set client-id "$CAPITALONE_CLIENT_ID"
685
+ ariesi bank capitalone config set client-secret "$CAPITALONE_CLIENT_SECRET"
686
+ ariesi bank capitalone config set accounts-path /accounts
687
+ ariesi bank capitalone config set balances-path '/accounts/{accountId}/balances'
688
+ ariesi bank capitalone config set transactions-path '/accounts/{accountId}/transactions'
134
689
  ```
135
690
 
136
691
  Capital One config is stored in `~/.aries/bank/capitalone.json` with restricted
@@ -165,15 +720,15 @@ for one run.
165
720
 
166
721
  ---
167
722
 
168
- ## `aries pentair` — Manage Pentair ScreenLogic systems
723
+ ## `ariesi pentair` — Manage Pentair ScreenLogic systems
169
724
 
170
725
  ```sh
171
- aries pentair config get
172
- aries pentair config get address
173
- aries pentair config set address 192.0.2.10
174
- aries pentair config set port 80
175
- aries pentair config set system-name "Pentair ScreenLogic"
176
- aries pentair circuit runtime set --circuit-id 6 --hours 24 --on
726
+ ariesi pentair config get
727
+ ariesi pentair config get address
728
+ ariesi pentair config set address 192.0.2.10
729
+ ariesi pentair config set port 80
730
+ ariesi pentair config set system-name "Pentair ScreenLogic"
731
+ ariesi pentair circuit runtime set --circuit-id 6 --hours 24 --on
177
732
  ```
178
733
 
179
734
  Pentair config is stored in `~/.aries/pentair/config.json` and is used by the
@@ -194,7 +749,7 @@ Pentair witness and circuit commands. `ARIES_HOME` overrides the `~/.aries` root
194
749
 
195
750
  `config get` redacts `password`; pass `--show-secrets` to print it.
196
751
 
197
- ### `aries pentair circuit runtime set`
752
+ ### `ariesi pentair circuit runtime set`
198
753
 
199
754
  Set the ScreenLogic circuit egg timer. Runtime values are sent to ScreenLogic as
200
755
  minutes; `--hours 24` becomes `1440`.
@@ -351,14 +906,6 @@ Scan for installed AI clients.
351
906
  |---|---|---|
352
907
  | `--json` | `false` | Output as JSON |
353
908
 
354
- ### `aries ai sync`
355
-
356
- Sync AI config between Claude Code and Codex.
357
-
358
- | Option | Default | Description |
359
- |---|---|---|
360
- | `--from <claude\|agents>` | `claude` | Source to sync from (the authority) |
361
-
362
909
  ### `aries ai lint [path]`
363
910
 
364
911
  Check Claude Code and Codex AI configuration drift. The folder defaults to the current directory.
@@ -368,37 +915,18 @@ Check Claude Code and Codex AI configuration drift. The folder defaults to the c
368
915
  | `--scope <all\|project\|home>` | `all` | Check project config, shared/custom home config, or both |
369
916
  | `--json` | `false` | Output as JSON |
370
917
 
371
- ---
372
-
373
- ## `aries clamp` — Run commands inside a permission-controlled sandbox
918
+ ### `aries ai skills list [tool]`
374
919
 
375
- ```sh
376
- aries clamp run <command> [args..] # Run a command inside the clamp sandbox
377
- aries clamp policy list # List available clamp policies
378
- aries clamp policy show <name> # Show a clamp policy
379
- aries clamp policy init # Create a starter .aries-clamp.json
380
- ```
381
-
382
- ### Per-command flags
383
-
384
- #### `aries clamp run <command> [args..]`
385
- | Positional | | Description |
386
- |---|---|---|
387
- | `command` | required | Command to run inside the sandbox |
388
- | `args` | `[]` | Arguments for the command |
920
+ List installed skills discovered for Claude Code, Codex, and Cursor. The optional
921
+ `tool` positional accepts `claude`, `codex`, or `cursor`; omit it to inspect all
922
+ three. Cursor currently reports no skills. Detection and listing do not modify client configuration.
389
923
 
390
924
  | Option | Default | Description |
391
925
  |---|---|---|
392
- | `-p, --policy <path-or-name>` | | Policy file path or name |
393
- | `--audit` | `true` | Enable audit logging |
394
- | `--dry-run` | `false` | Show what would be sandboxed without running |
395
-
396
- #### `aries clamp policy show <name>`
397
- | Positional | | Description |
398
- |---|---|---|
399
- | `name` | required | Policy name or file path |
926
+ | `--json` | `false` | Output as JSON |
400
927
 
401
- `policy list` and `policy init` take no command-specific options.
928
+ AI lint also inspects shared/custom home plugin manifests and skill files for
929
+ drift without changing them.
402
930
 
403
931
  ---
404
932
 
@@ -544,14 +1072,17 @@ aries datalake audit purge # Delete rotated audit files older than --max-age-
544
1072
  ### Local development
545
1073
 
546
1074
  ```sh
547
- aries datalake dev up # Start the local control + data plane dev server
548
- aries datalake dev down # Stop it (clears credentials)
549
- aries datalake dev status # Report whether the local dev server is running and healthy
550
- aries datalake dev logs # Print recent dev server log output
551
- aries datalake dev reset # Stop the dev server and wipe all local state
1075
+ aries datalake up # Start the local control + data plane dev server
1076
+ aries datalake down # Stop it (clears credentials)
1077
+ aries datalake status # Report whether the local dev server is running and healthy
1078
+ aries datalake logs # Print recent dev server log output
1079
+ aries datalake reset # Stop the dev server and wipe all local state
552
1080
  ```
553
1081
 
554
- #### `aries datalake dev up`
1082
+ The original `aries datalake dev up|down|status|logs|reset` spellings remain
1083
+ available for compatibility.
1084
+
1085
+ #### `aries datalake up`
555
1086
  | Option | Default | Description |
556
1087
  |---|---|---|
557
1088
  | `--control-port <n>` | free loopback port | Control-plane port |
@@ -564,7 +1095,7 @@ aries datalake dev reset # Stop the dev server and wipe all local state
564
1095
  | `--audit-rotate` | `false` | Rotate the audit log daily (writes to `<home>/dev/audit/`) |
565
1096
  | `--audit-keep-days <n>` | | Prune rotated audit files older than this many days |
566
1097
 
567
- #### `aries datalake dev logs`
1098
+ #### `aries datalake logs`
568
1099
  | Option | Default | Description |
569
1100
  |---|---|---|
570
1101
  | `-f, --follow` | `false` | Stream new lines as they arrive |
@@ -638,14 +1169,14 @@ preserving the hydrated transaction tuple and all existing signatures.
638
1169
 
639
1170
  ---
640
1171
 
641
- ## `aries hash [file]` — content hashing
1172
+ ## `ariesi hash [file]` — content hashing
642
1173
 
643
1174
  ```text
644
- aries hash [file] [options]
645
- aries hash compare <hashA> <hashB> --algorithm <name> [--json]
1175
+ ariesi hash [file] [options]
1176
+ ariesi hash compare <hashA> <hashB> --algorithm <name> [--json]
646
1177
  ```
647
1178
 
648
- Reads input from `[file]` (positional), `--string`, or piped stdin (priority order). Dispatches to one of 11 algorithms.
1179
+ Reads input from `[file]` (positional), `--string`, or piped stdin (priority order). Dispatches to one of 10 algorithms.
649
1180
 
650
1181
  ### Options
651
1182
 
@@ -664,7 +1195,6 @@ Reads input from `[file]` (positional), `--string`, or piped stdin (priority ord
664
1195
  |---|---|---|---|---|---|
665
1196
  | `sha256` | strict | bytes | 64-char hex | — | `exact-match` |
666
1197
  | `xyo` | strict | JSON | 64-char hex | — | `exact-match` |
667
- | `tlsh` | fuzzy-byte | ≥50 bytes | 70-char hex | — | `tlsh-bit-hamming` ⚠ |
668
1198
  | `nilsimsa` | fuzzy-byte | bytes | 64-char hex | — | `nilsimsa-score` |
669
1199
  | `ssdeep` | fuzzy-byte | bytes | `bs:h1:h2` | `ssdeep` | `ssdeep-levenshtein` ⚠ |
670
1200
  | `phash` | perceptual-image | image | 16-char hex (64-bit) | — | `hamming-64` |
@@ -675,7 +1205,6 @@ Reads input from `[file]` (positional), `--string`, or piped stdin (priority ord
675
1205
  | `video-frames` | video | video file | JSON `{fps, frames:[{t,hash}]}` | `ffmpeg` | `frame-sequence-<algo>@<fps>fps` |
676
1206
 
677
1207
  ⚠ — Approximations, not the canonical reference scores:
678
- - `tlsh-bit-hamming` — the upstream `tlsh` npm package only exposes hashing, not the canonical TLSH-diff algorithm. We use bit-level Hamming over the hash body as a proxy.
679
1208
  - `ssdeep-levenshtein` — block-size-aware Levenshtein, without the canonical block-size attenuation curve.
680
1209
 
681
1210
  ### External binary install
@@ -697,29 +1226,29 @@ Each algorithm probes its binary at hash time and prints clear install instructi
697
1226
 
698
1227
  ```sh
699
1228
  # Strict
700
- aries hash --string "hello"
701
- aries hash ./payload.json --algorithm xyo
1229
+ ariesi hash --string "hello"
1230
+ ariesi hash ./payload.json --algorithm xyo
702
1231
 
703
1232
  # Byte-fuzzy
704
- aries hash --algorithm tlsh ./binary.exe
705
- aries hash compare <hashA> <hashB> --algorithm tlsh
1233
+ ariesi hash --algorithm nilsimsa ./binary.exe
1234
+ ariesi hash compare <hashA> <hashB> --algorithm nilsimsa
706
1235
 
707
1236
  # Perceptual image
708
- aries hash --algorithm phash ./photo.jpg
709
- aries hash --algorithm pdq ./photo.jpg
710
- aries hash compare <hashA> <hashB> --algorithm pdq
1237
+ ariesi hash --algorithm phash ./photo.jpg
1238
+ ariesi hash --algorithm pdq ./photo.jpg
1239
+ ariesi hash compare <hashA> <hashB> --algorithm pdq
711
1240
 
712
1241
  # Audio
713
- aries hash --algorithm chromaprint ./song.mp3 > song.fp.json
714
- aries hash compare "$(cat a.fp.json)" "$(cat b.fp.json)" --algorithm chromaprint --json
1242
+ ariesi hash --algorithm chromaprint ./song.mp3 > song.fp.json
1243
+ ariesi hash compare "$(cat a.fp.json)" "$(cat b.fp.json)" --algorithm chromaprint --json
715
1244
 
716
1245
  # Video
717
- aries hash --algorithm video-frames --fps 1 ./movie.mkv > movie.fp.json
718
- aries hash --algorithm video-frames --fps 1 --frame-algorithm pdq ./movie.mkv > movie-pdq.fp.json
719
- aries hash compare "$(cat a.fp.json)" "$(cat b.fp.json)" --algorithm video-frames
1246
+ ariesi hash --algorithm video-frames --fps 1 ./movie.mkv > movie.fp.json
1247
+ ariesi hash --algorithm video-frames --fps 1 --frame-algorithm pdq ./movie.mkv > movie-pdq.fp.json
1248
+ ariesi hash compare "$(cat a.fp.json)" "$(cat b.fp.json)" --algorithm video-frames
720
1249
  ```
721
1250
 
722
- ### `aries hash compare <hashA> <hashB>`
1251
+ ### `ariesi hash compare <hashA> <hashB>`
723
1252
 
724
1253
  | Positional | | Description |
725
1254
  |---|---|---|
@@ -737,18 +1266,18 @@ The compare command needs only the two hash strings — works against hashes gen
737
1266
 
738
1267
  ---
739
1268
 
740
- ## `aries npmjs` — npmjs org package checks
1269
+ ## `ariesi npmjs` — npmjs org package checks
741
1270
 
742
1271
  ```sh
743
- aries npmjs list --org=xylabs
744
- aries npmjs lint --org=xylabs
745
- aries npmjs lint --org=xylabs --fix
746
- aries npmjs lint # all auth-visible org packages
1272
+ ariesi npmjs list --org=xylabs
1273
+ ariesi npmjs lint --org=xylabs
1274
+ ariesi npmjs lint --org=xylabs --fix
1275
+ ariesi npmjs lint # all auth-visible org packages
747
1276
  ```
748
1277
 
749
- By default, package discovery uses your current npm CLI authentication via `npm access list packages @<org> --json`, so private or restricted org packages are included when your npm account can see them. Omit `--org` to list or lint all scoped packages returned by `npm access list packages --json`, grouped by org with a per-org summary at the end. If npm auth is unavailable for a specific `--org`, `aries npmjs` falls back to public package discovery and reports `npm auth: unauthenticated` at the end of text output. Use `--public-only` with `--org` to force public discovery.
1278
+ By default, package discovery uses your current npm CLI authentication via `npm access list packages @<org> --json`, so private or restricted org packages are included when your npm account can see them. Omit `--org` to list or lint all scoped packages returned by `npm access list packages --json`, grouped by org with a per-org summary at the end. If npm auth is unavailable for a specific `--org`, `ariesi npmjs` falls back to public package discovery and reports `npm auth: unauthenticated` at the end of text output. Use `--public-only` with `--org` to force public discovery.
750
1279
 
751
- ### `aries npmjs list`
1280
+ ### `ariesi npmjs list`
752
1281
 
753
1282
  | Option | Default | Description |
754
1283
  |---|---|---|
@@ -756,7 +1285,7 @@ By default, package discovery uses your current npm CLI authentication via `npm
756
1285
  | `--public-only` | `false` | List only public packages without using `npm access` |
757
1286
  | `--json` | `false` | Output as JSON |
758
1287
 
759
- ### `aries npmjs lint`
1288
+ ### `ariesi npmjs lint`
760
1289
 
761
1290
  Find packages that are not marked deprecated but probably should be. V1 reports warning-only findings and exits `0` unless an operational error occurs.
762
1291