> ## Documentation Index
> Fetch the complete documentation index at: https://docs.x402r.org/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI

> One-shot command-line tool for paying x402 endpoints. Wallet-agnostic with zero provider dependencies.

`@x402r/cli` makes a single x402 payment from the command line. You point it at an address, 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

<CodeGroup>
  ```bash npm theme={null}
  npx @x402r/cli pay <url> [options]
  ```

  ```bash pnpm theme={null}
  pnpm dlx @x402r/cli pay <url> [options]
  ```

  ```bash bun theme={null}
  bunx @x402r/cli pay <url> [options]
  ```
</CodeGroup>

No project install required. Pin the version (for example, `@x402r/cli@0.2.0`) for reproducible scripted workflows.

### Usage

```bash theme={null}
x402r pay <url> [signer flags] [--chain <eip155:id>] [--rpc <url>] [--max-amount N] [--json]
```

If the endpoint does not return HTTP 402, the CLI short-circuits and prints the response body with exit code 0. The CLI sends no payment.

### Signer configuration

Configure exactly one signer source. CLI flags take precedence over environment variables. If the CLI finds zero or more than one source, it exits with code 6.

| Source          | Flag                                              | Environment variable              |
| --------------- | ------------------------------------------------- | --------------------------------- |
| Raw private key | `--key 0x...`                                     | `PRIVATE_KEY`                     |
| Remote JSON-RPC | `--signer-url <url>` and `--signer-address 0x...` | `SIGNER_URL` and `SIGNER_ADDRESS` |
| Custom module   | `--signer-module <pkg-or-path>`                   | `SIGNER_MODULE`                   |

Environment variable names use no `X402R_` prefix to match Foundry, Hardhat, and x402-reference conventions.

### Request options

| Flag                                         | Description                                                                                                                                       |
| -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--chain <eip155:id>`                        | Select a specific `accepts[]` entry when the merchant offers more than one chain. Required when more than one option exists.                      |
| `--asset-transfer-method <eip3009\|permit2>` | Select the token-collection path when the chosen `accepts[]` entry supports both EIP-3009 and Permit2. Required when more than one option exists. |
| `--rpc <url>`                                | Override the RPC endpoint for on-chain reads. Required for chain IDs not in `viem/chains`.                                                        |
| `--max-amount <n>`                           | 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.                                                                                      |

### Supported chains

The CLI reads the chain from the 402 response's `accepts[].network` field. Any EVM chain known to `viem/chains` works, including Base and Base Sepolia. For chain IDs `viem/chains` does not recognize, pass `--rpc <url>` with an RPC endpoint.

### 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, more than one, or incomplete configuration) |

### Examples

#### Raw private key

```bash theme={null}
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 theme={null}
npx @x402r/cli pay https://api.example.com/paid-endpoint \
  --signer-url https://signer.example/rpc \
  --signer-address 0x586486394C38A2a7d36B16a3FDaF366cd202d823
```

#### Custom module (Privy)

```javascript privy-signer.js theme={null}
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 theme={null}
npx @x402r/cli pay https://api.example.com/paid-endpoint \
  --signer-module ./privy-signer.js
```

#### Custom module (Coinbase CDP)

```javascript cdp-signer.js theme={null}
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 theme={null}
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 theme={null}
{
  "body": "<merchant response body>",
  "status": 200,
  "tx": "0x...",
  "elapsedMs": 1234,
  "signer": { "kind": "key", "address": "0x..." }
}
```

The CLI drops the `signer` field when the endpoint returned a non-402 response (the CLI sent no payment).

### Signer module contract

A custom signer module must default-export a factory function with the signature `() => Promise<Account>`. The returned object must be a viem `Account` with at least `address` and `signTypedData`. The CLI only needs typed-data signatures; the facilitator broadcasts the transaction.

### Programmatic usage

You can also use the `pay` function and `resolveSigner` directly from TypeScript:

```typescript theme={null}
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);
```

<Tip>
  The programmatic API uses the same `PayFlags` interface as the CLI binary. All options (chain, rpc, maxAmount, signer flags) are available.
</Tip>

### Exports

The `@x402r/cli` package exports:

| Export                   | Type     | Description                                           |
| ------------------------ | -------- | ----------------------------------------------------- |
| `pay`                    | function | Execute a one-shot payment against an endpoint        |
| `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                                           |

## Next steps

<CardGroup cols={3}>
  <Card title="Merchant guide" icon="store" href="/sdk/merchant/quickstart">
    Accept payments and manage escrow releases.
  </Card>

  <Card title="Examples" icon="code" href="/sdk/examples">
    Runnable examples for every SDK operation.
  </Card>
</CardGroup>
