diff --git a/docs.json b/docs.json
index d4c2b4a..7587d43 100644
--- a/docs.json
+++ b/docs.json
@@ -112,6 +112,7 @@
{
"group": "Reference",
"pages": [
+ "sdk/cli",
"sdk/create-client",
"sdk/examples"
]
diff --git a/sdk/cli.mdx b/sdk/cli.mdx
new file mode 100644
index 0000000..faaa55e
--- /dev/null
+++ b/sdk/cli.mdx
@@ -0,0 +1,204 @@
+---
+title: "CLI"
+description: "One-shot command-line tool for paying x402 endpoints. Wallet-agnostic with zero provider dependencies."
+icon: "terminal"
+---
+
+`@x402r/cli` makes a single x402 payment from the command line. You point it at a URL, provide a signer, and get back the response body plus a settlement transaction hash.
+
+The CLI carries zero provider SDK dependencies. Raw private keys, JSON-RPC signers (Privy, Turnkey, Fireblocks, Safe), and custom signer modules all work through the same interface.
+
+### Install
+
+
+```bash npm
+npx @x402r/cli pay [options]
+```
+```bash pnpm
+pnpm dlx @x402r/cli pay [options]
+```
+```bash bun
+bunx @x402r/cli pay [options]
+```
+
+
+No project install required. Pin the version (e.g. `@x402r/cli@0.2.0`) for reproducible agent workflows.
+
+### Usage
+
+```bash
+x402r pay [signer flags] [--chain ] [--rpc ] [--max-amount N] [--json]
+```
+
+If the URL does not return HTTP 402, the CLI short-circuits and prints the response body with exit code 0. No payment is made.
+
+### Signer configuration
+
+Exactly one signer source must be configured. CLI flags take precedence over environment variables. If zero or multiple sources are detected, the CLI exits with code 6.
+
+| Source | Flag | Env var |
+|--------|------|---------|
+| Raw private key | `--key 0x...` | `PRIVATE_KEY` |
+| Remote JSON-RPC | `--signer-url ` and `--signer-address 0x...` | `SIGNER_URL` and `SIGNER_ADDRESS` |
+| Custom module | `--signer-module ` | `SIGNER_MODULE` |
+
+Environment variable names are unprefixed to match Foundry, Hardhat, and x402-reference conventions.
+
+### Request options
+
+| Flag | Description |
+|------|-------------|
+| `--chain ` | Select a specific `accepts[]` entry when the merchant offers multiple chains. Required when there are multiple options. |
+| `--rpc ` | Override the RPC URL for on-chain reads. Required for chain IDs not in `viem/chains`. |
+| `--max-amount ` | Refuse to pay more than `n` atomic token units. Exits with code 3 if the price exceeds this. |
+| `--json` | Emit a single JSON envelope to stdout instead of plain text. |
+
+### Exit codes
+
+| Code | Meaning |
+|------|---------|
+| 0 | Success |
+| 1 | Network error |
+| 2 | Malformed 402 response or unusable `accepts[]` |
+| 3 | Price exceeds `--max-amount` |
+| 4 | Signature rejected |
+| 5 | Settlement failed (merchant error after payment, or facilitator error) |
+| 6 | Signer resolution failed (none, multiple, or partially configured) |
+
+### Examples
+
+#### Raw private key
+
+```bash
+PRIVATE_KEY=0xabc123... npx @x402r/cli pay https://api.example.com/paid-endpoint
+```
+
+#### JSON-RPC signer
+
+Any endpoint that speaks `eth_signTypedData_v4` works: Privy wallet RPC, Turnkey, Fireblocks, Safe, a local `cast wallet` endpoint, or a hardware wallet behind an RPC bridge.
+
+```bash
+npx @x402r/cli pay https://api.example.com/paid-endpoint \
+ --signer-url https://signer.example/rpc \
+ --signer-address 0xYourAddress...
+```
+
+#### Custom module (Privy)
+
+```javascript privy-signer.js
+import { PrivyClient } from "@privy-io/server-auth";
+import { createViemAccount } from "@privy-io/server-auth/viem";
+
+export default async function () {
+ const privy = new PrivyClient(
+ process.env.PRIVY_APP_ID,
+ process.env.PRIVY_APP_SECRET
+ );
+ return createViemAccount({
+ walletId: process.env.PRIVY_WALLET_ID,
+ address: process.env.PRIVY_WALLET_ADDRESS,
+ privy,
+ });
+}
+```
+
+```bash
+npx @x402r/cli pay https://api.example.com/paid-endpoint \
+ --signer-module ./privy-signer.js
+```
+
+#### Custom module (Coinbase CDP)
+
+```javascript cdp-signer.js
+import { CdpClient } from "@coinbase/cdp-sdk";
+import { toAccount } from "viem/accounts";
+
+export default async function () {
+ const cdp = new CdpClient();
+ const acct = await cdp.evm.getOrCreateAccount({
+ name: process.env.CDP_ACCOUNT_NAME,
+ });
+ return toAccount(acct);
+}
+```
+
+```bash
+npx @x402r/cli pay https://api.example.com/paid-endpoint \
+ --signer-module ./cdp-signer.js
+```
+
+### JSON output
+
+With `--json`, the CLI writes a single JSON envelope to stdout:
+
+```json
+{
+ "body": "",
+ "status": 200,
+ "tx": "0x...",
+ "elapsedMs": 1234,
+ "signer": { "kind": "key", "address": "0x..." }
+}
+```
+
+The `signer` field is omitted when the URL returned a non-402 response (no payment was made).
+
+### Signer module contract
+
+A custom signer module must default-export a factory function with the signature `() => Promise`. The returned object must be a viem `Account` with at least `address` and `signTypedData`. The CLI only needs typed-data signatures, transaction broadcasting is handled by the facilitator.
+
+### Programmatic usage
+
+You can also use the `pay` function and `resolveSigner` directly from TypeScript:
+
+```typescript
+import { pay } from "@x402r/cli";
+import type { PayResult } from "@x402r/cli";
+
+const result: PayResult = await pay({
+ url: "https://api.example.com/paid-endpoint",
+ key: process.env.PRIVATE_KEY,
+ json: true,
+});
+
+console.log(result.body);
+console.log(result.tx);
+```
+
+
+The programmatic API uses the same `PayFlags` interface as the CLI binary. All options (chain, rpc, maxAmount, signer flags) are available.
+
+
+### Exports
+
+The `@x402r/cli` package exports:
+
+| Export | Type | Description |
+|--------|------|-------------|
+| `pay` | function | Execute a one-shot payment against a URL |
+| `resolveSigner` | function | Resolve a signer from flags and environment variables |
+| `CliError` | class | Base error class with typed exit codes |
+| `NetworkError` | class | Exit code 1 |
+| `Malformed402Error` | class | Exit code 2 |
+| `MaxAmountExceededError` | class | Exit code 3 |
+| `SignatureRejectedError` | class | Exit code 4 |
+| `SettlementError` | class | Exit code 5 |
+| `SignerResolutionError` | class | Exit code 6 |
+
+### Supported chains
+
+The CLI auto-detects the chain from the 402 response's `accepts[].network` field. Any EVM chain known to `viem/chains` works out of the box (Base, Base Sepolia, Ethereum, Arbitrum, Optimism, and others). For unknown chain IDs, pass `--rpc ` to provide an RPC endpoint.
+
+## Next steps
+
+
+
+ Use the SDK programmatically for richer payer workflows.
+
+
+ Accept payments and manage escrow releases.
+
+
+ Runnable examples for every SDK operation.
+
+
diff --git a/sdk/overview.mdx b/sdk/overview.mdx
index 4b43e59..80c91e4 100644
--- a/sdk/overview.mdx
+++ b/sdk/overview.mdx
@@ -62,9 +62,23 @@ bun add @x402r/helpers
```
+For one-shot payments from the command line (no project install required):
+
+
+```bash npm
+npx @x402r/cli pay [options]
+```
+```bash pnpm
+pnpm dlx @x402r/cli pay [options]
+```
+```bash bun
+bunx @x402r/cli pay [options]
+```
+
+
### Guides
-
+
Deploy an operator, accept a payment, release funds from escrow.
@@ -74,6 +88,9 @@ bun add @x402r/helpers
Review disputes, approve or deny refunds, distribute fees.
+
+ One-shot payments from the command line or scripts.
+
### Supported Chains