Link CLI lets agents get secure, one-time-use payment credentials from a Link wallet to complete purchases on your behalf — without storing your real card details.
The CLI can produce one of two credential types:
- A virtual card (PAN) for use with a standard web checkout form. The issued card works anywhere, and is not restricted to Link-enabled sellers or sellers that use Stripe.
- A Shared Payment Token (SPT) when the seller accepts programmatic payments through Machine Payment Protocols (MPP)
For now, this is only available to US Link accounts.
npm i -g @stripe/link-cliOr run directly with npx:
npx @stripe/link-cliInstall the skill:
npx skills add stripe/link-cliBy default when called from an agent (non-TTY), all commands use toon output — a compact, LLM-friendly text format. All commands accept --format [format] for structured output. Other formats: json, yaml, md, jsonl.
List available commands:
link-cli --llms-fullGet a command's full schema with --schema. Example:
link-cli spend-request create --schemaLink CLI can 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"]
}
}
}Run a guided onboarding and demo flow:
link-cli onboardThe link-cli requires a Link account. You can log in to your existing one or register online.
link-cli auth loginYou 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.
link-cli payment-methods listReturns 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, add new ones in Link.
Create a spend request with a payment method, 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-approvalThe --request-approval flag triggers a push notification to the user for approval, then polls until the request is approved or denied.
Easily approve requests with the Link app.
--line-item and --total use repeatable key:value format.
--line-item keys: name (required), quantity, unit_amount, description, sku, url, image_url, product_url
--line-item "name:Running Shoes,unit_amount:12000,quantity:1,description:Trail runners"--total keys: type (required; one of: subtotal, tax, total), display_text (required), amount (required)
--total "type:subtotal,display_text:Subtotal,amount:12000" \
--total "type:total,display_text:Total,amount:12000"By default, a spend request provisions a virtual card. For merchants that support the Machine Payments Protocol (HTTP 402) and the Stripe payment method, instead pass --credential-type "shared_payment_token".
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_001By default, retrieving a spend request doesn't include card details. Pass --include card to see unmasked card details.
To avoid leaking card credentials into agent transcripts or logs, use --output-file to write the full card to a secure local file while stdout shows only redacted data (brand, last4, expiry):
link-cli spend-request retrieve lsrq_001 --include card --output-file /tmp/link-card.json --format jsonThe file is created with 0600 permissions. If the file already exists, the command fails unless --force is passed. When --output-file is set, the JSON output replaces the card object with redacted fields and adds a card_output_file path.
For agent polling, pass --interval and optionally --max-attempts:
link-cli spend-request retrieve lsrq_001 --interval 2 --max-attempts 150Polling 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}'link-cli auth login --client-name "Claude Code" # identify the connecting agent
link-cli auth status # check auth status
link-cli auth logout # disconnectWhen you provide --client-name, the Link app displays it when you approve the connection — for example, Claude Code on my-macbook instead of link-cli on my-macbook.
auth status 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 (for example, in CI).
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 real payment methods.
# Update before approval
link-cli spend-request update lsrq_001 \
--merchant-url https://press.stripe.com/working-in-public
# Request approval separately (alternative to create --request-approval)
link-cli spend-request request-approval lsrq_001
# Retrieve at any time (includes card credentials after approval)
link-cli spend-request retrieve lsrq_001Use mpp pay to complete purchases on merchants that use the Machine Payments Protocol. The spend request must use credential_type: "shared_payment_token" and you must approve it before paying. 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"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="..."'| 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) |
Run the guided setup flow — authenticates, checks payment methods, shows the app download QR, and runs both demo flows:
link-cli onboardRun 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 onlypnpm install
pnpm run build
pnpm run link-cli --helpWatch mode:
pnpm run devRun tests:
pnpm run testType-check and lint:
pnpm run typecheck
pnpm biome check .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.
When you make a user-facing change, add a changeset before merging:
pnpm changesetFollow 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.
Once changesets have accumulated on main, create a version PR:
pnpm changeset versionThis consumes all pending changesets, bumps the version in packages/cli/package.json, and updates CHANGELOG.md.
After the version PR is merged:
pnpm run build
pnpm changeset publishThis 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.