# Skill: Circle Wallet Spending Policy

**CRITICAL: This skill uses Circle Agent Wallet CLI exclusively. Do NOT use any other wallet outside of Circle Agent Wallet.**

## Overview

Manage spending limits on Circle agent wallets. Three commands:
- **Read** current limits: `circle wallet limit` — no OTP required
- **Set** custom limits: `circle wallet limit set` — requires human OTP
- **Reset** to defaults: `circle wallet limit reset` — requires human OTP

Spending policies are mainnet-only. Testnet chains are rejected.

## Prerequisites

1. Authenticated session: `circle wallet status` must show `VALID`
2. Agent wallet address: `circle wallet list --chain <CHAIN> --output json`
3. If not logged in: `curl -sL https://agents.circle.com/skills/wallet-login.md`

## Interactive OTP Flow

`wallet limit set` and `wallet limit reset` are **interactive** commands. They send an OTP email mid-execution and wait for the human to enter the code at the CLI prompt.

### CRITICAL: Do NOT Re-Run the Command

Each invocation triggers a NEW OTP and invalidates the previous one. If you run the command a second time while the first is still waiting, the first OTP becomes invalid and the human gets multiple confusing emails.

### Correct Process (Named Pipe + File Polling)

**Why not split across shell calls?** File descriptors (\`exec 3>\`) are per-process. If your runtime spawns a new shell for each command (Claude Code, Codex, etc.), the fd dies between calls and the CLI gets EOF. The entire pipe lifecycle must live in **one shell invocation**.

**Step 1 — Launch the CLI in a single long-running shell.** This script holds the pipe open and polls for a sentinel file containing the OTP:

\`\`\`bash
rm -f /tmp/circle-otp-pipe /tmp/circle-otp-code /tmp/circle-out
mkfifo /tmp/circle-otp-pipe

circle wallet limit set \
  --address <addr> --chain BASE \
  --policy-type stablecoin \
  --per-tx 1000 --daily 5000 --weekly 20000 --monthly 50000 \
  < /tmp/circle-otp-pipe > /tmp/circle-out 2>&1 &
CLI_PID=$!
exec 3>/tmp/circle-otp-pipe

# Poll until the OTP code file appears (written by a separate call)
for i in $(seq 1 180); do
  if [ -f /tmp/circle-otp-code ]; then
    OTP=$(cat /tmp/circle-otp-code)
    echo "$OTP" >&3
    exec 3>&-
    wait $CLI_PID
    cat /tmp/circle-out
    rm -f /tmp/circle-otp-pipe /tmp/circle-otp-code /tmp/circle-out
    exit 0
  fi
  sleep 1
done
echo "Timeout waiting for OTP"
exec 3>&-
rm -f /tmp/circle-otp-pipe /tmp/circle-otp-code /tmp/circle-out
\`\`\`

Run this command in the **background** so you can proceed to the next steps.

**Step 2 — Read the OTP prefix from the CLI output.** Wait a few seconds for the OTP email to send, then:

\`\`\`bash
cat /tmp/circle-out
\`\`\`

This shows the prompt with the security prefix (e.g. \`Enter the 6-digit OTP from your email after OOW-:\`).

**Step 3 — Ask the human** for the OTP code: "An OTP was sent to your email with prefix **XYZ-**. Please share the 6-digit code."

**Step 4 — Write the code to the sentinel file.** The polling loop picks it up and feeds it to the CLI:

\`\`\`bash
echo "<6-digit-code>" > /tmp/circle-otp-code
\`\`\`

Then check \`/tmp/circle-out\` for the result.

The OTP format is \`ABC-123456\` (full) or \`123456\` (digits only — the CLI prepends the cached prefix). Only the digits are needed since the CLI already knows the prefix.

If the command was accidentally re-run, tell the human to use the OTP from the **latest** email only.

## Commands

### Read Limits (No OTP)

```bash
circle wallet limit --address <addr> --chain BASE --output json
```

### Set Custom Limits (OTP Required)

```bash
circle wallet limit set \
  --address <addr> --chain BASE \
  --policy-type stablecoin \
  --per-tx 1000 --daily 5000 --weekly 20000 --monthly 50000
```

Limits must be monotonic: `per-tx ≤ daily ≤ weekly ≤ monthly`. Run `circle wallet limit set --help` for all flags.

### Reset to Defaults (OTP Required)

```bash
circle wallet limit reset --address <addr> --chain BASE --yes
```

Omit `--yes` to get a confirmation prompt before the OTP is sent. Run `circle wallet limit reset --help` for all flags.

## Rules

- NEVER re-run the command while waiting for OTP — each invocation invalidates the previous OTP
- ALWAYS use the named pipe + file-polling approach to hold the process open and feed in the OTP
- ALWAYS confirm limit values with the user before running `limit set`
- Spending policies are mainnet-only — testnet chains are rejected
- Only agent wallets support spending policies, not local wallets

---

**Current location**: `/skills/wallet-policy.md`

**For full skill directory**: Read https://agents.circle.com/.well-known/agent-skills/index.json to see all available skills and navigate between them.
