skills/berrypay/SKILL.md
Manage Nano (XNO) cryptocurrency wallet operations using BerryPay CLI. Use for checking balance, sending/receiving XNO, creating payment charges with webhooks, generating QR codes, and processing payments with automatic sweeping.
npx skillsauth add strawberry-labs/berrypay-cli berrypayInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
BerryPay is a Nano (XNO) cryptocurrency wallet CLI designed for AI agents. It provides passwordless operation, JSON output for parsing, and a payment processor for accepting payments with automatic sweeping.
| Task | Command |
|------|---------|
| Check balance | berrypay balance |
| Get address | berrypay address |
| Send XNO | berrypay send <address> <amount> --yes |
| Receive pending | berrypay receive |
| Create charge | berrypay charge create <amount> --webhook <url> |
| Check charge | berrypay charge status <id> |
| List charges | berrypay charge list |
npm install -g berrypay
berrypay init
This creates a new wallet with a random seed stored in ~/.berrypay/config.json.
export BERRYPAY_SEED=<64-character-hex-seed>
When BERRYPAY_SEED is set, it overrides the config file. This is the recommended approach for AI agents.
berrypay import <64-character-hex-seed>
| Variable | Description | Default |
|----------|-------------|---------|
| BERRYPAY_SEED | 64-char hex seed (overrides config) | - |
| BERRYPAY_RPC_URL | Nano RPC node URL | https://uk1.public.xnopay.com/proxy |
| BERRYPAY_WS_URL | WebSocket URL for confirmations | wss://uk1.public.xnopay.com/ws |
berrypay address
Output:
{
"address": "nano_1abc...",
"index": 0
}
With QR code (for sharing/display):
berrypay address --qr
Displays QR code in terminal.
Save QR code as PNG image:
berrypay address --qr --output /path/to/qr.png
Creates a 400x400 PNG image of the QR code. Useful for sending via Telegram or other messaging.
berrypay balance
Output:
{
"address": "nano_1abc...",
"balance": "1.5",
"balanceRaw": "1500000000000000000000000000000",
"pending": "0.0",
"pendingRaw": "0"
}
Note: This command auto-receives any pending funds before showing balance.
JSON-only output (for parsing):
berrypay balance --json
berrypay send <recipient_address> <amount> --yes
Parameters:
<recipient_address>: Nano address starting with nano_<amount>: Amount in XNO (e.g., 0.1, 1.5, 100)--yes or -y: Skip confirmation prompt (required for automation)Example:
berrypay send nano_1abc123... 0.5 --yes
Output:
{
"hash": "ABC123...",
"to": "nano_1abc...",
"amount": "0.5",
"amountRaw": "500000000000000000000000000000"
}
Note: Auto-receives pending funds before sending to ensure full balance is available.
berrypay receive
Receives all pending incoming transactions. Called automatically by balance and send, but can be run manually.
Output:
{
"received": 2,
"blocks": [
{"hash": "ABC...", "amount": "0.1"},
{"hash": "DEF...", "amount": "0.05"}
]
}
berrypay watch
Monitors the wallet address via WebSocket and auto-receives incoming payments. Runs continuously until Ctrl+C.
The payment processor creates ephemeral addresses for each payment request, monitors for payments, and automatically sweeps funds to the main wallet.
1. Create charge → Ephemeral address generated
2. Customer/payer sends XNO to ephemeral address
3. Listener detects payment via WebSocket
4. Auto-receive → Funds received to ephemeral address
5. Auto-sweep → Funds sent to main wallet (index 0)
6. Webhook called → Your server notified
7. Listener auto-stops when no active charges remain
berrypay charge create <amount> [options]
Parameters:
<amount>: Amount in XNO to requestOptions:
| Option | Description |
|--------|-------------|
| -t, --timeout <minutes> | Timeout in minutes (default: 30) |
| -w, --webhook <url> | URL to POST when payment completes |
| -m, --metadata <json> | JSON metadata included in webhook |
| --qr | Display QR code in terminal |
| -o, --output <path> | Save QR code as PNG image |
Example - Basic charge:
berrypay charge create 0.1
Example - With webhook and metadata:
berrypay charge create 1.5 \
--webhook http://localhost:3000/api/payment-callback \
--metadata '{"orderId": "order_123", "userId": "user_456"}'
Example - With QR code image:
berrypay charge create 0.5 --qr --output /tmp/payment-qr.png
Output:
{
"id": "chg_abc123def456...",
"address": "nano_3ephemeral...",
"amount": "0.5",
"amountRaw": "500000000000000000000000000000",
"expiresAt": "2026-01-30T12:30:00.000Z",
"webhookUrl": "http://localhost:3000/callback",
"metadata": {"orderId": "order_123"}
}
Important: Creating a charge automatically starts the background listener if not already running.
berrypay charge status <charge_id>
Example:
berrypay charge status chg_abc123def456
Output:
{
"id": "chg_abc123def456",
"address": "nano_3ephemeral...",
"status": "completed",
"required": "0.5",
"requiredRaw": "500000000000000000000000000000",
"onChainBalance": "0.5",
"onChainPending": "0.0",
"isPaid": true,
"remaining": "0.0",
"swept": true,
"sweepHash": "XYZ789..."
}
Status values:
| Status | Description |
|--------|-------------|
| pending | Waiting for payment |
| partial | Some payment received, not complete |
| completed | Full payment received |
| swept | Funds transferred to main wallet |
| expired | Timeout reached without full payment |
Note: Running charge status will:
--no-sweep flag)berrypay charge list
Filter by status:
berrypay charge list --status pending
berrypay charge list --status completed
berrypay charge list --status swept
Output:
{
"charges": [
{"id": "chg_abc...", "status": "swept", "amount": "0.5", "received": "0.5"},
{"id": "chg_def...", "status": "pending", "amount": "1.0", "received": "0.0"}
]
}
berrypay charge sweep <charge_id>
Forces immediate sweep of funds from charge's ephemeral address to main wallet.
Verbose mode (for debugging):
berrypay charge sweep <charge_id> --verbose
Check if listener is running:
berrypay charge listener
Output:
{
"running": true,
"pid": 12345
}
Manually stop listener:
berrypay charge stop
Manually start listener (usually not needed):
berrypay charge listen
Note: Listener auto-starts on charge create and auto-stops when no active charges remain.
berrypay charge cleanup
Removes swept charges from history to free up storage.
When a charge is completed and swept, BerryPay POSTs to your webhook URL:
Request:
POST /your-webhook-endpoint HTTP/1.1
Content-Type: application/json
{
"event": "charge.completed",
"charge": {
"id": "chg_abc123def456",
"address": "nano_3ephemeral...",
"amountNano": "0.5",
"amountRaw": "500000000000000000000000000000",
"receivedNano": "0.5",
"receivedRaw": "500000000000000000000000000000",
"status": "swept",
"sweepTxHash": "ABC123...",
"sweptAmountNano": "0.5",
"sweptAmountRaw": "500000000000000000000000000000",
"completedAt": "2026-01-30T12:15:00.000Z",
"sweptAt": "2026-01-30T12:15:05.000Z",
"metadata": {
"orderId": "order_123",
"userId": "user_456"
}
},
"timestamp": "2026-01-30T12:15:05.000Z"
}
Your webhook should return HTTP 200 to confirm receipt.
| File | Purpose |
|------|---------|
| ~/.berrypay/config.json | Wallet seed and settings |
| ~/.berrypay/charges.json | Charge history and state |
| ~/.berrypay/listener.pid | Background listener PID |
# 1. Create charge with webhook
berrypay charge create 0.1 \
--webhook http://localhost:3000/api/payment-complete \
--metadata '{"jobId": "job_abc123"}'
# 2. Parse the output to get charge address
# 3. Share the address with the payer
# 4. Your webhook will be called when payment completes
# 5. Funds are automatically in your main wallet
# Check charge status (also triggers sweep if paid)
berrypay charge status chg_abc123def456
# Parse JSON output, check "isPaid" field
# 1. Check balance
berrypay balance
# 2. Send payment (--yes to skip confirmation)
berrypay send nano_1recipient... 0.5 --yes
# 3. Parse output to get transaction hash
# Create charge with QR image
berrypay charge create 1.0 \
--qr \
--output /tmp/payment_qr.png \
--webhook http://localhost:3000/callback
# The QR image at /tmp/payment_qr.png can be sent to user via Telegram, etc.
import { BerryPayWallet, PaymentProcessor } from 'berrypay';
// Create wallet from environment
const wallet = new BerryPayWallet({
seed: process.env.BERRYPAY_SEED
});
// Check balance
const { balance, pending } = await wallet.getBalance();
console.log(`Balance: ${BerryPayWallet.rawToNano(balance)} XNO`);
// Send payment
const result = await wallet.send(
'nano_1recipient...',
BerryPayWallet.nanoToRaw('0.5')
);
console.log(`Sent! Hash: ${result.hash}`);
// Payment processor
const processor = new PaymentProcessor({
wallet,
autoSweep: true
});
processor.on('charge:completed', (charge) => {
console.log(`Payment received for ${charge.id}`);
});
processor.on('charge:swept', ({ charge, hash }) => {
console.log(`Swept to main wallet: ${hash}`);
});
await processor.start();
// Create charge
const charge = await processor.createCharge({
amountNano: '1.0',
webhookUrl: 'http://localhost:3000/callback',
metadata: { orderId: '123' }
});
console.log(`Pay to: ${charge.address}`);
All commands output JSON with error information on failure:
{
"error": "Insufficient balance. Have: 0.05 XNO"
}
Common errors:
| Error | Cause | Solution |
|-------|-------|----------|
| "No wallet found" | Wallet not initialized | Run berrypay init or set BERRYPAY_SEED |
| "Insufficient balance" | Not enough XNO | Check balance, wait for pending |
| "Invalid Nano address" | Bad recipient address | Verify address starts with nano_ |
| "Account not opened" | Sending from empty account | Receive some XNO first |
| "Charge not found" | Invalid charge ID | Check charge list for valid IDs |
--yes flag when sending to skip interactive promptsBERRYPAY_SEED for secure seed managementbalance and send auto-receive pending funds--output to save QR codes for sharing with users| Unit | Value | |------|-------| | 1 XNO (Nano) | 10^30 raw | | 1 raw | Smallest unit |
In code:
BerryPayWallet.nanoToRaw('1.5') // "1500000000000000000000000000000"
BerryPayWallet.rawToNano('1500000000000000000000000000000') // "1.5"
https://uk1.public.xnopay.com/proxywss://uk1.public.xnopay.com/wsnano_1xnopay1bfmyx5eit8ut4gg1j488kt8bjukijerbn37jh3wdm81y6mxjg8qjtools
Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layers like Lobster, ACPX, plugins, or plain code. Keep conditional logic in the caller; use TaskFlow for flow identity, child-task linkage, waiting state, revision-checked mutations, and user-facing emergence.
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
# Lobster Lobster executes multi-step workflows with approval checkpoints. Use it when: - User wants a repeatable automation (triage, monitor, sync) - Actions need human approval before executing (send, post, delete) - Multiple tool calls should run as one deterministic operation ## When to use Lobster | User intent | Use Lobster? | | ------------------------------------------------------ | --------------------------
tools
A CLI tool for making authenticated requests to the X (Twitter) API. Use this skill when you need to post tweets, reply, quote, search, read posts, manage followers, send DMs, upload media, or interact with any X API v2 endpoint.