@visa/cli 4.1.0-rc.6 → 4.1.0-rc.61

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 (70) hide show
  1. package/README.md +168 -235
  2. package/dist/checkout-engine/adapters/generic.d.ts +23 -0
  3. package/dist/checkout-engine/adapters/generic.js +216 -0
  4. package/dist/checkout-engine/adapters/index.d.ts +8 -0
  5. package/dist/checkout-engine/adapters/index.js +21 -0
  6. package/dist/checkout-engine/adapters/shopify.d.ts +31 -0
  7. package/dist/checkout-engine/adapters/shopify.js +423 -0
  8. package/dist/checkout-engine/adapters/stripe-like.d.ts +10 -0
  9. package/dist/checkout-engine/adapters/stripe-like.js +21 -0
  10. package/dist/checkout-engine/amount.d.ts +15 -0
  11. package/dist/checkout-engine/amount.js +72 -0
  12. package/dist/checkout-engine/browser-launch.d.ts +46 -0
  13. package/dist/checkout-engine/browser-launch.js +81 -0
  14. package/dist/checkout-engine/ceremony.d.ts +64 -0
  15. package/dist/checkout-engine/ceremony.js +261 -0
  16. package/dist/checkout-engine/cli-engine.d.ts +200 -0
  17. package/dist/checkout-engine/cli-engine.js +659 -0
  18. package/dist/checkout-engine/detect.d.ts +61 -0
  19. package/dist/checkout-engine/detect.js +398 -0
  20. package/dist/checkout-engine/evidence.d.ts +25 -0
  21. package/dist/checkout-engine/evidence.js +104 -0
  22. package/dist/checkout-engine/executor.d.ts +176 -0
  23. package/dist/checkout-engine/executor.js +1322 -0
  24. package/dist/checkout-engine/hosted-approval.d.ts +142 -0
  25. package/dist/checkout-engine/hosted-approval.js +339 -0
  26. package/dist/checkout-engine/index.d.ts +6 -0
  27. package/dist/checkout-engine/index.js +8 -0
  28. package/dist/checkout-engine/inline-target.d.ts +13 -0
  29. package/dist/checkout-engine/inline-target.js +37 -0
  30. package/dist/checkout-engine/instrument.d.ts +61 -0
  31. package/dist/checkout-engine/instrument.js +87 -0
  32. package/dist/checkout-engine/live-fill-approval.d.ts +43 -0
  33. package/dist/checkout-engine/live-fill-approval.js +90 -0
  34. package/dist/checkout-engine/mandate/card-mandate.d.ts +121 -0
  35. package/dist/checkout-engine/mandate/card-mandate.js +227 -0
  36. package/dist/checkout-engine/mandate/mandate-ledger.d.ts +142 -0
  37. package/dist/checkout-engine/mandate/mandate-ledger.js +335 -0
  38. package/dist/checkout-engine/mandate.d.ts +25 -0
  39. package/dist/checkout-engine/mandate.js +100 -0
  40. package/dist/checkout-engine/outcome.d.ts +30 -0
  41. package/dist/checkout-engine/outcome.js +225 -0
  42. package/dist/checkout-engine/owner-only-file.d.ts +19 -0
  43. package/dist/checkout-engine/owner-only-file.js +41 -0
  44. package/dist/checkout-engine/package.json +3 -0
  45. package/dist/checkout-engine/receipt.d.ts +81 -0
  46. package/dist/checkout-engine/receipt.js +109 -0
  47. package/dist/checkout-engine/repo-env.d.ts +11 -0
  48. package/dist/checkout-engine/repo-env.js +23 -0
  49. package/dist/checkout-engine/trace-handles.d.ts +8 -0
  50. package/dist/checkout-engine/trace-handles.js +12 -0
  51. package/dist/checkout-engine/types.d.ts +44 -0
  52. package/dist/checkout-engine/types.js +2 -0
  53. package/dist/checkout-engine/vgs-gateway/fetch-credential.d.mts +74 -0
  54. package/dist/checkout-engine/vgs-gateway/fetch-credential.mjs +248 -0
  55. package/dist/checkout-engine/vgs-gateway/server-mint-client.d.ts +82 -0
  56. package/dist/checkout-engine/vgs-gateway/server-mint-client.js +180 -0
  57. package/dist/checkout-engine/vgs-live-instrument.d.ts +170 -0
  58. package/dist/checkout-engine/vgs-live-instrument.js +293 -0
  59. package/dist/checkout-engine/vic-confirmation.d.ts +34 -0
  60. package/dist/checkout-engine/vic-confirmation.js +39 -0
  61. package/dist/cli.js +391 -427
  62. package/dist/mcp-server/index.js +312 -163
  63. package/dist/skills/pair-visa-agent/RUNTIMES.md +92 -0
  64. package/dist/skills/pair-visa-agent/SKILL.md +315 -0
  65. package/dist/skills/pair-visa-agent/scripts/setup.mjs +48 -0
  66. package/install.ps1 +3 -41
  67. package/install.sh +3 -35
  68. package/native/bin/win32-x64/visa-keychain-win.exe +0 -0
  69. package/package.json +11 -7
  70. package/server.json +3 -3
