@capxul/cli 4.20.0-beta.4 → 4.20.0-beta.6
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 +179 -5
- package/dist/browser/GeistVF.woff +0 -0
- package/dist/browser/signer.js +74410 -0
- package/dist/browser/signer.js.map +1 -0
- package/dist/main.mjs +19647 -16155
- package/dist/main.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# Capxul CLI
|
|
2
2
|
|
|
3
|
-
The CLI provides
|
|
4
|
-
|
|
3
|
+
The CLI provides email OTP login, persistent first-party sessions, terminal-owned
|
|
4
|
+
signup, a bundled Openfort wallet page, backend profile and account reads,
|
|
5
|
+
diagnostics, and one global collection preference. It requires Node 24 or later
|
|
6
|
+
on macOS or Linux.
|
|
5
7
|
|
|
6
8
|
```sh
|
|
7
9
|
capxul --help
|
|
@@ -15,25 +17,126 @@ capxul doctor --online --timeout-ms 30000 --json
|
|
|
15
17
|
```
|
|
16
18
|
|
|
17
19
|
Help and version do not require application credentials or a working backend.
|
|
20
|
+
With no arguments, `capxul` shows the same generated help as `capxul --help`.
|
|
18
21
|
They use the same observation policy as ordinary commands. Shell completion
|
|
19
22
|
machinery and collection controls send no observation records.
|
|
20
23
|
`doctor` checks local configuration unless `--online` is present. An online
|
|
21
24
|
check uses the public Capxul SDK and verifies the backend response nonce.
|
|
22
25
|
It does not authenticate a person or submit a transaction.
|
|
23
26
|
|
|
27
|
+
## Organization commands
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
capxul org list --json
|
|
31
|
+
capxul org use --org ORGANIZATION_ID
|
|
32
|
+
capxul org status --org ORGANIZATION_ID --json
|
|
33
|
+
capxul org get --json
|
|
34
|
+
capxul org me --json
|
|
35
|
+
capxul org members --json
|
|
36
|
+
capxul org member list --json
|
|
37
|
+
capxul org member get --account-id ACCOUNT_ID --json
|
|
38
|
+
capxul org wait --timeout-seconds 120 --json
|
|
39
|
+
capxul org create --name NAME --handle HANDLE --country CC [--bio TEXT] [--size TEXT] [--confirm]
|
|
40
|
+
capxul org retry --org ORGANIZATION_ID [--confirm]
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
These commands accept `--email`. Without it, they restore the protected current
|
|
44
|
+
session. Organization reads accept `--org` or its alias `--org-id`. Identical
|
|
45
|
+
repeated IDs are accepted. Different IDs are refused.
|
|
46
|
+
|
|
47
|
+
`org use` requires an explicit Organization ID. It checks current access and
|
|
48
|
+
saves a protected per-person read default. The default never grants authority.
|
|
49
|
+
Each read checks current access again. Without an explicit ID or saved default,
|
|
50
|
+
interactive mode asks you to select an Organization. JSON, CI, and noninteractive
|
|
51
|
+
mode refuse missing scope. No command starts a signer or changes backend state.
|
|
52
|
+
|
|
53
|
+
`org get` reports the canonical command `org.status`. Both member list forms
|
|
54
|
+
report `org.members` and retain pending members with `accountId: null`.
|
|
55
|
+
`org member get` matches the full AccountId, not a Safe address or ID prefix.
|
|
56
|
+
No match returns exit 2. Duplicate matches return exit 1.
|
|
57
|
+
|
|
58
|
+
`org wait` reads the same lifecycle every second until it reports `ready` or
|
|
59
|
+
`failed`. It never retries setup. The timeout accepts integers from 1 to 3600
|
|
60
|
+
seconds and defaults to 120. Timeout returns exit 5; interruption returns 130.
|
|
61
|
+
A successful read can report a failed or pending domain state.
|
|
62
|
+
|
|
63
|
+
## Organization writes
|
|
64
|
+
|
|
65
|
+
`org create` and `org retry` restore the protected current session and start the
|
|
66
|
+
existing command-scoped browser signer. They never read or write the saved read
|
|
67
|
+
default. Local input checks run before any client, browser, or backend work, and
|
|
68
|
+
they include the confirmation gate:
|
|
69
|
+
|
|
70
|
+
- A noninteractive or JSON write requires `--confirm`. Without it the command
|
|
71
|
+
refuses with exit 2 before any client, browser, or mutation work.
|
|
72
|
+
- A terminal write verifies the session and performs its Organization reads
|
|
73
|
+
first, then prints the resolved preview and asks a default-no prompt, even when
|
|
74
|
+
`--confirm` is supplied. Rejection refuses with exit 2. An absent session is
|
|
75
|
+
exit 3 before any preview. The browser signer is built only after confirmation
|
|
76
|
+
succeeds, so a refused write never starts it.
|
|
77
|
+
|
|
78
|
+
`--email` selects the session explicitly. Otherwise the protected
|
|
79
|
+
current-session pointer decides. An invalid explicit email refuses with exit 2.
|
|
80
|
+
|
|
81
|
+
`--timeout-seconds` bounds the command's own wait, not backend execution. It
|
|
82
|
+
accepts integers from 1 to 3600 and defaults to 120, and it is one deadline for
|
|
83
|
+
the whole write: the `completeOrganization` or `retrySetup` call and the
|
|
84
|
+
settlement that follows share it. While a lane settles the command reads the
|
|
85
|
+
exact Organization lifecycle every second with no overlapping read. At the
|
|
86
|
+
deadline the active SDK signal is aborted, so the command stops waiting and
|
|
87
|
+
forwards no further signature, while the durable backend lane keeps running.
|
|
88
|
+
Committed lifecycle progress is flushed first, so the Organization ID stays on
|
|
89
|
+
stderr and the same Organization resumes with `org retry --org`. Exceeding the
|
|
90
|
+
deadline returns exit 5.
|
|
91
|
+
|
|
92
|
+
`org create` validates `--name`, the `--handle` grammar, and the ISO `--country`
|
|
93
|
+
code first, and its terminal preview also lists the Organizations the person
|
|
94
|
+
already has. It subscribes to the onboarding Organization-state projection, then
|
|
95
|
+
completes the Organization with an explicit create intent. The first committed
|
|
96
|
+
Organization ID is retained, and each committed lifecycle change is written to
|
|
97
|
+
stderr before the next Organization authorization digest reaches the signer.
|
|
98
|
+
JSON mode writes one newline-delimited progress object per change:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{ "type": "organization.lifecycle", "organizationId": "O", "status": "settingUp" }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Human mode prints the full Organization ID and lifecycle status. A refused or
|
|
105
|
+
failed lane still reports the Organization it is about. The command returns
|
|
106
|
+
success only after an exact `org(O).getLifecycle()` read reports `ready`. It
|
|
107
|
+
never saves a read default and never returns a different ready Organization.
|
|
108
|
+
|
|
109
|
+
`org retry` requires an explicit `--org` (or `--org-id`). It validates the ID
|
|
110
|
+
with the public `toOrgId` constructor, reads that exact Organization's lifecycle
|
|
111
|
+
for its terminal preview, resumes that same durable setup lane, then settles the
|
|
112
|
+
same Organization's lifecycle. A resumed lane that asks the
|
|
113
|
+
signer to reset its session clears the stale readiness, closes that browser
|
|
114
|
+
bridge, and opens the next one for the same command. `org retry` never creates a
|
|
115
|
+
replacement Organization and never changes the read default. An already-ready
|
|
116
|
+
Organization returns that exact readiness without a signature. A conflicting
|
|
117
|
+
failed or in-flight lane is preserved and refused.
|
|
118
|
+
|
|
119
|
+
The result data for both commands is `{ organizationId, lifecycle }`. A known
|
|
120
|
+
Organization ID on a `WRONG_STATE` refusal appears only in the SDK-supplied
|
|
121
|
+
`error.details.organizationId` field, and the refusal copy names the recovery
|
|
122
|
+
action instead of authentication guidance. No token, OTP, signature, or signer
|
|
123
|
+
capability is ever printed. Interruption returns 130 and closes both the
|
|
124
|
+
subscription and the browser bridge.
|
|
125
|
+
|
|
24
126
|
## Configuration
|
|
25
127
|
|
|
26
128
|
| Variable | Use |
|
|
27
129
|
| ------------------------------ | ------------------------------------------------------------------------------------------------------------ |
|
|
28
130
|
| `CAPXUL_CLI_HOME` | Directory for global CLI settings. Defaults to `$XDG_CONFIG_HOME/capxul/cli`, or `$HOME/.config/capxul/cli`. |
|
|
29
|
-
| `CAPXUL_PUBLISHABLE_KEY` |
|
|
131
|
+
| `CAPXUL_PUBLISHABLE_KEY` | Optional developer override for the bundled first-party staging key. |
|
|
30
132
|
| `CAPXUL_BOOTSTRAP_URL` | Bootstrap origin. Defaults to `https://api.staging.capxul.com`. Convex Cloud origins are rejected. |
|
|
31
133
|
| `CAPXUL_POSTHOG_HOST` | Optional development override for the built-in public PostHog ingestion origin. |
|
|
32
134
|
| `CAPXUL_POSTHOG_PROJECT_TOKEN` | Optional development override for the built-in public project ingestion token. |
|
|
33
135
|
| `CAPXUL_TELEMETRY_DISABLED` | Set to `true` to disable remote observation regardless of the saved preference. |
|
|
34
136
|
|
|
35
|
-
The published CLI includes
|
|
36
|
-
|
|
137
|
+
The published CLI includes the verified first-party staging application key and
|
|
138
|
+
Capxul-owned public ingestion configuration. You do not need key or PostHog
|
|
139
|
+
environment variables. A different bootstrap origin requires an explicit key. Collection defaults to enabled for
|
|
37
140
|
ordinary local and online commands, help, version, and safely attributed argument
|
|
38
141
|
refusals. Parser refusals produce a completion without a start. Early native
|
|
39
142
|
global errors with no resolved command route send nothing, because the CLI
|
|
@@ -109,6 +212,15 @@ compinit
|
|
|
109
212
|
Use `npm update -g @capxul/cli` or `brew upgrade xelmar-tech/tap/capxul` to update.
|
|
110
213
|
Use one installer for the `capxul` executable to avoid conflicting PATH entries.
|
|
111
214
|
|
|
215
|
+
After a successful human command, help, or version request, the CLI can show an
|
|
216
|
+
update notice on terminal stderr. It checks the public npm `latest` tag at most
|
|
217
|
+
once per 24 hours. It shows only the command for the verified running npm-global
|
|
218
|
+
or Homebrew installation. It does not execute that command. Unknown installations,
|
|
219
|
+
development versions, JSON output, redirected stderr, CI, shell completion, and
|
|
220
|
+
all `telemetry` commands receive no notice. The optional check has one 500 ms
|
|
221
|
+
budget. Safe failed attempts are cached. Storage or network failures remain
|
|
222
|
+
silent and do not change the command result. This check sends no telemetry.
|
|
223
|
+
|
|
112
224
|
## Development commands
|
|
113
225
|
|
|
114
226
|
```sh
|
|
@@ -121,3 +233,65 @@ vp exec node --test --test-name-pattern='@capxul/cli' scripts/__tests__/pack-ins
|
|
|
121
233
|
The last command installs the tarball outside the workspace and exercises the
|
|
122
234
|
installed executable with isolated settings and a local HTTP server. The CI
|
|
123
235
|
`CLI / Linux / Node 24.0.0` job runs this proof at the declared minimum version.
|
|
236
|
+
|
|
237
|
+
## Email login and session restoration
|
|
238
|
+
|
|
239
|
+
This CLI establishes a first-party BetterAuth session. It has broader authority
|
|
240
|
+
than the earlier native `account:read` grant. Existing native grants remain
|
|
241
|
+
stored and tagged as `legacy-native-grant` in status. A profile read asks for an
|
|
242
|
+
explicit new login; it never exchanges the old grant for a broader session.
|
|
243
|
+
Logout forgets and attempts to revoke both credential types for the selected email.
|
|
244
|
+
|
|
245
|
+
For a human, `capxul auth login` prompts for email and a hidden OTP. `auth signup`
|
|
246
|
+
also prompts for the current Profile fields: display name, two-letter country
|
|
247
|
+
code, and handle. The browser opens only when the shared Core onboarding journey
|
|
248
|
+
needs Openfort wallet readiness. It shows wallet status only. It has no email,
|
|
249
|
+
OTP, Profile, or approval form.
|
|
250
|
+
|
|
251
|
+
For an agent, send and verify in separate processes:
|
|
252
|
+
|
|
253
|
+
```sh
|
|
254
|
+
capxul auth send --email "$TEST_EMAIL" --json
|
|
255
|
+
# Supply the delivered six-digit OTP through stdin, not a command argument.
|
|
256
|
+
capxul auth verify --email "$TEST_EMAIL" --otp-stdin --json
|
|
257
|
+
capxul auth signup --email "$TEST_EMAIL" --display-name "Test Person" --country GH --handle test_person --json
|
|
258
|
+
capxul auth profile --email "$TEST_EMAIL" --json
|
|
259
|
+
# A later process uses the same protected CLI home; no new OTP is required.
|
|
260
|
+
capxul auth profile --email "$TEST_EMAIL" --json
|
|
261
|
+
capxul auth status --email "$TEST_EMAIL" --json
|
|
262
|
+
capxul auth logout --email "$TEST_EMAIL" --json
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
`--otp-stdin` reads up to 64 bytes, ending at EOF. Pipe from a secret provider or
|
|
266
|
+
use input redirection from a protected file. OTPs are never accepted in argv,
|
|
267
|
+
persisted in the continuation, or included in output. Non-interactive commands
|
|
268
|
+
without the required input refuse with exit 2 instead of prompting.
|
|
269
|
+
|
|
270
|
+
A fresh non-interactive signup can do verification and setup in one command:
|
|
271
|
+
|
|
272
|
+
```sh
|
|
273
|
+
# Supply only the delivered OTP through stdin.
|
|
274
|
+
capxul auth signup --email "$TEST_EMAIL" --otp-stdin \
|
|
275
|
+
--display-name "Test Person" --country GH --handle test_person --json
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
The local page binds to an OS-selected loopback port. A random launch capability
|
|
279
|
+
is redeemed once and removed from the URL before Openfort starts. The page receives
|
|
280
|
+
only the authenticated wallet token and encryption session in memory. Closing it
|
|
281
|
+
ends the current wallet attempt. Re-run `auth signup` with the same CLI home to
|
|
282
|
+
resume the same Profile and Account without another OTP while the backend session
|
|
283
|
+
remains valid.
|
|
284
|
+
|
|
285
|
+
The version 2 `first-party-session` record stores the opaque provider credential
|
|
286
|
+
in the existing protected plaintext store. Its scope includes the application
|
|
287
|
+
key, issuer, environment, and email. Each process validates restoration with the
|
|
288
|
+
backend; cached session data is not authority. Conditional replacement prevents
|
|
289
|
+
a concurrent logout from being undone by a delayed credential save. The backend
|
|
290
|
+
owns expiry and revocation. A failed remote logout is reported as `unconfirmed`;
|
|
291
|
+
local sign-out remains in effect.
|
|
292
|
+
|
|
293
|
+
`auth profile` returns a backend-read Profile and account lifecycle without opening
|
|
294
|
+
the browser. Successful email authentication can return `setupState: "setup-required"`.
|
|
295
|
+
`auth signup` returns `setupState: "ready"` only after Core reads a ready Account.
|
|
296
|
+
After logout, profile reads refuse with `NOT_AUTHENTICATED` and exit 3. An invalid
|
|
297
|
+
or expired OTP refuses with exit 2.
|
|
Binary file
|