Skip to content

Repository files navigation

Paytaca CLI

A command-line interface for the Paytaca Bitcoin Cash (BCH) wallet. Built with the same core logic as the Paytaca mobile app, using watchtower-cash-js for transaction operations and libauth for HD key derivation.

Bitcoin Cash is peer-to-peer electronic cash, enabling fast, low-fee transactions for everyday use. Paytaca CLI brings the full capabilities of the Paytaca wallet to the terminal — create wallets, derive addresses, send and receive BCH, manage CashTokens (fungible tokens and NFTs), swap tokens on the Cauldron DEX, pay x402 HTTP APIs, chat over Nostr, and view transaction history, all from the command line.

Designed to be AI agent-friendly and useful for automation by power users. It ships an MCP server, a one-step installer for the Paytaca AI provider, and a local web UI (paytaca web).

Requirements

  • Node.js >= 20 (developed on 22.12.0)

Installation

npm install -g paytaca-cli

Or install from source:

git clone https://github.com/paytaca/paytaca-cli.git && cd paytaca-cli
npm install
npm run build
npm link

After installing, the paytaca command is available globally.

Commands

Most commands accept --json for machine-readable output and --chipnet to target testnet (see Network). Run paytaca <command> --help for the full option list.

Wallet

paytaca wallet create              # Generate a new 12-word seed phrase
paytaca wallet create --chipnet    # Create on chipnet (testnet)
paytaca wallet import              # Import a seed phrase (12/15/18/21/24 words)
paytaca wallet info                # Show wallet hash, address, and balance
paytaca wallet export              # Display the stored seed phrase (interactive terminal + biometrics)

wallet import accepts 12/15/18/21/24-word phrases separated by spaces or commas. Unknown words are rejected with the closest BIP39 suggestion, and the checksum is validated before the wallet is stored.

wallet export requires an interactive terminal and prompts for biometric authentication (Touch ID, fingerprint, or Windows Hello) when available. It cannot be used from scripts, pipes, or other non-interactive processes.

Balance

paytaca balance                    # Show BCH balance with USD conversion
paytaca balance --sats             # Show in satoshis only
paytaca balance --token <category> # Show balance for a specific CashToken
paytaca balance --tokens           # Show CashToken balances only (balance > 0)
paytaca balance --all              # Show BCH and CashToken balances
paytaca balance --chipnet          # Query chipnet balance

The default balance view shows the BCH (or token) amount plus its fiat value (e.g. 0.01218811 BCH / ≈ 3.17 USD). Fiat conversion is skipped when no price is available. --tokens and --all list only tokens with a positive balance.

Receive

paytaca receive                              # Show receiving address with QR code
paytaca receive --index 3                    # Show address at index 3
paytaca receive --no-qr                      # Address only, no QR code
paytaca receive --amount 0.5                 # BIP21 URI with BCH amount
paytaca receive --token                      # Token-aware z-prefix address
paytaca receive --token <category>           # PayPro URI for a specific token
paytaca receive --token <category> --amount 100  # PayPro URI with token amount

The displayed address (and its token-aware variant) is automatically subscribed with Watchtower so incoming BCH and CashTokens are monitored, even for indices not covered by the initial wallet scan.

Send

paytaca send <address> <amount>               # Send BCH (default currency: bch)
paytaca send <address> 50000 sats             # Send in satoshis
paytaca send <address> 50000 satoshis         # Send in satoshis (alias)
paytaca send <address> 10 usd                 # Send a USD amount (converted at live rate)
paytaca send <address> 0.001 --chipnet        # Send on chipnet

The [currency] argument is positional: bch (default), sats/satoshis, or usd. When sending with usd, the current BCH-USD rate is fetched and applied, and the fiat value is shown inline with the amount.

Transaction History

paytaca history                    # Show recent transactions
paytaca history --sats             # Amounts in satoshis
paytaca history --type incoming    # Filter: incoming, outgoing, or all
paytaca history --page 2           # Pagination
paytaca history --token <category> # Filter by CashToken category

Address