@@ -0,0 +1,92 @@
1
+ # Running Visa pairing in OpenClaw and Hermes
2
+
3
+ `@visa/visa-cli-openclaw` is packaged for OpenClaw, but the pairing v2 skill is
4
+ runtime-agnostic. OpenClaw, Hermes, and any runtime that can execute the `visa` CLI or
5
+ mount its MCP server all use the same identity-only enrollment ceremony.
6
+
7
+ ## Plugins are runtime-specific
8
+
9
+ | Axis | OpenClaw | Hermes |
10
+ | --------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
11
+ | Language | JavaScript/TypeScript | Python |
12
+ | Plugin manifest | `openclaw.plugin.json` + `definePluginEntry` (`index.ts`) | `~/.hermes/plugins/<name>/plugin.yaml` + `__init__.py`, `ctx.register_tool(...)` |
13
+ | Config file | `~/.openclaw/openclaw.json` | `~/.hermes/config.yaml` |
14
+ | Skills | Markdown `SKILL.md` | Markdown under `~/.hermes/skills/<name>/` |
15
+ | MCP | `mcp.servers.*` | `mcp_servers.*` |
16
+ | Migration | — | `hermes claw migrate` imports skills, allowlists, compatible MCP servers, memory, and `SOUL.md` |
17
+
18
+ The OpenClaw JavaScript tools do not load as a Hermes plugin. Portability comes from the
19
+ Markdown skill, CLI, and MCP protocol instead.
20
+
21
+ ## One ceremony, three surfaces
22
+
23
+ All supported surfaces share the same local pending record and pairing v2 protocol:
24
+
25
+ 1. OpenClaw: `pair_agent_start` / `pair_agent_poll`.
26
+ 2. Visa MCP server: `enroll_agent` with `action: "start"` / `action: "claim"`.
27
+ 3. Raw CLI: `visa agent enroll --format json` /
28
+ `visa agent enroll-claim --format json`.
29
+
30
+ The start operation returns an authorization URL for the human. The browser receives only
31
+ that URL. The runtime retains its private Ed25519 key and local claim material. Polling
32
+ resumes the same pending identity and safely replays the same signed request after an
33
+ interruption.
34
+
35
+ On activation, use `agentId` as the stable identity. `identityKeyJkt` identifies the
36
+ currently bound Ed25519 public key and can change after key rotation. Activation means the
37
+ identity is paired only; payment methods, email, and tap bindings are separate future or
38
+ follow-up configuration.
39
+
40
+ ## Install and mount
41
+
42
+ Install the prerelease CLI, which provides both command names and the MCP server:
43
+
44
+ ```sh
45
+ npm install -g @visa/cli@rc
46
+ ```
47
+
48
+ There is no `visa mcp` subcommand. Run `visa-cli connect <runtime>` when supported, or
49
+ configure `@visa/cli/dist/mcp-server/index.js` directly. Replace `<npm root -g>` below
50
+ with the output of `npm root -g`.
51
+
52
+ OpenClaw (`~/.openclaw/openclaw.json`):
53
+
54
+ ```json
55
+ {
56
+ "mcp": {
57
+ "servers": {
58
+ "visa-cli": {
59
+ "command": "node",
60
+ "args": ["<npm root -g>/@visa/cli/dist/mcp-server/index.js"]
61
+ }
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ Hermes (`~/.hermes/config.yaml`):
68
+
69
+ ```yaml
70
+ mcp_servers:
71
+ visa-cli:
72
+ command: node
73
+ args: ['<npm root -g>/@visa/cli/dist/mcp-server/index.js']
74
+ ```
75
+
76
+ ## Runtime setup map
77
+
78
+ | Runtime | Setup and pairing surface |
79
+ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
80
+ | OpenClaw | Install `@visa/visa-cli-openclaw` for the `pair_agent_*` tools and bundled skill. The plugin auto-mounts the Visa MCP server. The MCP or raw CLI surfaces remain valid alternatives. |
81
+ | Hermes | Run `visa-cli connect hermes`, install `pair-visa-agent/SKILL.md` under `~/.hermes/skills/`, and use `enroll_agent`. `hermes claw migrate` can import an existing OpenClaw setup. |
82
+ | Other runtime | Put `visa` on `PATH`, mount the same MCP server if supported, or use the raw `visa agent enroll` and `visa agent enroll-claim` commands as the universal fallback. |
83
+
84
+ The skill itself can be installed with `visa agent skill`. Pass `--runtime <name>` or
85
+ `--dir <path>` when auto-detection is not appropriate, then reload the runtime.
86
+
87
+ ## Optional Hermes wrapper
88
+
89
+ A Hermes Python plugin may expose the same `pair_agent_start` and `pair_agent_poll` names
90
+ by calling the canonical raw CLI commands and registering tools with
91
+ `ctx.register_tool(...)`. It is optional: the MCP server and skill already expose the
92
+ same protocol and persisted pairing state without a second implementation.
@@ -0,0 +1,315 @@
1
+ ---
2
+ name: pair-visa-agent
3
+ description: Pair a Visa CLI v4 agent identity to this runtime. Present one authorization link and the full public request-key fingerprint to the human, then poll until the runtime's local Ed25519 identity is activated. Use when the user says "pair my agent", "enroll my Visa CLI", "connect my Visa agent", or "set up my agent identity".
4
+ compatibility: Needs the `visa` CLI (`npm i -g @visa/cli@rc`) — run `node scripts/setup.mjs` to install it if missing — plus network access to the Visa authorization service. Works in OpenClaw, Hermes, or any Agent Skills runtime.
5
+ allowed-tools: Bash(visa:*) Bash(visa-cli:*) Bash(node:*) Bash(npm:*) Bash(npx:*)
6
+ metadata:
7
+ author: visa
8
+ homepage: https://visacli.sh/agents
9
+ version: '0.6.5'
10
+ # OpenClaw-namespaced extension (agentskills.io keeps `metadata` free-form, so
11
+ # non-standard runtime config lives here — `user-invocable` is not a standard
12
+ # top-level field). OpenClaw auto-installs `install[]` when `requires.bins` are
13
+ # missing; other runtimes (Hermes, Claude Code, …) self-provision via the
14
+ # bundled `scripts/setup.mjs` (see compatibility + Getting set up). @rc pinned
15
+ # until 4.1.0 is promoted to latest.
16
+ openclaw:
17
+ user-invocable: true
18
+ emoji: '🔐'
19
+ requires:
20
+ bins:
21
+ - visa
22
+ install:
23
+ - kind: node
24
+ package: '@visa/cli@rc'
25
+ bins:
26
+ - visa
27
+ - visa-cli
28
+ ---
29
+
30
+ # Pair a Visa CLI v4 agent identity
31
+
32
+ Pair this runtime's locally generated identity with a human-approved Visa agent. Pairing
33
+ protocol v2 has one ceremony and three equivalent ways to drive it:
34
+
35
+ - **`pair_agent_start` / `pair_agent_poll`** — OpenClaw plugin tools.
36
+ - **`enroll_agent` with `action: "start"` / `action: "claim"`** — the `visa` MCP server tool.
37
+ - **`visa agent enroll --format json` / `visa agent enroll-claim --format json`** — the raw
38
+ CLI and universal fallback.
39
+
40
+ Use the first surface available. Do not mix this flow with older pairing or login flows;
41
+ all three surfaces above wrap the same v2 enrollment ceremony and local pending state.
42
+
43
+ ## What pairing establishes
44
+
45
+ Pairing activates an agent identity on this runtime:
46
+
47
+ - `agentId` is the server-assigned, stable identifier for the agent.
48
+ - The runtime creates and retains the private Ed25519 identity key. It sends only the
49
+ public JWK to the service.
50
+ - `identityKeyJkt` is the thumbprint of the currently bound Ed25519 public key. It can
51
+ change when that key rotates, so it must never be presented or stored as the stable
52
+ agent identifier.
53
+ - The human receives the authorization URL, stable agent ID, and full public request-key
54
+ fingerprint for exact comparison. Private key material, the local claim token, and signed
55
+ protocol messages stay with the runtime.
56
+ - An `activated` result means **identity paired only**. Payment methods, an email address,
57
+ and tap bindings are separate configuration that may be added later. Do not infer any
58
+ of those capabilities from pairing success.
59
+
60
+ ## Getting this skill
61
+
62
+ The skill ships inside the public `@visa/cli` npm package. No clone of the private
63
+ monorepo is required:
64
+
65
+ ```sh
66
+ npm install -g @visa/cli@rc
67
+ visa agent skill
68
+ ```
69
+
70
+ `visa agent skill` auto-detects OpenClaw, Hermes, and Claude Code, falling back to the
71
+ project-local `./.agents/skills`. Pass `--runtime <name>` or `--dir <path>` to choose a
72
+ target, `--force` to overwrite, or `--print` to read without writing. Reload or restart
73
+ the agent runtime after installation so it registers the skill.
74
+
75
+ Access remains enforced by the Visa service. Installing the public package or skill does
76
+ not authorize an account to pair.
77
+
78
+ OpenClaw users also receive the skill with the `@visa/visa-cli-openclaw` plugin.
79
+
80
+ ## Getting set up
81
+
82
+ 1. **Install the prerelease CLI.** Run `npm install -g @visa/cli@rc`, or run the bundled
83
+ idempotent provisioner `node scripts/setup.mjs`. The `@latest` tag may not yet expose
84
+ the v4 agent commands. Installation puts `visa` and `visa-cli` on `PATH` and includes
85
+ `@visa/cli/dist/mcp-server/index.js`.
86
+ 2. **Mount the MCP server when the runtime supports MCP.**
87
+ - **OpenClaw:** installing `@visa/visa-cli-openclaw` auto-mounts the server by writing
88
+ `mcp.servers["visa-cli"]` in `~/.openclaw/openclaw.json`.
89
+ - **Hermes or another supported runtime:** run `visa-cli connect hermes` or
90
+ `visa-cli connect <runtime>`. For Hermes, the entry is written under `mcp_servers`
91
+ in `~/.hermes/config.yaml`.
92
+ - **No MCP integration:** use the raw `visa agent …` commands.
93
+ 3. **Pair.** Follow the core flow below.
94
+
95
+ ## MCP mounting examples
96
+
97
+ Both runtimes use the same server entrypoint. Replace `<npm root -g>` with the output of
98
+ `npm root -g`.
99
+
100
+ OpenClaw (`~/.openclaw/openclaw.json`):
101
+
102
+ ```json
103
+ {
104
+ "mcp": {
105
+ "servers": {
106
+ "visa-cli": {
107
+ "command": "node",
108
+ "args": ["<npm root -g>/@visa/cli/dist/mcp-server/index.js"]
109
+ }
110
+ }
111
+ }
112
+ }
113
+ ```
114
+
115
+ Hermes (`~/.hermes/config.yaml`):
116
+
117
+ ```yaml
118
+ mcp_servers:
119
+ visa-cli:
120
+ command: node
121
+ args: ['<npm root -g>/@visa/cli/dist/mcp-server/index.js']
122
+ ```
123
+
124
+ In Hermes, `hermes claw migrate` can also import this skill and MCP configuration from an
125
+ existing OpenClaw installation. See `RUNTIMES.md` for the complete runtime map.
126
+
127
+ ## JSON and exit-code contract
128
+
129
+ Prefer structured output and parse it; never scrape prose.
130
+
131
+ - The OpenClaw and MCP tools return structured objects directly.
132
+ - Raw CLI commands support `--format json`.
133
+ - `visa agent enroll-claim` exits `0` when activated, `3` when the human has not finished,
134
+ and `1` on a terminal failure.
135
+
136
+ The start result includes protocol version `2`, `pairingId`, stable `agentId`, full
137
+ `requestKeyFingerprint`, `browserUrl`, and expiry information. The activation result
138
+ includes protocol version `2`, `pairingId`, stable `agentId`, the display name, and
139
+ `identityKeyJkt`.
140
+
141
+ ## Fastest path — one shot (`visa agent pair`)
142
+
143
+ If the `visa` CLI is on PATH, prefer the one-shot command — it does the whole flow
144
+ from a single call, so the user types nothing after their initial request:
145
+
146
+ ```
147
+ visa agent pair --format json
148
+ ```
149
+
150
+ It returns `browserUrl`, `pairingId`, stable `agentId`, and the full public
151
+ `requestKeyFingerprint` **immediately**. It starts a detached activation process only
152
+ after the pending identity and private key are durable. Present the link and fingerprint
153
+ for exact browser comparison. When `claiming` is `background`, activation completes after
154
+ approval without another command; if it is `manual`, run the returned `recoveryCommand`
155
+ after approval. Use the step-by-step flow below when `pair` is unavailable or when driving
156
+ the plugin/MCP tools.
157
+
158
+ ## Returning & already-connected — do NOT re-pair
159
+
160
+ If `pair`/`enroll` returns **`already_connected`** (or `alreadyConnected: true`), this
161
+ device is **already set up** as an agent — a fresh pairing is neither needed nor
162
+ possible (re-pairing an existing identity silently dead-ends). Do this instead:
163
+
164
+ 1. **Tell the user plainly:** "This device is already connected as `<name>.visa`."
165
+ Read the name from the response. Do **not** start another hand-off. `--new` /
166
+ `force:true` exists only if they explicitly want a _second, separate_ agent.
167
+ 2. **Report status honestly — "connected" is five separate things**, not one. Never
168
+ imply the agent can spend just because it's connected:
169
+ - **Identity** — connected (`.visa` name bound to _this user's_ account). ✓ once `already_connected`.
170
+ - **Spending** — a _separate human approval_. If `keyBound`/spend isn't set, say:
171
+ "To let me pay, approve spending in your **account settings → agent card → Spend**."
172
+ You **cannot** self-grant it; never tell the user to run `visa agent add-rail`
173
+ (it refuses identity-only agents).
174
+ - **Mesh (`.visa` messaging)** — with `SUBWAY_MESH=visa`, a returning device now
175
+ registers on `pair`; if `meshRegistered` is false, `visa register <name>` joins it.
176
+ - **Trusted (TAP)** — follows spend/provisioning; don't promise it before then.
177
+ 3. **Scope everything to the user.** The identity is bound to the account the user
178
+ signed in with (their email); the wallet + spend limits are theirs. Speak in terms
179
+ of "your agent / your account / the limits you approved," never a shared identity.
180
+
181
+ The paid wallet keeps working regardless of the account's spend flag — see "What you
182
+ can do once paired." Missing **spend** blocks _checkout mandates_, not local x402 pay.
183
+
184
+ ## Core flow
185
+
186
+ - [ ] Start the pairing with `pair_agent_start`, `enroll_agent` action `start`, or
187
+ `visa agent enroll --format json`.
188
+ - [ ] Present the authorization URL, stable agent ID, and full public fingerprint to the human.
189
+ - [ ] Poll with `pair_agent_poll`, `enroll_agent` action `claim`, or
190
+ `visa agent enroll-claim --format json`.
191
+ - [ ] Report the stable `agentId` and that the identity is paired on this runtime.
192
+
193
+ ### 1. Start
194
+
195
+ Start once. If there is already a pending pairing, poll it before creating another.
196
+
197
+ The result provides `browserUrl`, stable `agentId`, and `requestKeyFingerprint`. Show the
198
+ URL as a bare, tappable value on its own line. Do not decorate it as a Markdown link or put
199
+ it in a code span; chat clients reliably recognize the bare URL. Show the complete
200
+ fingerprint without truncation and tell the human to approve only when every character
201
+ matches the browser review page.
202
+
203
+ Use this concise shape:
204
+
205
+ > 🔐 Pair your Visa agent — open this authorization page:
206
+ >
207
+ > 👉 &lt;browserUrl, bare and on its own line&gt;
208
+ >
209
+ > Stable agent ID: &lt;agentId&gt;
210
+ >
211
+ > Public request-key fingerprint — compare every character in the browser:
212
+ > &lt;requestKeyFingerprint, complete and untruncated&gt;
213
+ >
214
+ > Approve only if the fingerprint matches, then tell me when it is finished. The link
215
+ > expires shortly.
216
+
217
+ Do not ask the human for a code, secret, private key, token, or signed message. The URL,
218
+ stable agent ID, and public fingerprint are review values, not claim credentials.
219
+
220
+ ### 2. Poll
221
+
222
+ Poll the same pending pairing. Interpret results as follows:
223
+
224
+ - `activated` — pairing is complete. Continue to the completion report.
225
+ - `not_ready` with `likelyExpired: false` — the human has not finished. Wait and poll
226
+ again, using bounded retries rather than an endless loop.
227
+ - `not_ready` with `likelyExpired: true` — the authorization window probably expired.
228
+ Start a fresh pairing.
229
+ - `no_pending` — this runtime has no resumable pairing. Start a fresh pairing.
230
+ - `error` — surface the error without exposing local pending data. Retry once if it is a
231
+ transient network failure; otherwise stop and ask the human to start again.
232
+
233
+ ### 3. Report completion
234
+
235
+ On `activated`, report the display name when present and the stable `agentId`. You may
236
+ also report `identityKeyJkt` as the current key fingerprint, but label it clearly as a
237
+ rotatable key identifier.
238
+
239
+ Use precise completion language:
240
+
241
+ > Visa agent &lt;displayName&gt; is paired to this runtime. Stable agent ID: &lt;agentId&gt;.
242
+
243
+ Do not claim that activation configured payments, email, tap bindings, or any other
244
+ product capability. Those are separate follow-up configuration flows.
245
+
246
+ ## Interruption and replay safety
247
+
248
+ The runtime persists its v2 pending record before sending the signed claim. If a request
249
+ or response is interrupted, the next poll resumes the exact same `pairingId`, `agentId`,
250
+ Ed25519 identity, and claim material. This makes an identical retry safe and avoids
251
+ creating a second identity because a response was lost.
252
+
253
+ The pending record remains until the activated agent record has been written durably.
254
+ Therefore:
255
+
256
+ - Poll before starting over.
257
+ - Do not delete or edit pending files to fix a transient failure.
258
+ - Do not regenerate keys for an existing pairing.
259
+ - Do not copy pending state between runtimes.
260
+
261
+ ## Optional `.visa` mesh binding (separate from pairing)
262
+
263
+ Pairing does not register a `.visa` name, TAP key, or Subway peer. If the operator has
264
+ separately enabled and registered those channel bindings, the mounted `visa-cli` MCP server
265
+ may expose `subway_register`, `subway_send`, `subway_inbox`, and `subway_find`.
266
+
267
+ Mesh messaging is available only on a compatible RC/dev build with `SUBWAY_MESH=visa` and
268
+ a reachable `SUBWAY_RELAY_MULTIADDR`. If those tools or the relay are unavailable, report
269
+ that clearly and stop. Do not imply that identity pairing alone granted directory or
270
+ messaging authority, and do not improvise another transport.
271
+
272
+ ## Optional checkout profile (separate from pairing)
273
+
274
+ Pairing does not enable card checkout. If the operator has separately provisioned card
275
+ authority, enabled `checkout_agent_access`, and opted the MCP server into submission with
276
+ `CHECKOUT_AGENT_ALLOW_SUBMIT=1`, the experimental `pay_merchant` flow also needs a local
277
+ `~/.visa-mcp/contact.json` file. Collect every value from the human before the first review;
278
+ never infer or invent identity or address data. Write the file with mode `0600`.
279
+
280
+ ```jsonc
281
+ {
282
+ "fullName": "Ada Lovelace",
283
+ "email": "ada@example.com",
284
+ "addressLine1": "1 Analytical Way",
285
+ "addressLine2": "",
286
+ "city": "San Francisco",
287
+ "state": "CA",
288
+ "postalCode": "94105",
289
+ "country": "US",
290
+ }
291
+ ```
292
+
293
+ `fullName` must be non-blank; `firstName` plus `lastName` is also accepted. The engine reads
294
+ the exact keys `fullName`, `firstName`, `lastName`, `email`, `addressLine1`, `addressLine2`,
295
+ `city`, `state`, `postalCode`, and `country`. The profile supplies checkout/cardholder and
296
+ billing data only. Its `email` value is not the account's verified owner email, an agent
297
+ mailbox, key proof, recovery factor, or permission to spend.
298
+
299
+ ## Security rules
300
+
301
+ - Never read, print, log, paste, or transmit the private Ed25519 JWK or local claim token.
302
+ - Never read or echo the pending pairing file. Present only the authorization URL returned
303
+ by the supported command or tool.
304
+ - Never treat `identityKeyJkt` as the stable identity. Use `agentId` for references and
305
+ persistence.
306
+ - Never fetch the authorization URL on the human's behalf. The human reviews and approves
307
+ it in their browser.
308
+ - Never invent a secondary pairing path when polling fails. Preserve the pending state,
309
+ surface the error, and retry or restart through the same canonical enrollment flow.
310
+
311
+ ## Further docs
312
+
313
+ - `RUNTIMES.md` — OpenClaw, Hermes, and raw CLI setup.
314
+ - `docs/agents/ARCHITECTURE.md` — where enrollment sits in the v4 request paths.
315
+ - `visacli.sh/agents` — product-facing agent documentation.
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env node
2
+ // Portable provisioner for the pair-visa-agent skill.
3
+ //
4
+ // Ensures the `visa` CLI is installed so ANY Agent Skills runtime can pair —
5
+ // not just OpenClaw (whose `metadata.openclaw.install` auto-runs). Hermes,
6
+ // Claude Code, and any other agentskills.io-compatible runtime run this bundled
7
+ // script per the standard's `scripts/` execution stage.
8
+ //
9
+ // Safe to run repeatedly: it no-ops when `visa` already resolves. Pinned to @rc
10
+ // because the v4 agent surface is prerelease (the @latest tag predates the
11
+ // `visa agent` commands); drop the tag once 4.1.0 is promoted to latest.
12
+
13
+ import { execSync } from 'node:child_process'
14
+
15
+ function resolves(cmd) {
16
+ try {
17
+ execSync(`${cmd} --version`, { stdio: 'ignore' })
18
+ return true
19
+ } catch {
20
+ return false
21
+ }
22
+ }
23
+
24
+ if (resolves('visa') || resolves('visa-cli')) {
25
+ console.log('✓ visa CLI already installed — nothing to do. Run the pairing flow in SKILL.md.')
26
+ process.exit(0)
27
+ }
28
+
29
+ console.log('Installing @visa/cli@rc (the v4 agent surface is prerelease)…')
30
+ try {
31
+ execSync('npm install -g @visa/cli@rc', { stdio: 'inherit' })
32
+ } catch {
33
+ console.error(
34
+ 'Global install failed. Try `npm install -g @visa/cli@rc` manually (may need sudo, or set a\n' +
35
+ 'user-writable npm prefix: `npm config set prefix ~/.npm-global` and add its `bin` to PATH).'
36
+ )
37
+ process.exit(1)
38
+ }
39
+
40
+ if (!resolves('visa') && !resolves('visa-cli')) {
41
+ console.error(
42
+ 'Installed, but `visa` is not on PATH. Ensure your npm global bin dir is on PATH\n' +
43
+ '(`npm bin -g` shows it), then re-run this script.'
44
+ )
45
+ process.exit(1)
46
+ }
47
+
48
+ console.log('✓ visa CLI ready. Now run the pairing flow in SKILL.md.')
package/install.ps1 CHANGED
@@ -168,7 +168,6 @@ if ($npmExitCode -ne 0) {
168
168
  # Verify
169
169
  $cliCommandNames = Get-InstalledCliCommands
170
170
  $verifiedCommand = $null
171
- $verifiedCommandPath = $null
172
171
  $visaVersion = $null
173
172
 
174
173
  foreach ($commandName in $cliCommandNames) {
@@ -177,12 +176,9 @@ foreach ($commandName in $cliCommandNames) {
177
176
  continue
178
177
  }
179
178
 
180
- # Capture the resolved executable path so the setup hand-off below runs
181
- # exactly the binary verified here, not a fresh PATH lookup.
182
179
  $versionOutput = (& $commandInfo.Source --version 2>$null | Select-Object -First 1)
183
180
  if ($LASTEXITCODE -eq 0 -and $versionOutput) {
184
181
  $verifiedCommand = $commandName
185
- $verifiedCommandPath = $commandInfo.Source
186
182
  $visaVersion = $versionOutput.Trim()
187
183
  break
188
184
  }
@@ -191,46 +187,12 @@ foreach ($commandName in $cliCommandNames) {
191
187
  Write-Host ""
192
188
  if ($verifiedCommand) {
193
189
  Write-Host " Visa CLI $visaVersion installed." -ForegroundColor Green
194
-
195
- # Hand off straight into setup so install -> setup -> signed-in is one
196
- # uninterrupted flow. Hardening:
197
- # * Auto-launch only on an interactive console with input/output/error
198
- # all attached - setup must prompt and open a browser. Redirected
199
- # streams and CI fall back to printing the next step.
200
- # * Invoke $verifiedCommandPath (the path verified just above), not a
201
- # bare command name re-resolved through PATH.
202
- # * Pass only the literal "setup" argument - nothing caller-controlled.
203
- if ($Host.Name -eq 'ConsoleHost' -and -not [Console]::IsInputRedirected -and -not [Console]::IsOutputRedirected -and -not [Console]::IsErrorRedirected -and -not $env:CI) {
204
- Write-Host ""
205
- Write-Host " Continuing to setup..." -ForegroundColor Cyan
206
- Write-Host ""
207
- try {
208
- $setupProcess = Start-Process -FilePath $verifiedCommandPath -ArgumentList @('setup') -Wait -NoNewWindow -PassThru -ErrorAction Stop
209
- } catch {
210
- Write-Host ""
211
- Write-Host " Setup could not start. Visa CLI is installed." -ForegroundColor Yellow
212
- Write-Host " PowerShell error: $($_.Exception.Message)" -ForegroundColor Yellow
213
- Write-Host " run '$verifiedCommand setup' when you're ready to finish." -ForegroundColor Yellow
214
- Wait-BeforeExit
215
- exit 1
216
- }
217
- if ($setupProcess.ExitCode -ne 0) {
218
- Write-Host ""
219
- Write-Host " Setup exited before completion. Visa CLI is installed." -ForegroundColor Yellow
220
- Write-Host " run '$verifiedCommand setup' when you're ready to finish." -ForegroundColor Yellow
221
- Wait-BeforeExit
222
- exit 1
223
- }
224
- exit 0
225
- } else {
226
- Write-Host " Run '$verifiedCommand setup' to get started." -ForegroundColor Cyan
227
- Write-Host " After setup, run /mcp inside Claude Code, not PowerShell, if Claude Code was already open." -ForegroundColor Cyan
228
- }
190
+ Write-Host " Connect an AI client with: $verifiedCommand connect <client>" -ForegroundColor Cyan
191
+ Write-Host " Then ask your agent to call enroll_agent." -ForegroundColor Cyan
229
192
  Write-Host ""
230
193
  } else {
231
194
  $primaryCommand = $cliCommandNames | Select-Object -First 1
232
195
  Write-Host " Installed but '$primaryCommand' was not runnable from PATH yet." -ForegroundColor Yellow
233
- Write-Host " Close and reopen PowerShell, then run: $primaryCommand setup" -ForegroundColor Yellow
234
- Write-Host " Run /mcp inside Claude Code after setup if you need to reconnect the MCP server." -ForegroundColor Yellow
196
+ Write-Host " Close and reopen PowerShell, then run: $primaryCommand connect <client>" -ForegroundColor Yellow
235
197
  Write-Host ""
236
198
  }
package/install.sh CHANGED
@@ -99,9 +99,6 @@ fi
99
99
  echo "$NPM_OUTPUT"
100
100
 
101
101
  # ── verify ────────────────────────────────────────────────────────────────────
102
- # Capture the absolute path resolved here so the setup hand-off below invokes
103
- # exactly the binary we just verified, instead of re-resolving "visa-cli"
104
- # through $PATH a second time.
105
102
  VISA_BIN=""
106
103
  VISA_VERSION=""
107
104
  if VISA_BIN="$(command -v visa-cli 2>/dev/null)"; then
@@ -111,40 +108,11 @@ fi
111
108
  echo ""
112
109
  if [ -n "$VISA_VERSION" ]; then
113
110
  ok "Visa CLI ${VISA_VERSION} installed."
114
- # Hand off straight into setup so install -> setup -> signed-in is one
115
- # uninterrupted flow. Hardening:
116
- # * Auto-launch only when output streams are real terminals and setup can
117
- # read from either stdin or /dev/tty. That keeps `curl ... | bash` usable:
118
- # the script arrives on stdin, while setup prompts still read from the
119
- # user's terminal. CI and redirected output print the next step instead.
120
- # * Invoke "$VISA_BIN" (the path verified just above), never a bare
121
- # "visa-cli" re-resolved through $PATH at call time.
122
- # * Pass only the literal "setup" argument — "$@" is never forwarded — so
123
- # nothing the script's caller controls reaches the installed binary.
124
- if [ -t 1 ] && [ -t 2 ] && { [ -t 0 ] || [ -r /dev/tty ]; }; then
125
- echo ""
126
- info "Continuing to setup..."
127
- echo ""
128
- SETUP_EXIT=0
129
- if [ -t 0 ]; then
130
- "$VISA_BIN" setup || SETUP_EXIT=$?
131
- else
132
- "$VISA_BIN" setup </dev/tty || SETUP_EXIT=$?
133
- fi
134
- if [ "$SETUP_EXIT" -ne 0 ]; then
135
- echo ""
136
- warn "Setup exited before completion. Visa CLI is installed."
137
- warn "run 'visa-cli setup' when you're ready to finish."
138
- exit 1
139
- fi
140
- exit 0
141
- else
142
- info "Run 'visa-cli setup' to get started."
143
- info "After setup, run /mcp inside Claude Code, not Terminal, if Claude Code was already open."
144
- fi
111
+ info "Connect an AI client with: visa-cli connect <client>"
112
+ info "Then ask your agent to call enroll_agent."
145
113
  else
146
114
  warn "Installed, but 'visa-cli' was not found on PATH."
147
- warn "You may need to restart your shell, then run: visa-cli setup"
115
+ warn "Restart your shell, then run: visa-cli connect <client>"
148
116
  fi
149
117
  echo ""
150
118
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@visa/cli",
3
- "version": "4.1.0-rc.6",
4
- "description": "AI-powered payments for Claude Code",
3
+ "version": "4.1.0-rc.61",
4
+ "description": "Visa CLI runtime for stable agent identity and separately authorized payment capabilities",
5
5
  "bin": {
6
6
  "visa-cli": "./bin/visa-cli.js",
7
7
  "visa": "./bin/visa-cli.js"
@@ -9,7 +9,7 @@
9
9
  "scripts": {
10
10
  "sync:server-json": "node scripts/sync-server-json.mjs",
11
11
  "check:server-json": "node scripts/sync-server-json.mjs --check",
12
- "prebuild": "node scripts/sync-server-json.mjs && pnpm --filter @visa/money build && pnpm --filter @visa/crypto build && pnpm --filter subway-sdk build && pnpm --filter @visa-cli/tools build && pnpm --filter @visa/identity build && pnpm --filter @visa/wallet build && pnpm --filter @visa/wallet-tools build",
12
+ "prebuild": "node scripts/sync-server-json.mjs && pnpm --filter @visa/shared build && pnpm --filter @visa/observability build && pnpm --filter @visa/money build && pnpm --filter @visa/crypto build && pnpm --filter subway-sdk build && pnpm --filter @visa-cli/tools build && pnpm --filter @visa/identity build && pnpm --filter @visa/wallet build && pnpm --filter @visa/agent-mail build && pnpm --filter @visa/wallet-tools build && pnpm --filter @visa/checkout-engine build",
13
13
  "build": "tsc --noEmit && node esbuild.config.js",
14
14
  "prepack": "node scripts/sync-server-json.mjs --check",
15
15
  "dev": "tsc --watch",
@@ -22,7 +22,6 @@
22
22
  "test:smoke": "VISA_AUTH_URL=https://auth.visacli.sh jest --config jest.smoke.config.js",
23
23
  "test:integration": "jest --config jest.integration.config.js",
24
24
  "test:e2e": "jest --config jest.e2e.config.js",
25
- "test:catalog-e2e": "jest --config jest.catalog-e2e.config.js",
26
25
  "test:all": "npm run test:unit && npm run test:integration && npm run test:e2e",
27
26
  "prepublishOnly": "npm run build && npm test",
28
27
  "lint": "eslint src/**/*.ts",
@@ -43,6 +42,7 @@
43
42
  "license": "SEE LICENSE IN LICENSE",
44
43
  "dependencies": {
45
44
  "@modelcontextprotocol/sdk": "^1.0.0",
45
+ "@ucp-js/sdk": "0.4.1",
46
46
  "commander": "^12.1.0",
47
47
  "zod": "^3.23.0"
48
48
  },
@@ -53,10 +53,14 @@
53
53
  "@chainsafe/libp2p-noise": "^17.0.0",
54
54
  "@chainsafe/libp2p-yamux": "^8.0.1",
55
55
  "@multiformats/multiaddr": "^13.0.3",
56
- "uint8arrays": "^6.1.1"
56
+ "uint8arrays": "^6.1.1",
57
+ "playwright-core": "^1.48.2"
57
58
  },
58
59
  "devDependencies": {
60
+ "@visa/agent-mail": "workspace:*",
61
+ "@visa/checkout-engine": "workspace:*",
59
62
  "@visa/crypto": "workspace:*",
63
+ "@visa/identity": "workspace:*",
60
64
  "subway-sdk": "workspace:*",
61
65
  "@visa/money": "workspace:*",
62
66
  "@visa/wallet": "workspace:*",
@@ -67,8 +71,8 @@
67
71
  "@changesets/cli": "^2.31.0",
68
72
  "@types/jest": "^30.0.0",
69
73
  "@types/node": "^26.1.0",
70
- "@typescript-eslint/eslint-plugin": "^8.63.0",
71
- "@typescript-eslint/parser": "^8.63.0",
74
+ "@typescript-eslint/eslint-plugin": "^8.65.0",
75
+ "@typescript-eslint/parser": "^8.65.0",
72
76
  "@types/express": "^5.0.0",
73
77
  "esbuild": "^0.28.1",
74
78
  "express": "^4.21.0",
package/server.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json",
3
3
  "name": "io.github.visa-crypto-labs/visa-cli",
4
- "version": "4.1.0-rc.6",
4
+ "version": "4.1.0-rc.61",
5
5
  "title": "Visa CLI",
6
- "description": "AI-powered payments and creative tools for coding agents. Generate images, music, video, query crypto prices, and make purchases all from your AI coding assistant.",
6
+ "description": "Pair a human-approved agent identity, configure payment capabilities separately, and discover and pay x402 services from your AI coding assistant.",
7
7
  "websiteUrl": "https://github.com/Visa-Crypto-Labs/Visa-mono/tree/main/packages/cli#readme",
8
8
  "packages": [
9
9
  {
10
10
  "registryType": "npm",
11
11
  "identifier": "@visa/cli",
12
- "version": "4.1.0-rc.6",
12
+ "version": "4.1.0-rc.61",
13
13
  "transport": {
14
14
  "type": "stdio"
15
15
  },