stripe-link-wallet
The stripe-link-wallet skill enables an assistant to spend money on a user's behalf by composing spend requests through the Stripe Link CLI wallet. When the user approves spending in the Link app on their device, the CLI issues one-time-use payment credentials to complete purchases, support Machine Payment Protocol endpoints, and cap agent spending with audit trails. It automatically intercepts checkout URLs and payment sessions across various flows rather than surfacing them to the user.
git clone --depth 1 https://github.com/vellum-ai/vellum-assistant /tmp/stripe-link-wallet && cp -r /tmp/stripe-link-wallet/skills/stripe-link-wallet ~/.claude/skills/stripe-link-walletSKILL.md
# Stripe Link Wallet Spend on the user's behalf using the [Stripe Link CLI](https://github.com/stripe/link-cli). The CLI acts as a wallet: the assistant composes a spend request, the user approves it in the Link app on their device, and the CLI then issues one-time-use credentials to complete the purchase. Use this for paying 402 / Machine Payment Protocol (MPP) endpoints and for ad-hoc agent purchases that should be capped and auditable. ## Required tools - `bash` for all `link-cli` invocations. Use `host_bash` only if a specific flow genuinely requires host-level access (e.g. reading a local file the user has on their machine). ## Hard constraints - Always pass `--request-approval` on `spend-request create`. The Link app approval is the consent surface — it is non-negotiable. No spending happens without it. - Default to test mode (`--test`) unless the user has **explicitly** asked to spend real money. When unsure, ask in chat before dropping `--test`. - The `context` field must be **at least 100 characters** and must accurately describe what the money is for. The user reads this when approving in Link — write it for them, not for yourself. - Always use `--format json` on every command. The default interactive Ink output is for humans, not agents. Exception: `demo` and `onboard` require a TTY and have no JSON mode. - **Amount is in cents.** $10.00 = `--amount 1000`. Maximum is 50,000 cents ($500). - Never log or repeat raw card credentials (PAN, CVC) in the conversation. Always use `--output-file` when retrieving card credentials. --- ## Checkout interception — always active Whenever **any** flow (MCP tool, API call, web request, or otherwise) produces a checkout URL, hosted payment page, or payment session that would otherwise be handed to the user to click through — **intercept it**. Route the payment through Stripe Link instead. Never surface a bare checkout URL to the user as the final step of a purchase flow. **Decision tree:** 1. **MPP / HTTP 402 endpoint** — Flow A (Shared Payment Token) 2. **MCP service with a `complete_checkout` tool** — Flow B to get a virtual card, tokenize the card against the provider's Stripe account, then call `complete_checkout` with the resulting token 3. **Standard web checkout (no payment API)** — Flow B to get a virtual card, then use a browser automation skill to fill the card into the checkout form **For MCP-based checkouts (e.g. PostalForm):** - After retrieving the virtual card from `--output-file`, create a Stripe PaymentMethod via `POST /v1/payment_methods` using the merchant's publishable key (extract from the checkout URL or session if present), then pass the resulting `pm_xxx` token to the MCP's `complete_checkout` tool. - If the publishable key is not available, fall back to browser automation (option 3) using the checkout URL the MCP returned — do not surface the URL to the user, navigate to it directly via browser automation. **Never skip this step.** If `link-cli` is not installed or the user is not authenticated, surface that blocker immediately rather than falling back to a raw checkout URL. --- ## Step 0: Check installation and auth ```bash if command -v link-cli >/dev/null; then link-cli auth status --format json else bunx @stripe/link-cli auth status --format json fi ``` - `link-cli` missing — use `bunx @stripe/link-cli` for Step 0 and every command below. - Exit 0 but `"authenticated": false` — fall to **Setup: login**. - Authenticated — proceed to the requested flow. - `"update"` key present in auth status — mention the update to the user but don't block on it. --- ## Setup ### If `link-cli` is missing Invoke the CLI on demand with `bunx`: ```bash bunx @stripe/link-cli <subcommand> ``` In every example below, substitute `bunx @stripe/link-cli` wherever you see `link-cli`. ### If installed but not authenticated Use your own assistant name for `--client-name` — read it from `IDENTITY.md`. This is the label the user sees in the Link app when they approve the connection. ```bash link-cli auth login --client-name "<your assistant name>" ``` Opens a browser flow. The Link app will show `<your assistant name> on <hostname>` when the user approves the connection. After it completes, re-run Step 0. ### Introspecting the CLI If you need the exact flags for a subcommand not covered below: ```bash link-cli --llms-full # all commands, LLM-friendly link-cli spend-request create --schema # full schema for one command link-cli <command> --help ``` --- ## Pre-flight: get a payment method ID Every spend request needs a `--payment-method-id`. Retrieve the user's saved methods first: ```bash link-cli payment-methods list --format json ``` If the user has multiple, ask which one to use. If they have none, direct them to [app.link.com/wallet](https://app.link.com/wallet) to add one first. --- ## Common flows ### Flow A: Pay a 402 / MPP-protected URL Use this when the target endpoint returns HTTP 402 and requires a Shared Payment Token (SPT). **1. Decode the challenge (optional but useful for diagnosing)** ```bash link-cli mpp decode \ --challenge 'Payment id="ch_001", realm="merchant.example", method="stripe", ...' ``` Extracts the `network_id` and other challenge fields. Use when the URL is unfamiliar or the challenge looks malformed. **2. Create the spend request** ```bash link-cli spend-request create \ --payment-method-id <id> \ --merchant-name "<merchant>" \ --merchant-url "<url>" \ --context "<min-100-char description of what is being purchased and why>" \ --amount <cents> \ --credential-type "shared_payment_token" \ --line-item "name:<item>,unit_amount:<cents>,quantity:<n>" \ --total "type:total,display_text:Total,amount:<cents>" \ --request-approval \ --test \ --format json ``` Drop `--test` only if the user has explicitly asked to spend real money — and say so in chat before running. > **Important — JSON mode does not block.** With `--format json
>
>
>
>
Check Vellum Assistant architecture and package boundaries. Use when editing imports, moving code, adding endpoints, touching assistant/gateway/client/skill boundaries, or reviewing architecture-sensitive changes.
Review Vellum Assistant code changes for correctness, repo-specific quality rules, security risks, and missing validation. Use when reviewing diffs, preparing a PR, finishing implementation work, or when the user asks for a code review, quality pass, or pre-merge check in this repository.
Guide Vellum Assistant feature flag changes and rollout hygiene. Use when adding, editing, reviewing, or documenting assistant feature flags, rollout-gated behavior, or platform flag follow-up work.
Validate Vellum Assistant database and workspace migrations. Use when adding, editing, reviewing, or testing migrations, release-note migrations, persisted schemas, workspace file formats, or data backfills.