paytaca address derive             # Derive address at index 0
paytaca address derive 5           # Derive address at index 5
paytaca address derive --token     # Derive token-aware z-prefix address
paytaca address list               # List first 5 addresses
paytaca address list -n 20         # List first 20 addresses
paytaca address list --token       # List token-aware z-prefix addresses

CashTokens

paytaca token list                                   # List fungible tokens with balances and USD values
paytaca token info <category>                        # Token metadata, balance, USD value, and NFTs
paytaca token price <category> [amount]              # USD price of a token and value of an amount (default: balance)
paytaca token send <address> <amount> --token <cat>  # Send fungible tokens
paytaca token send-nft <address> --token <cat> --commitment <hex>  # Send an NFT
paytaca token send-nft <address> --token <cat> --commitment '' --capability minting

token send-nft also accepts --capability <none|minting|mutable> (default none), and --txid / --vout to pin a specific NFT UTXO (auto-detected otherwise).

Swap (Cauldron DEX)

paytaca swap <tokenId> <amount>                # Sell tokens for BCH (default: sell)
paytaca swap <tokenId> <amount> --action buy   # Buy tokens with BCH
paytaca swap <tokenId> <amount> --raw          # Amount is in raw base units
paytaca swap <tokenId> <amount> --yes          # Skip the confirmation prompt

The --action option is sell (token→BCH) or buy (BCH→token). Swaps run on mainnet only; --chipnet is accepted but exits with an error.

x402 Payments

The x402 protocol enables HTTP payments via BCH. Some APIs require payment to access.

paytaca check <url>                    # Check if URL requires payment, shows estimated cost
paytaca check <url> -X POST -d '{}'    # Check a POST endpoint (-X/--method, -H/--header, -d/--body)
paytaca pay <url>                      # Make a paid HTTP request (handles 402 automatically)
paytaca pay <url> --json               # JSON output (recommended for AI agents)
paytaca pay <url> --dry-run            # Preview payment without executing
paytaca pay <url> -X POST -d '{"prompt":"hello"}'
paytaca pay <url> --max-amount 500     # Cap payment in sats (overrides server max)
paytaca pay <url> --change-address <addr>  # Custom change address
paytaca pay <url> --payer <value>      # Payer identifier (defaults to wallet index 0)
paytaca pay <url> --confirmed          # Skip the confirmation prompt

Example workflow:

paytaca check https://api.example.com/v1/complete --json
# → {"paymentRequired": true, "estimatedCostSats": "100"}

paytaca pay https://api.example.com/v1/complete --method POST --body '{"prompt":"hello"}'
# → Handles 402 → pays → returns response

Update

paytaca update                  # Update paytaca-cli to the latest version on npm
paytaca update --check          # Only check for updates; do not install
paytaca update --registry <url> # Override the npm registry URL

Compares the installed version against the latest published version on npm and, when behind, runs npm install -g paytaca-cli@latest. Pass --check to see available updates without installing.

Paytaca AI

Paytaca AI is a pay-as-you-go model gateway paid with BCH or LIFT via x402. Manage it from the CLI:

paytaca ai configure [harness]      # Install MCP + AI provider (opencode is the default)
paytaca ai api-key create           # Create a wallet-bound API key (shown once)
paytaca ai models                   # List available models
paytaca ai plans [model]            # Plan pricing, optionally for a single model
paytaca ai credits [--model <id>]   # Remaining time credits per model
paytaca ai usage                    # Per-session usage
paytaca ai balance                  # BCH + LIFT funds available for purchases
paytaca ai purchase --model <id> --minutes <n>              # Buy a plan
paytaca ai purchase --model <id> --minutes 60 --lift        # Pay with LIFT (discount)
paytaca ai auto-refill --enable --model <id> --minutes <n> --max-minutes <n>
paytaca ai auto-refill --status     # Inspect; also --disable, --delete

ai configure accepts --backend, --path, --api-key, --chipnet, and -y/--yes. ai purchase and ai auto-refill accept --lift to pay with LIFT tokens at a discount. Add --json to any ai subcommand for machine-readable output.

