Link CLI (GitHub Repo)
Stripe released Link CLI, a tool that lets AI agents complete purchases using secure, one-time payment credentials without ever accessing users' real card details.
Deep dive
- Agents create spend requests specifying merchant details, line items, and amounts, then receive one-time virtual card credentials (number, CVV, expiration) or shared payment tokens
- The
--request-approvalflag triggers push notifications or emails requiring explicit user consent before credentials are provisioned - Each spend request includes a context field requiring at least 100 characters explaining the purchase rationale to the user
- Supports two payment flows: traditional virtual cards for standard checkout forms, and Machine Payments Protocol (HTTP 402) for merchants with native support
- Runs as both a standalone CLI tool and an MCP (Model Context Protocol) server for integration with Claude and other agent platforms
- Spend requests have transaction limits (max $500/50,000 cents) and credentials expire after use or time limit
- Test mode allows development and integration testing without real payment methods using Stripe's test card
- Polling mechanisms let agents wait for user approval with configurable intervals and timeouts, exiting with specific error codes if requests remain pending
- Authentication flow shows the connecting agent name in the Link app (e.g., "Claude Code on my-macbook") for transparency
- The tool never stores or logs real card details—credentials are generated on-demand and scoped to specific merchants
Decoder
- Link: Stripe's digital wallet product that stores payment methods and generates secure credentials
- MCP (Model Context Protocol): A protocol that allows AI assistants like Claude to connect to external tools and services
- Spend request: A request for temporary payment credentials specifying merchant, amount, and context for user approval
- MPP (Machine Payments Protocol): An HTTP 402-based protocol for programmatic payments where merchants can request payment directly
- Shared payment token (SPT): A one-time-use payment token for MPP-compatible merchants, alternative to virtual card credentials
- Virtual card: A temporary card number with CVV and expiration generated specifically for one transaction
Original article
Link CLI
Link CLI lets agents get secure, one-time-use payment credentials from a Link wallet — so they can complete purchases on your behalf without ever storing your real card details.
Installation
npm i -g @stripe/link-cli
Or run directly with npx:
npx @stripe/link-cli
You can install the skill via npx skills add stripe/link-cli.
MCP Server
Link CLI can also run as a local MCP server. Add the following to your MCP client config (.mcp.json, etc.)
{
"mcpServers": {
"link": {
"command": "npx",
"args": ["@stripe/link-cli", "--mcp"]
}
}
}
Quickstart
Login
The link-cli requires a Link account. You can log in to your existing one or register online.
link-cli auth login
You'll receive a verification URL and a short phrase. Visit the URL, log in to your Link account, and enter the phrase to approve the connection.
List payment methods
link-cli payment-methods list
Returns the cards and bank accounts saved to your Link account. Use the id field as payment_method_id in the next step. If you have no payment methods, you can add new ones in Link.
Create a spend request
To request a secure, one-time payment credential from your Link wallet, you create a spend request. You specify a payment method in your account, as well as some merchant details, line items, and amounts.
link-cli spend-request create \
--payment-method-id csmrpd_xxx \
--merchant-name "Stripe Press" \
--merchant-url "https://press.stripe.com" \
--context "Purchasing 'Working in Public' from press.stripe.com. The user initiated this purchase through the shopping assistant." \
--amount 3500 \
--line-item "name:Working in Public,unit_amount:3500,quantity:1" \
--total "type:total,display_text:Total,amount:3500" \
--request-approval
The --request-approval flag triggers a push notification (or email) to the user for approval, then polls until the request is approved or denied.
Users can easily approve requests with the Link app.
Credential types
By default, a spend request provisions a virtual card. For merchants that support the Machine Payments Protocol (HTTP 402) and the Stripe payment method, you can instead include --credential-type "shared_payment_token".
Execute payment
The approved spend request includes a card object with number, cvc, exp_month, exp_year, billing_address, and valid_until. Enter these into the merchant's checkout form.
link-cli spend-request retrieve lsrq_001 --format json
By default, retrieving a spend request will not include card details. Use the --include=card to see unmasked card details.
For agent polling, pass --interval and optionally --max-attempts:
link-cli spend-request retrieve lsrq_001 --interval 2 --max-attempts 150 --format json
Polling exits successfully only after the request reaches a terminal status such as approved, denied, or expired. If polling reaches --timeout or exhausts --max-attempts while the request is still non-terminal, the command exits non-zero with code: "POLLING_TIMEOUT" so callers do not treat a still-pending request as complete.
If the merchant supports MPP, use link-cli mpp pay instead:
link-cli mpp pay https://climate.stripe.dev/api/contribute \
--spend-request-id lsrq_001 \
--method POST \
--data '{"amount":100}' \
--format json
Advanced
Authentication
link-cli auth login --client-name "Claude Code" --format json # identify the connecting agent
link-cli auth status --format json # check auth status
link-cli auth logout --format json # disconnect
When --client-name is provided, the name is shown in the Link app when the user approves the connection — e.g. Claude Code on my-macbook instead of link-cli on my-macbook.
auth status --format json includes an update field when a newer version is available:
{
"authenticated": true,
"update": {
"current_version": "0.1.2",
"latest_version": "0.2.0",
"update_command": "npm install -g @stripe/link-cli"
}
}
Set NO_UPDATE_NOTIFIER=1 to suppress update checks (e.g. in CI).
Spend request lifecycle
A spend request moves through: create → request approval → approved (with credentials).
Required fields for create: payment_method_id, merchant_name, merchant_url, context, amount
Constraints: context must be at least 100 characters; amount must not exceed 50000 (cents); currency must be a 3-letter ISO code. Test mode: Pass --test to create testmode credentials (uses test card 4242424242424242). Useful for development and integration testing without using real payment methods.
# Update before approval
link-cli spend-request update lsrq_001 \
--merchant-url https://press.stripe.com/working-in-public \
--format json
# Request approval separately (alternative to create --request-approval)
link-cli spend-request request-approval lsrq_001 --format json
# Retrieve at any time (includes card credentials once approved)
link-cli spend-request retrieve lsrq_001 --format json
Output formats
All commands accept --format json for structured JSON output. Other formats: yaml, md, jsonl, toon (default). Errors are returned as JSON with code and message fields, with exit code 1.
MPP
Use mpp pay to complete purchases on merchants that use the Machine Payments Protocol. The spend request must use credential_type: "shared_payment_token" and be approved. The SPT is one-time-use — if payment fails, create a new spend request.
link-cli mpp pay https://climate.stripe.dev/api/contribute \
--spend-request-id lsrq_001 \
--method POST \
--data '{"amount":100}' \
--header "X-Custom: value" \
--format json
Use mpp decode to validate a raw WWW-Authenticate header and extract the network_id needed for shared_payment_token spend requests:
link-cli mpp decode \
--challenge 'Payment id="ch_001", realm="merchant.example", method="stripe", intent="charge", request="..."' \
--format json
Environment variables
| Variable | Effect |
|---|---|
LINK_API_BASE_URL |
Override the API base URL |
LINK_AUTH_BASE_URL |
Override the auth base URL |
LINK_HTTP_PROXY |
Route all requests through an HTTP proxy (requires undici) |
Onboard
Run the guided setup flow — authenticates, checks payment methods, shows the app download QR, and walks through both demo flows:
link-cli onboard
Demo
Run an interactive demo of both Link payment flows (always uses test mode — no real charges):
link-cli demo # shows menu to choose flow
link-cli demo --only-card # virtual card flow only
link-cli demo --only-spt # machine payment (SPT) flow only
Development
pnpm install
pnpm run build
pnpm run link-cli --help
Watch mode:
pnpm run dev
Run tests:
pnpm run test
Type-check and lint:
pnpm run typecheck
pnpm biome check .
Releasing
This project uses Changesets to manage versioning and publishing. Only @stripe/link-cli is published to npm — internal packages (@stripe/link-sdk, @stripe/link-typescript-config) are ignored by changesets.
Add a changeset
When you make a user-facing change, add a changeset before merging:
pnpm changeset
Follow the prompts to select the package (@stripe/link-cli) and the semver bump type (patch, minor, or major). This creates a markdown file in .changeset/ describing the change.
Version
Once changesets have accumulated on main, create a version PR:
pnpm changeset version
This consumes all pending changesets, bumps the version in packages/cli/package.json, and updates CHANGELOG.md.
Publish
After the version PR is merged:
pnpm run build
pnpm changeset publish
This publishes @stripe/link-cli to npm. CI also runs pnpm --filter @stripe/link-cli publish --dry-run --no-git-checks on every push to main to verify the package is publishable.