Armed auto-refill state lives at ~/.paytaca/auto-refill.json. Arming performs one immediate check (buying right away if the armed model has no credits), and the paytaca mcp server keeps a background backstop (every 60s) while a session is running. The get_credits MCP tool is read-only and never triggers a purchase. Each execution is appended to ~/.paytaca/auto-refill-events.jsonl and the latest is reported as lastEvent. It disarms when the budget is spent, funds are short, or the plan is no longer offered. Use --disable to pause and --delete to remove the configuration (history is kept).

Image Generation

Generate images with AI models, paid in BCH on-chain:

paytaca ai image models                             # List available image models
paytaca ai image generate "a green phoenix"         # Generate an image from a prompt
paytaca ai image generate "prompt" --model <id>     # Specify model (defaults to cheapest)
paytaca ai image generate "prompt" --aspect-ratio 16:9  # Aspect ratio (default: 1:1)
paytaca ai image generate "prompt" --quality high   # Quality: low, medium, high, auto
paytaca ai image generate "prompt" --resolution 2K  # Resolution: 512, 1K, 2K, 4K
paytaca ai image generate "prompt" --yes            # Skip confirmation prompt
paytaca ai image history                            # Show order history
paytaca ai image history --page 2                   # Paginate history
paytaca ai image status <order-id>                  # Poll a pending generation order

Image generation uses a two-phase flow: an order is created (returning a CashScript contract address and sats price), BCH is paid on-chain, the backend confirms payment via Watchtower, generation runs server-side, and the finished image is saved under ~/.paytaca/images/. Use image status to resume if a generation is still processing when the initial request returns.

MCP Server

Configure an AI harness in one step. This installs the Paytaca MCP server and, for opencode, also the Paytaca AI provider (model catalogue + API key) so the Paytaca AI models are usable immediately:

paytaca ai configure opencode   # opencode | pi | omp

The command creates a wallet-bound API key against the Paytaca AI backend, writes the provider (base URL, models, key) and MCP server into the harness config, then checks your AI credits and offers to buy a plan when none are active.

Re-running is idempotent: an existing provider API key is reused. Then run the server over stdio:

paytaca mcp              # mainnet
paytaca mcp --chipnet    # default MCP tools to chipnet (testnet)

Read-only wallets: if the active wallet cannot sign (no seed phrase in the keychain), ai configure asks for an API key instead of creating one. Generate it from your full wallet and hand it over:

paytaca ai api-key create                          # full wallet: prints sk-pytc-… once
paytaca ai configure opencode --api-key sk-pytc-…  # read-only wallet

Read-only wallets report credits from the shared wallet hash but can't buy plans — fund credits from the full wallet.

MCP tools: wallet (get_balance, get_transactions, get_receiving_address, get_tokens, send) plus Paytaca AI (get_models, get_plans, get_credits, buy_plan, auto_refill, get_help, generate_image, get_image_status, get_image_models, get_image_history).

Spending tools (send, buy_plan, auto_refill, generate_image) require host-level approval. By default MCP operates on your main wallet and can spend real funds.

When get_credits finds a model with no active session (e.g. after a 402 from the Paytaca AI provider), the result includes a purchaseHint. Relay purchaseHint.message as-is — it carries the exact copy-paste top-up command (no upsell or follow-up questions needed):

{
  "modelId": "deepseek/deepseek-v4.1-flash",
  "active": false,
  "purchaseHint": {
    "model": "deepseek/deepseek-v4.1-flash",
    "minutes": 15,
    "command": "paytaca ai purchase --model deepseek/deepseek-v4.1-flash --minutes 15",
    "message": "To keep using DeepSeek V4.1 Flash, top up by running this in a terminal:\n\n    paytaca ai purchase --model deepseek/deepseek-v4.1-flash --minutes 15\n\n(Switch models with `paytaca ai plans`.)"
  }
}

Nostr Chat

End-to-end encrypted Nostr chat keyed from the wallet mnemonic (HD path m/44'/1237'/0'/0/0; keys are derived in memory and never stored). Conversation metadata (contacts, rooms, messages) is persisted at ~/.paytaca/chat-state.json.

paytaca chat identity                     # Show your npub and pubkey
paytaca chat profile                      # Show display name and published BCH address
paytaca chat contacts                     # List saved contacts
paytaca chat add-contact <npub> [name]    # Add a contact
paytaca chat start <npub>                 # Start a 1:1 conversation
paytaca chat list                         # List conversations
paytaca chat open <room-id> --tail 20     # Show recent messages (--tail, --json)
paytaca chat send <room-id> <text>        # Send a message
paytaca chat listen [--contact <npub|name>]  # Subscribe to new messages (long-running)
paytaca chat set-display-name <name>      # Publish profile name to relays (NIP-78)
paytaca chat set-bch-address <address>    # Publish a BCH address to relays (NIP-78)
paytaca chat remove-display-name          # Remove published name
paytaca chat remove-bch-address           # Remove published address

Web UI

Launch a local browser UI for the wallet, Cauldron swaps, and Paytaca AI:

paytaca web                      # Serve on http://127.0.0.1:7474 and open the browser
paytaca web --port 8080          # Use a custom port
paytaca web --chipnet            # Mainnet by default; --chipnet targets testnet
paytaca web --backend <url>      # Override the Paytaca AI backend URL
paytaca web --no-open            # Do not auto-open the browser

The server binds to 127.0.0.1 only. Access is gated by a random per-session token sent in the X-Paytaca-Token header; the browser is auto-opened with a session link that carries the token, and the page strips it from the address bar after loading. With --no-open, use the printed URL alongside the session link to open it manually.

The UI is organized into two tabs:

  • Wallet — send and receive BCH, send CashTokens, swap on the Cauldron DEX, and review transaction history (date, type, counterparty, amount, USD value, fee, and explorer links), with token-category selection in the send and swap forms.
  • AI — buy plans (BCH or a live LIFT quote), manage auto-refill (enable / pause / delete, with budget-cap validation), and browse generated images (gallery with lightbox, order history, and delete).

Incoming transactions are streamed live over a Watchtower WebSocket and surface as in-page notifications; a light/dark theme toggle is persisted in the browser.

Network

All commands default to mainnet. Pass --chipnet for testnet:

paytaca wallet create --chipnet
paytaca balance --chipnet
paytaca send <address> <amount> --chipnet

Security

Seed phrases are stored in the OS native keychain:

  • macOS — Keychain
  • Linux — GNOME Keyring / KWallet
  • Windows — Credential Manager

Powered by @napi-rs/keyring (prebuilt Rust binaries, no node-gyp required).

Nostr chat keys are not persisted — they are re-derived from the wallet mnemonic at runtime via HD path m/44'/1237'/0'/0/0 and held only in memory for the duration of a session. Non-secret chat metadata (contacts, rooms, messages) is written to ~/.paytaca/chat-state.json with mode 0600; no key material is ever written there.

The paytaca web server listens on 127.0.0.1 only and requires a random per-session token in the X-Paytaca-Token header; requests whose Host header is not 127.0.0.1/localhost are rejected, request bodies are capped at 1 MB, and internal error details are logged to stderr rather than returned to the client.

Architecture

src/
  commands/        CLI command definitions (Commander.js)
    wallet.ts        wallet create | import | info | export
    balance.ts       balance display (BCH and CashTokens, USD conversion)
    receive.ts       receiving address + QR code + payment URIs
    send.ts          BCH sending (bch/sats/usd amounts)
    history.ts       transaction history (BCH and CashTokens)
    address.ts       HD address derivation (standard and z-prefix)
    token.ts         CashToken commands (list, info, price, send, send-nft)
    swap.ts          Cauldron DEX swaps (sell/buy with --action)
    pay.ts           x402 BCH payment handler for HTTP requests
    check.ts         Check if URL requires x402 payment
    ai.ts            Paytaca AI (configure, api-key, models, plans, credits, purchase, auto-refill, image)
    chat.ts          Nostr chat (contacts, conversations, identity, listen)
    web.ts           `paytaca web` — local browser UI launcher
    mcp.ts           `paytaca mcp` stdio entry + per-harness config templates
    update.ts        Self-update from npm registry
  core/
    context.ts       Wallet context resolution (keychain + network), embed-safe
    wallet.ts        Render-agnostic wallet ops shared by CLI and MCP tools
  mcp/
    server.ts        MCP server construction and stdio lifecycle
    tools.ts         MCP tool registration (wallet reads, send, Paytaca AI)
  web/
    server.ts        Local HTTP server (token auth, JSON API routes)
    page.ts          Self-contained Alpine.js UI (wallet, swap, AI tabs)
    assets.ts        Inline asset loading (vendored Alpine.js, styles)
  wallet/
    index.ts         Wallet class, mnemonic gen/import/load
    bch.ts           BchWallet (balance, send, history, CashTokens)
    keys.ts          LibauthHDWallet (HD key derivation, token addresses)
    x402.ts          X402Payer (BCH payment signing and verification)
    cauldron/
      api.ts           Cauldron (riften indexer) REST client
      pools.ts         Pool conversions and helpers
      swap.ts          Swap orchestration: quote estimation and execution
      transact.ts      Cauldron trade transaction building
  storage/
    keychain.ts      OS keychain wrapper (@napi-rs/keyring)
  utils/
    crypto.ts        pubkey -> CashAddress pipeline
    format.ts        Shared display/formatting helpers
    network.ts       Watchtower URLs, derivation paths
    prices.ts        Watchtower asset-prices client (USD per token/BCH)
    x402.ts          x402 header parsing, payment requirement selection
  types/
    x402.ts          x402 payment types (PaymentRequired, PaymentPayload, etc.)
  ai/
    client.ts        Paytaca AI backend client (config, wallet status)
    config.ts        Backend URL, LIFT token id, ~/.paytaca paths
    oauth.ts         BCH OAuth challenge -> access token -> API key
    models.ts        Model catalogue, plan tiers, price/duration helpers
    credits.ts       Credit session lookup and summaries
    images.ts        Image generation client, order orchestration, polling
    purchase.ts      Plan purchase via x402 (BCH or LIFT)
    autoRefill.ts    Auto-refill state and orchestration
    configure.ts     Harness setup (MCP + Paytaca AI provider + credits offer)
  nostr/
    keys.ts          Nostr key derivation from wallet mnemonic (in memory)
    chat.ts          DM event building/signing (NIP-17 style)
    relay.ts         Relay connection/subscription service
    store.ts         Contact/room/message JSON store (~/.paytaca)

Key Dependencies

Package Purpose
watchtower-cash-js UTXO fetching, tx building/signing/broadcasting
@bitauth/libauth HD key derivation (pinned to 2.0.0-alpha.8)
@cashlab/cauldron Cauldron DEX swap building
@napi-rs/keyring OS-native keychain storage
@modelcontextprotocol/sdk MCP server (stdio)
alpinejs Reactive web UI (paytaca web), vendored inline
bip39 Mnemonic generation and validation
nostr-tools Nostr chat events, keys, and relay transport
js-sha256 Hashing for key derivation and payment headers
commander CLI framework
chalk Terminal colors
qrcode-terminal Terminal QR code rendering
zod MCP tool input schemas

Development

npm run dev        # Watch mode (recompile on change)
npm run build      # One-time build (also type-checks)
npm test           # Run the Vitest suite
npm run clean      # Remove dist/

There is no lint script; npm run build is the type-check. Tests live next to sources as *.test.ts.

x402 Server

A reference x402 server accepting BCH (the utxo scheme) is included for testing:

cd x402-server
npm install
npm run dev        # Start dev server on port 3000 (npm start to run once)

Configuration via environment variables:

Variable Description Default
PORT Server port 3000
BCH_NETWORK mainnet or chipnet mainnet
RECEIVE_ADDRESS BCH address to receive payments required for real payments

The server exposes:

Endpoint Cost Description
GET /api/quote 100 sats Random inspirational quote
GET /api/weather 50 sats Fake weather data
GET /api/status 1 sat Server status

Useful for testing the paytaca check / paytaca pay workflow locally (see x402-server/README.md for the header-level protocol details).

License

Copyright Paytaca Inc. 2021. All rights reserved. See LICENSE for details.

About

A command-line interface for the Paytaca wallet for scripts and AI agents

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages