{"id":"1bb1d82c-bf42-4792-82b3-6388cb9b7e5c","entityType":"agent","slug":"clawhub-tibbar-etihw-agenta-monero","name":"agenta-monero","canonicalUrl":"https://www.xpersona.co/agent/clawhub-tibbar-etihw-agenta-monero","canonicalPath":"/agent/clawhub-tibbar-etihw-agenta-monero","generatedAt":"2026-10-10T00:22:12.857Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T10:43:21.018Z","emptyReason":null},"description":"Use when making or receiving Monero (XMR) payments. Generates addresses, sends payments, checks balances, verifies transactions, generates and verifies payment proofs, estimates fees, sweeps funds, and manages wallet operations via a self-hosted monero-wallet-rpc node. Keywords: monero, xmr, cryptocurrency, payments, wallet, send, receive, payment proof.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 2.9K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s1739h27ayzfmp9kv3fd0n0b6n8bc459:agenta-monero","sourceUrl":"https://clawhub.ai/tibbar-etihw/agenta-monero","homepage":"https://clawhub.ai/tibbar-etihw/skills/agenta-monero","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/tibbar-etihw/agenta-monero","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/tibbar-etihw/skills/agenta-monero","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":69,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"agenta-monero technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T10:43:21.018Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T10:43:21.018Z","emptyReason":null},"stars":null,"forks":null,"downloads":2925,"packageName":null,"latestVersion":"0.1.2","tractionLabel":"2.9K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T10:43:21.017Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T10:43:21.018Z","lastCrawledAt":"2026-10-09T10:43:21.017Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T10:43:21.017Z","lastVerifiedAt":null,"highlights":[{"version":"0.1.2","createdAt":"2026-07-28T17:14:06.093Z","changelog":"**Requires explicit confirmation to broadcast Monero transactions.** - Sending (send_xmr.sh) and sweeping (sweep_all.sh) XMR now require --confirm; transactions are not broadcast by default. - --dry-run mode is available to preview transactions without sending. - Updated documentation and usage instructions to reflect confirmation requirement. - Added \"Agenta-Monero Security Review.md\" file. - Various script, test, and documentation updates to support new confirmation workflow.","fileCount":228,"zipByteSize":114565},{"version":"0.1.1","createdAt":"2026-07-28T13:43:57.330Z","changelog":"**This release improves skill transparency, security, and safety with explicit permissions and warnings.** - Declares all permissions and operational capabilities in SKILL.md (`shell_execution`, `file_writes`, `process_management`, `network_access`, `credential_access`), detailing what is written/read and where. - Adds a prominent safety warning about Monero transfer irreversibility, risk with sweeps, and credential exposure in `.env`. - Expands documentation on setup, credential file handling, and security considerations. - Minor metadata updates: bumps version, refines compatibility section, and adds explicit user/operator guidance. - No breaking changes to APIs or script invocation.","fileCount":226,"zipByteSize":109091}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s1739h27ayzfmp9kv3fd0n0b6n8bc459:agenta-monero","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s1739h27ayzfmp9kv3fd0n0b6n8bc459:agenta-monero` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/tibbar-etihw/agenta-monero before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-tibbar-etihw-agenta-monero/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-tibbar-etihw-agenta-monero/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-tibbar-etihw-agenta-monero/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-tibbar-etihw-agenta-monero/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-tibbar-etihw-agenta-monero/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-tibbar-etihw-agenta-monero/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T00:22:12.853Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-tibbar-etihw-agenta-monero/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-tibbar-etihw-agenta-monero/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-tibbar-etihw-agenta-monero/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-tibbar-etihw-agenta-monero/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T10:43:21.018Z","emptyReason":null},"readme":"Skill: agenta-monero\n\nOwner: tibbar-etihw\n\nSummary: Use when making or receiving Monero (XMR) payments. Generates addresses, sends payments, checks balances, verifies transactions, generates and verifies payment proofs, estimates fees, sweeps funds, and manages wallet operations via a self-hosted monero-wallet-rpc node. Keywords: monero, xmr, cryptocurrency, payments, wallet, send, receive, payment proof.\n\nTags: latest:0.1.2\n\nVersion history:\n\nv0.1.2 | 2026-07-28T17:14:06.093Z | auto\n\n**Requires explicit confirmation to broadcast Monero transactions.**\n\n- Sending (send_xmr.sh) and sweeping (sweep_all.sh) XMR now require --confirm; transactions are not broadcast by default.\n- --dry-run mode is available to preview transactions without sending.\n- Updated documentation and usage instructions to reflect confirmation requirement.\n- Added \"Agenta-Monero Security Review.md\" file.\n- Various script, test, and documentation updates to support new confirmation workflow.\n\nv0.1.1 | 2026-07-28T13:43:57.330Z | auto\n\n**This release improves skill transparency, security, and safety with explicit permissions and warnings.**\n\n- Declares all permissions and operational capabilities in SKILL.md (`shell_execution`, `file_writes`, `process_management`, `network_access`, `credential_access`), detailing what is written/read and where.\n- Adds a prominent safety warning about Monero transfer irreversibility, risk with sweeps, and credential exposure in `.env`.\n- Expands documentation on setup, credential file handling, and security considerations.\n- Minor metadata updates: bumps version, refines compatibility section, and adds explicit user/operator guidance.\n- No breaking changes to APIs or script invocation.\n\nArchive index:\n\nArchive v0.1.2: 228 files, 114565 bytes\n\nFiles: .env.example (875b), .gitignore (239b), Agenta-Monero Security Review.md (9037b), docs (0b), docs/GETTING_STARTED.md (12444b), lib (0b), lib/common.sh (1195b), lib/config.sh (1322b), lib/format.sh (1436b), lib/retry.sh (742b), lib/rpc.sh (2353b), lib/validate.sh (846b), README.md (5757b), references (0b), references/env-reference.md (4659b), references/error-runbook.md (7331b), references/rpc-reference.md (10918b), scripts (0b), scripts/check_balance.sh (602b), scripts/check_tx_proof.sh (1751b), scripts/create_address.sh (608b), scripts/estimate_fee.sh (2416b), scripts/get_transfer.sh (2567b), scripts/get_tx_proof.sh (902b), scripts/interactive_setup.sh (9294b), scripts/list_addresses.sh (481b), scripts/list_incoming.sh (1526b), scripts/list_outgoing.sh (1286b), scripts/send_xmr.sh (3272b), scripts/stop_wallet_rpc.sh (1486b), scripts/sweep_all.sh (2922b), scripts/sync_status.sh (1004b), scripts/validate_address.sh (898b), scripts/verify_payment.sh (3098b), scripts/wallet_rpc_status.sh (1202b), setup.sh (3725b), skill-card.md (2705b), SKILL.md (21484b), tests (0b), tests/check_balance.bats (853b), tests/check_tx_proof.bats (5529b), tests/common.bats (3583b), tests/config.bats (1871b), tests/create_address.bats (3648b), tests/estimate_fee.bats (3568b), tests/fixtures (0b), tests/fixtures/.gitkeep (0b), tests/fixtures/ca (0b), tests/fixtures/ca_acc (0b), tests/fixtures/ca_acc/create_address.json (76b), tests/fixtures/ca_nolabel (0b), tests/fixtures/ca_nolabel/create_address.json (72b), tests/fixtures/ca_q (0b), tests/fixtures/ca_q/create_address.json (69b), tests/fixtures/ca/create_address.json (76b), tests/fixtures/check_balance (0b), tests/fixtures/check_balance/get_balance.json (140b), tests/fixtures/check_balance/refresh.json (38b), tests/fixtures/ctp_bad (0b), tests/fixtures/ctp_bad/check_tx_proof.json (88b), tests/fixtures/ctp_bad/refresh.json (38b), tests/fixtures/ctp_err (0b), tests/fixtures/ctp_err/check_tx_proof.ERR.json (76b), tests/fixtures/ctp_err/refresh.json (38b), tests/fixtures/ctp_nr (0b), tests/fixtures/ctp_nr/check_tx_proof.json (99b), tests/fixtures/ctp_ok (0b), tests/fixtures/ctp_ok/check_tx_proof.json (100b), tests/fixtures/ctp_ok/refresh.json (38b), tests/fixtures/ef (0b), tests/fixtures/ef_bad (0b), tests/fixtures/ef_bad/transfer.json (111b), tests/fixtures/ef_bad/validate_address.json (51b), tests/fixtures/ef_multi (0b), tests/fixtures/ef_multi/transfer.json (109b), tests/fixtures/ef_multi/validate_address.json (108b), tests/fixtures/ef/transfer.json (111b), tests/fixtures/ef/validate_address.json (108b), tests/fixtures/gt (0b), tests/fixtures/gt_empty (0b)\n\nFile v0.1.2:SKILL.md\n\n---\nname: agenta-monero\ndescription: \"Use when making or receiving Monero (XMR) payments. Generates addresses, sends payments, checks balances, verifies transactions, generates and verifies payment proofs, estimates fees, sweeps funds, and manages wallet operations via a self-hosted monero-wallet-rpc node. Keywords: monero, xmr, cryptocurrency, payments, wallet, send, receive, payment proof.\"\nlicense: MIT\ncompatibility: \"Requires bash 4+, curl, jq, flock (util-linux), and a running monero-wallet-rpc >= 0.18.0.\"\nmetadata:\n  hermes:\n    category: finance\n    tags: [monero, cryptocurrency, payments, wallet, xmr]\n    related_skills: []\n  version: \"0.3.0\"\n  author: Private Payments\n  permissions:\n    shell_execution: true\n    file_writes:\n      - \".env (chmod 600) — RPC credentials + wallet password\"\n      - \"$MONERO_LOCK_DIR/.netrc (chmod 600) — ephemeral RPC auth\"\n      - \"$MONERO_LOCK_DIR/wallet-rpc.pid — process tracking\"\n      - \"$MONERO_LOCK_DIR/wallet-rpc.port — port tracking\"\n      - \"$MONERO_LOCK_DIR/.last_refresh — refresh timestamp\"\n    process_management: \"starts/stops monero-wallet-rpc as a background process\"\n    network_access: \"HTTP POST to $MONERO_RPC_URL/json_rpc (localhost by default)\"\n    credential_access: \"reads .env for RPC + wallet credentials; writes .netrc for curl auth\"\n---\n\n# Agenta-Monero\n\nShell wrappers over `monero-wallet-rpc` for autonomous Monero (XMR) payments. All scripts emit JSON to stdout (success) or a structured error JSON to stderr; they compose into receive/send/verify/sweep workflows. Money math is integer piconeros internally; XMR decimal strings appear in output.\n\n> **WARNING — IRREVERSIBLE FINANCIAL OPERATIONS**\n>\n> - Monero transactions are **irreversible**. Once broadcast, funds cannot be recovered.\n> - `send_xmr.sh` and `sweep_all.sh` **require `--confirm` to broadcast**. Without it, they refuse to relay. Use `--dry-run` to preview without `--confirm`.\n> - `sweep_all.sh` transfers **all unlocked funds** from the wallet (or subaddress) to a single destination. A mistaken or maliciously triggered sweep can drain the entire balance.\n> - Always validate the recipient address (`validate_address.sh`) and confirm the amount before executing a send or sweep.\n> - The `.env` file contains `MONERO_WALLET_PASSWORD` and RPC credentials. It is created with `chmod 600`, but on multi-user systems, shared CI, or agent workspaces with broad read access, an attacker who reads `.env` can access the wallet and move funds. Secure the file and the system accordingly.\n\n**Use when:** generating receive addresses, sending/sweeping XMR, checking balance, verifying an incoming payment or a payment proof, estimating fees, or reconciling transactions by hash.\n\n## Prerequisites\n\n- **Install Monero CLI tools** (≥ 0.18.0): download from https://getmonero.org/downloads/ — you need at minimum `monero-wallet-rpc`. Also create a wallet file: `monero-wallet-cli --generate-new-wallet ~/Monero/wallets/main --password 'PASS'` (write down the 25-word seed).\n- **Bash ≥ 4**, `curl`, `jq`, `flock` (util-linux) — standard on Linux/macOS (`brew install jq` on macOS).\n- **First-time setup:** run `./scripts/interactive_setup.sh` (interactive prompts) **or** tell the Hermes agent \"Set up the Agenta-Monero skill\" (agent-driven; see First-Time Setup below). Both paths generate RPC credentials, write `.env`, start `monero-wallet-rpc`, and verify readiness.\n- After setup, every script runs from the skill root. Invoke `./setup.sh` again after changing `.env`.\n\n## Permissions & Capabilities\n\nThis skill performs the following actions. Operators should review these before approving or invoking the skill in automated workflows:\n\n| Capability | Details |\n|------------|---------|\n| **Shell execution** | Runs `curl`, `jq`, `flock`, `monero-wallet-rpc`, and standard shell utilities |\n| **File writes** | `.env` (chmod 600), `.netrc` (chmod 600, ephemeral), PID/port files, lock files, refresh timestamp |\n| **Process management** | Starts and stops `monero-wallet-rpc` as a background daemon (PID tracked in `$MONERO_LOCK_DIR`) |\n| **Network access** | HTTP POST to `$MONERO_RPC_URL/json_rpc` (localhost by default; can be configured for remote) |\n| **Credential access** | Reads `.env` for RPC user/password and wallet password; writes `.netrc` for curl auth; never emits credentials in stdout |\n\nAll credential files are created with restrictive permissions (`0600` for files, `0700` for the lock directory). The `.env` file is parsed safely (never sourced) and shell metacharacters are rejected.\n\n## First-Time Setup\n\nWhen a user asks to set up the Agenta-Monero skill, follow this workflow.\n\n**Path A — Agent-driven (recommended):**\n1. Ask: \"What's the path to your wallet file?\"\n2. Ask: \"What's the wallet password?\"\n3. Ask: \"Local daemon or remote node?\"\n   - If remote: \"What's the daemon address? (e.g. node.example.com:18081)\"\n4. Check: `command -v monero-wallet-rpc` — if missing, print install guidance (https://getmonero.org/downloads/) and stop.\n5. Run: `./scripts/interactive_setup.sh --wallet-path \"PATH\" --wallet-password \"PASS\" --network mainnet --daemon-type local [--daemon-address \"HOST:PORT\" if remote] --force`\n6. Read the JSON output. If `ready:true` → done. If `ready:false` → check `warnings` and troubleshoot.\n7. To check wallet-rpc status later: `./scripts/wallet_rpc_status.sh`. To stop it: `./scripts/stop_wallet_rpc.sh`.\n\n**Path B — Manual interactive script:**\nTell the user to run `./scripts/interactive_setup.sh` and follow the prompts.\n\n**Both paths:**\n- Generate random RPC credentials (12-char user, 24-char password).\n- Write `.env` (chmod 600) with all values including `MONERO_WALLET_PASSWORD`.\n  - **Caution:** `.env` persists on disk and contains the wallet password. On multi-user systems or CI, ensure the file is not world-readable, not committed to version control, and not included in backups or log captures.\n- Start `monero-wallet-rpc` as a background process (PID stored in `$MONERO_LOCK_DIR/wallet-rpc.pid`).\n- Run `./setup.sh` and report readiness.\n- **Credentials are not emitted in stdout JSON.** They exist only in `.env` (chmod 600). If the user needs to see them, read from `.env` directly.\n\n## Quick reference\n\nOne compact block per operation. **Load `references/rpc-reference.md` when you need exact JSON-RPC params, full output field lists, or per-operation refresh classification.**\n\n```text\ncreate_address.sh  --label \"Payment from Alice\" [--account 0]   -> {address, address_index, account}\nsend_xmr.sh        --address ADDR --amount \"1.5\"                -> {tx_hash, fee, amount[, tx_key]}\n                   [--priority 0] [--get-tx-key] [--dry-run] [--confirm]\n                   [--dest '[{\"address\":\"A\",\"amount\":\"1.0\"}]']\nestimate_fee.sh    --address ADDR --amount \"1.5\" [--priority 0] -> {fee, amount, priority, num_destinations}\nsweep_all.sh       --address ADDR [--account 0] [--subaddress N]-->{tx_hash, fee, amount}\n                   [--priority 0] [--dry-run] [--confirm]\ncheck_balance.sh   [--account 0]                                -> {balance, unlocked_balance, blocks_to_unlock, time_to_unlock, account}\nget_transfer.sh    --tx-hash HASH                               -> {tx_hash, amount, fee, direction, confirmations, address, address_index, timestamp, confirmed, unlock_time}\nverify_payment.sh  --tx-hash HASH | --address ADDR --expected-amount \"1.5\" -> {verified, confirmations, tx_hash, address, address_index, confirmed, amount}\nget_tx_proof.sh    --tx-hash HASH --address ADDR                -> {tx_hash, address, proof}\ncheck_tx_proof.sh  --tx-hash HASH --address ADDR --proof PROOF  -> {verified, confirmations, amount, tx_hash, address}\nlist_incoming.sh   [--confirmed-only|--all] [--since-block N]   -> [{tx_hash, amount, confirmations, address, address_index, timestamp, confirmed, unlock_time}]\n                   [--since-timestamp N] [--limit 100] [--account 0]\nlist_outgoing.sh   [--since-block N] [--since-timestamp N]      -> [{tx_hash, amount, fee, timestamp, address, address_index, unlock_time}]\n                   [--limit 100] [--account 0]\nlist_addresses.sh  [--account 0]                                -> [{index, address, label, balance, unlocked_balance}]\nvalidate_address.sh --address ADDR                              -> {valid, network, network_match, subaddress, integrated}\nsync_status.sh                                                   -> {height, daemon_connected, wallet_version}\n```\n\nConcrete output examples (stdout; success is one JSON object per line):\n\n```json\n// create_address.sh\n{\"address\":\"88bc...\",\"address_index\":5,\"account\":0}\n// send_xmr.sh --address ... --amount \"1.5\"\n{\"tx_hash\":\"7663438...\",\"fee\":\"0.0000869\",\"amount\":\"1.5\"}\n// estimate_fee.sh --address ... --amount \"1.5\"\n{\"fee\":\"0.0000869\",\"amount\":\"1.5\",\"priority\":0,\"num_destinations\":1}\n// sweep_all.sh --address DEST --dry-run\n{\"tx_hash\":\"\",\"fee\":\"0.0000869\",\"amount\":\"8.2\"}\n// check_balance.sh\n{\"balance\":\"10.5\",\"unlocked_balance\":\"8.2\",\"blocks_to_unlock\":42,\"time_to_unlock\":30240,\"account\":0}\n// get_transfer.sh --tx-hash ...\n{\"tx_hash\":\"c36258a...\",\"amount\":\"1.5\",\"fee\":\"0.0000435\",\"direction\":\"in\",\"confirmations\":15,\"address\":\"77Vx9cs...\",\"address_index\":3,\"timestamp\":1535918400,\"confirmed\":true,\"unlock_time\":0}\n// verify_payment.sh --tx-hash ...\n{\"verified\":true,\"confirmations\":12,\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"address_index\":3,\"confirmed\":true,\"amount\":\"1.5\"}\n// get_tx_proof.sh --tx-hash ... --address ...\n{\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"proof\":\"ProofV1...\"}\n// check_tx_proof.sh --tx-hash ... --address ... --proof ...\n{\"verified\":true,\"confirmations\":15,\"amount\":\"1.5\",\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\"}\n// validate_address.sh --address ...\n{\"valid\":true,\"network\":\"mainnet\",\"network_match\":true,\"subaddress\":false,\"integrated\":false}\n// sync_status.sh\n{\"height\":1523651,\"daemon_connected\":true,\"wallet_version\":196613}\n// list_incoming.sh (array element)\n{\"tx_hash\":\"c36258a...\",\"amount\":\"1.5\",\"confirmations\":15,\"address\":\"77Vx9cs...\",\"address_index\":3,\"timestamp\":1535918400,\"confirmed\":true,\"unlock_time\":0}\n```\n\nAmounts in outputs are XMR decimal strings (e.g. `\"1.5\"`). `--dry-run` and `estimate_fee` preview without broadcasting.\n\n## Gotchas (verified facts — get these right)\n\n- **No `sync` RPC.** The wallet refreshes from the daemon via `refresh`, which can take seconds-to-minutes. Refresh is **operation-aware**: balance/transfer/verify ops auto-refresh; address-management, `validate_address`, `estimate_fee`, `get_tx_proof`, and `sync_status` do not. Override with `--no-refresh` on any auto-refresh op (**`--no-refresh` works in any argument position**).\n- **`blocks_to_unlock` / `time_to_unlock` are native `get_balance` fields.** Read them directly — never derive them. `check_balance` surfaces both. They are `0` when no funds are locked, or `null` if the wallet omits them — treat `0`/`null` as \"nothing locked\".\n- **Priority values: `0=default, 1=unimportant, 2=normal, 3=elevated, 4=priority`.** The default is **`0`** (wallet decides). Do **not** default to `1` — that literally means \"unimportant\". Send/sweep/estimate accept `--priority 0-4`.\n- **Single `/json_rpc` endpoint.** Every wallet method this skill uses — including `get_height` and `get_version` — is POSTed to `$MONERO_RPC_URL/json_rpc`. There is no root-path call anywhere.\n- **`validate_address` uses real RPC fields.** The RPC is called with `any_net_type:true` so the real `nettype` is returned; `network_match` is derived client-side by comparing `nettype` to `MONERO_NETWORK`. There is **no `checksum_valid` field** (the checksum is part of `valid`). This keeps `INVALID_ADDRESS` (bad format/checksum) distinct from `NETWORK_MISMATCH` (valid but wrong network).\n- **Money is integer piconeros (1 XMR = 10^12).** Never use floating-point for amounts. All arithmetic is integer piconero; the XMR decimal strings in output come from the scripts' string-based conversion. Amounts must be positive and have <=12 decimals.\n- **Sends and sweeps are not idempotent and are NOT auto-retried.** On timeout/uncertain result, check `get_transfer.sh --tx-hash` **before** retrying (see retry-safety workflow). Use `--dry-run` / `estimate_fee` to preview.\n- **Credentials use netrc (never `curl -u`); `.env` is parsed, never sourced.** The netrc lives at `$MONERO_LOCK_DIR/.netrc` (mode `0600`). All user values are passed to the RPC via `jq --arg`/`--argjson` — never by string interpolation.\n\n## Workflows\n\nWorkflows are rendered as checklists. Money/identity paths (send, sweep, verify) are prescriptive: follow the order. Every destructive workflow ends with a verify-after-act step.\n\n### Receive a Payment\n\n- [ ] `scripts/create_address.sh --label \"Payment from Alice\"` — note the returned `address`.\n- [ ] Share `address` with the payer.\n- [ ] `scripts/check_balance.sh` (or `scripts/list_incoming.sh --since-block <height>`).\n- [ ] `scripts/verify_payment.sh --address \"ADDR\" --expected-amount \"1.5\"` — wait until `verified:true`.\n- [ ] `scripts/get_tx_proof.sh --tx-hash \"HASH\" --address \"ADDR\"` — hand the payer the `proof` for their records.\n\n### Send a Payment (plan -> validate -> execute)\n\n> **Irreversible:** `send_xmr.sh` requires `--confirm` to broadcast. Use `--dry-run` to preview without `--confirm`. Always validate the address and confirm the amount before executing.\n\n- [ ] **Plan:** `scripts/estimate_fee.sh --address \"RECIPIENT\" --amount \"2.5\"` — preview `fee`.\n- [ ] **Validate:** `scripts/validate_address.sh --address \"RECIPIENT\"` — confirm `valid:true` and `network_match:true`.\n- [ ] **Balance:** `scripts/check_balance.sh` — confirm `unlocked_balance >= 2.5`.\n- [ ] **Preview (optional):** `scripts/send_xmr.sh --address \"RECIPIENT\" --amount \"2.5\" --dry-run` — confirm fee/amount without broadcasting.\n- [ ] **Execute:** `scripts/send_xmr.sh --address \"RECIPIENT\" --amount \"2.5\" --confirm` — note the `tx_hash`.\n- [ ] **Verify:** `scripts/get_transfer.sh --tx-hash \"<tx_hash>\"` — confirm it was recorded (and `confirmed` once enough blocks pass).\n\n### Send a Payment — retry safety (DECISION GATE)\n\nSends are not idempotent. **Never retry blindly on timeout.** Run this gate first:\n\n- [ ] Attempt: `scripts/send_xmr.sh --address \"RECIPIENT\" --amount \"2.5\" --confirm`.\n- [ ] If it returns a `tx_hash` (success) -> **done; do NOT re-send.**\n- [ ] If it **times out / returns an uncertain result**, whether you can use `get_transfer` depends on having a hash:\n  - **You have a `tx_hash`** (from the send response, or a prior attempt you're unsure about) -> call `scripts/get_transfer.sh --tx-hash \"<tx_hash>\"` and branch on the **error code**:\n    - `TX_NOT_FOUND` -> the transaction is genuinely absent from the wallet -> **safe to retry the send.**\n    - `RPC_UNREACHABLE` -> the wallet RPC / daemon could not be reached -> the transaction status is **unknown**, not absent -> **do NOT retry the send;** fix connectivity (`sync_status.sh`, restart `monero-wallet-rpc`/`monerod`) and re-check `get_transfer` before doing anything else.\n    - any success result -> the tx exists -> **do NOT re-send.**\n  - **You have NO `tx_hash`** (pure transport failure / `RPC_UNREACHABLE` with no payload) -> there is nothing to look up; status is **unknown**. **Do NOT retry the send.** Fix connectivity first, then reconcile with `scripts/list_outgoing.sh` (match by amount/timestamp) to detect any tx that may have been created before re-evaluating.\n\n### Verify a Payment Proof\n\n- [ ] Collect from the payer: `tx_hash`, `address`, and `proof` string.\n- [ ] `scripts/check_tx_proof.sh --tx-hash \"HASH\" --address \"ADDR\" --proof \"PROOF\"`.\n- [ ] Act on `verified`: `true` => proof is cryptographically valid (read `amount`, `confirmations`). `false` / `PROOF_INVALID` => reject and ask the payer to re-issue.\n\n### Sweep Funds (plan -> validate -> execute)\n\n> **Irreversible and high-impact:** `sweep_all.sh` requires `--confirm` to broadcast. Use `--dry-run` to preview without `--confirm`. A mistaken address can drain the entire wallet.\n\n- [ ] `scripts/check_balance.sh` — read `unlocked_balance` (the sweepable amount).\n- [ ] `scripts/validate_address.sh --address \"DESTINATION\"` — `valid:true` + `network_match:true`.\n- [ ] `scripts/sweep_all.sh --address \"DESTINATION\" --dry-run` — preview `amount` + `fee` without sending.\n- [ ] `scripts/sweep_all.sh --address \"DESTINATION\" --confirm` — execute; note `tx_hash`.\n- [ ] (Optional) `scripts/get_transfer.sh --tx-hash \"<tx_hash>\"` — confirm. Same retry-safety caveat as sends applies.\n\n### Check for Payments (with filtering)\n\n- [ ] `scripts/sync_status.sh` — confirm `daemon_connected:true` and that `height` is recent (else data may be stale). `list_incoming` auto-refreshes unless `MONERO_AUTO_REFRESH=false` or you pass `--no-refresh`; if auto-refresh is off and you need fresh data, re-enable it (there is no standalone refresh script).\n- [ ] `scripts/list_incoming.sh --since-block <height> --limit 50` — recent incoming transfers.\n- [ ] Read `confirmations` / `confirmed` per row (threshold = `MONERO_CONFIRMATIONS`, default `10`).\n- [ ] To pin a specific payment: `scripts/verify_payment.sh --tx-hash \"HASH\"` (or `--address` + `--expected-amount`).\n\n## Error codes\n\nEvery error is a JSON object on **stderr** plus a non-zero exit. It is **compact (single-line)** — but always parse it with `jq`, never line-by-line. The object has exactly `error`, `code`, and `message` (the `suggestion` key is reserved in the emitter but not currently populated; use the table below for recovery text):\n\n```json\n{\n  \"error\": true,\n  \"code\": \"TX_NOT_FOUND\",\n  \"message\": \"no transfer found for txid 7663438…\"\n}\n```\n\n**Load `references/error-runbook.md` when a script returns an error code and you need detailed, per-code recovery steps.**\n\n| Code | Meaning | Retryable | One-line recovery |\n|------|---------|:---------:|-------------------|\n| `CONFIG_MISSING` | Required env var / arg not set | No | Run `./setup.sh`; supply the missing `--flag`. |\n| `CONFIG_INVALID` | `.env` has bad syntax/metachars | No | Inspect `.env`; fix malformed lines; do not source it. |\n| `CONFIRM_REQUIRED` | `--confirm` not provided for destructive operation | No | Add `--confirm` to broadcast, or `--dry-run` to preview without broadcasting. |\n| `RPC_UNREACHABLE` | Cannot reach monero-wallet-rpc | Yes | Start/check `monero-wallet-rpc`; re-check. (Do NOT treat a send timeout with this code as \"tx absent\".) |\n| `WALLET_NOT_LOADED` | Wallet name != loaded wallet | No | `open_wallet` the right wallet; check `MONERO_WALLET_NAME`. |\n| `WALLET_LOCKED` | Wallet file locked elsewhere | No | Find/kill the holder (`lsof \\| grep wallet.keys`) or wait. |\n| `DAEMON_DISCONNECTED` | Wallet RPC can't reach daemon | Yes | Check/restart `monerod`. |\n| `INSUFFICIENT_BALANCE` | Not enough unlocked funds | No | `check_balance.sh`; wait for unlocks or reduce amount. |\n| `AMOUNT_INVALID` | Amount <=0 / >12 decimals / >balance | No | Correct the amount string. |\n| `INVALID_ADDRESS` | Bad format/checksum | No | Re-check the address; do not use. |\n| `NETWORK_MISMATCH` | Valid address, wrong network | No | Use an address for `MONERO_NETWORK` (mainnet/stagenet). |\n| `INVALID_INPUT` | Bad flag value (e.g. priority 0-4, tx-hash, label) | No | Correct the argument value. |\n| `SYNC_FAILED` / `REFRESH_FAILED` | Wallet sync/refresh failed | Yes | `sync_status.sh`; may need to restart wallet RPC. |\n| `TX_RELAY_FAILED` | Tx created but not broadcast | No | `get_transfer.sh --tx-hash`; may need manual relay. |\n| `RATE_LIMITED` | Lock acquisition timed out / daemon busy | Yes | Wait; reduce call frequency. |\n| `TX_NOT_FOUND` | Hash unknown to this wallet | No | Re-check the hash; for sends this means \"safe to retry\" (see retry-safety). |\n| `PROOF_INVALID` | Payment proof verification failed | No | Reject; ask payer to re-issue proof. |\n\nTransient codes (`RPC_UNREACHABLE`, `DAEMON_DISCONNECTED`, `SYNC_FAILED`, `REFRESH_FAILED`, `RATE_LIMITED`) surface **immediately** — they are **not** auto-retried by the scripts. The retry helper (`lib/retry.sh`) exists and is unit-tested, but is **not** currently applied to any script RPC call (all scripts call `rpc_call` directly). `send_xmr`/`sweep_all` are intentionally never retried (non-idempotent). `get_transfer` and `check_tx_proof` are intentionally direct so they don't mask the retry-safety probe / proof classification. If a read-only op returns a transient code, **the agent should retry it itself** (never retry sends/sweeps — drive those via the decision gate above).\n\n## Refresh & concurrency\n\n- **Refresh:** controlled by `MONERO_AUTO_REFRESH` (default `true`) and `MONERO_REFRESH_MIN_INTERVAL` (default `30`s; a refresh is skipped if one happened within this window). Auto-refreshing ops accept `--no-refresh` to skip. The last-refresh timestamp lives in `$MONERO_LOCK_DIR/.last_refresh`.\n- **Concurrency:** every script takes an exclusive `flock` on `$MONERO_LOCK_DIR/agenta-monero.lock` (timeout `MONERO_LOCK_TIMEOUT`, default `60`s) before any RPC; lock contention surfaces as `RATE_LIMITED`. The lock is released on exit, coordinating multiple local agent processes against the wallet RPC's own serialization.\n\n**Load `references/env-reference.md` when you need the full environment-variable table (connection, network, refresh, retry, concurrency, TLS knobs) or the complete refresh-strategy / retry-backoff details.**\n\nFile v0.1.2:README.md\n\n# Agenta-Monero\n\n> Autonomous Monero (XMR) payments for Hermes and Openclaw agents via shell. JSON-in, JSON-out wrappers over `monero-wallet-rpc` for sending, receiving, verifying, and sweeping. Composable into agent-driven workflows.\n\n> **WARNING — Irreversible Financial Operations**\n>\n> Monero transactions are **irreversible**. `send_xmr.sh` and `sweep_all.sh` broadcast by default — use `--dry-run` to preview. `sweep_all.sh` transfers **all unlocked funds** to one destination; a mistaken or maliciously triggered sweep can drain the entire wallet balance. Always validate addresses and confirm amounts before executing.\n\n## What It Does\n\n| Command | Description |\n|---------|-------------|\n| `create_address.sh` | Generate a receive address with label |\n| `send_xmr.sh` | Send XMR (requires `--confirm`, supports `--dry-run`) |\n| `sweep_all.sh` | Sweep **all** wallet funds to a destination (requires `--confirm`, supports `--dry-run`) |\n| `check_balance.sh` | Check balance + unlock status |\n| `estimate_fee.sh` | Preview fees before sending |\n| `validate_address.sh` | Verify address format and network |\n| `get_transfer.sh` | Look up a transaction by hash |\n| `verify_payment.sh` | Confirm a payment was received |\n| `get_tx_proof.sh` / `check_tx_proof.sh` | Generate or verify payment proofs |\n| `list_incoming.sh` / `list_outgoing.sh` | List transactions with filtering |\n| `list_addresses.sh` | List subaddresses with balances |\n| `sync_status.sh` | Check daemon connection + wallet height |\n| `interactive_setup.sh` | First-time setup wizard |\n| `wallet_rpc_status.sh` / `stop_wallet_rpc.sh` | Manage the RPC daemon |\n\n## Prerequisites\n\n- **OS:** Linux or macOS (Windows not supported)\n- **Monero CLI tools** >= 0.18.0 ([download](https://getmonero.org/downloads/)) - at minimum `monero-wallet-rpc`\n- **Bash** >= 4, `curl`, `jq`, `flock` (util-linux)\n\n## Installation\n\n**Hermes:**\n```bash\ngit clone https://github.com/tibbar-etihw/agenta-monero.git ~/.hermes/skills/finance/agenta-monero\n```\n\n**OpenClaw:**\n```bash\ngit clone https://github.com/tibbar-etihw/agenta-monero.git ~/.openclaw/workspace/skills/finance/agenta-monero\n```\n\nOr tell your agent:\n> \"Install the agenta-monero skill from https://github.com/tibbar-etihw/agenta-monero\"\n\n**New to this?** See the [Getting Started guide](docs/GETTING_STARTED.md) for a detailed walkthrough covering wallet creation, daemon setup, and first-time configuration.\n\n## Configuration\n\nYour agent configures everything. Simply prompt it with:\n\n> \"Set up the Agenta-Monero skill.\"\n\n---\n\n<details>\n<summary>Manual configuration (advanced)</summary>\n\nCopy `.env.example` to `.env` and fill in your values:\n\n```bash\ncp .env.example .env\n```\n\nRequired variables:\n- `MONERO_RPC_URL` - wallet RPC endpoint (default: `http://127.0.0.1:18088`)\n- `MONERO_RPC_USER` / `MONERO_RPC_PASSWORD` - RPC credentials\n- `MONERO_WALLET_NAME` - must match the loaded wallet\n- `MONERO_WALLET_PASSWORD` - wallet password\n- `MONERO_NETWORK` - `mainnet` or `stagenet`\n\n> **Caution:** `.env` contains `MONERO_WALLET_PASSWORD` and RPC credentials. It is created with `chmod 600`, but on multi-user systems, shared CI, or agent workspaces with broad read access, anyone who reads this file can access the wallet and move funds. Do not commit `.env` to version control or include it in backups/log captures.\n\n</details>\n\n## Usage Examples\n\n```bash\n# Create a receive address\n./scripts/create_address.sh --label \"Payment from Alice\"\n\n# Check your balance\n./scripts/check_balance.sh\n\n# Send XMR (dry run first)\n./scripts/send_xmr.sh --address \"RECIPIENT\" --amount \"1.5\" --dry-run\n./scripts/send_xmr.sh --address \"RECIPIENT\" --amount \"1.5\" --confirm\n\n# Verify a payment\n./scripts/verify_payment.sh --tx-hash \"HASH\" --expected-amount \"1.5\"\n\n# Estimate fees\n./scripts/estimate_fee.sh --address \"RECIPIENT\" --amount \"1.5\"\n\n# List recent incoming transactions\n./scripts/list_incoming.sh --since-block 1500000 --limit 50\n```\n\n## How It Works\n\nAll scripts communicate with `monero-wallet-rpc` via a single `/json_rpc` endpoint. Credentials are stored in a netrc file (never passed via command line). The `.env` file is parsed safely - never sourced.\n\n- **Auto-refresh**: Balance/transfer/verify operations auto-refresh the wallet. Use `--no-refresh` to skip.\n- **Concurrency**: Scripts use file locking (`flock`) to coordinate multiple processes.\n- **Money math**: All amounts are integer piconeros internally (1 XMR = 10^12). XMR decimal strings appear in output.\n\n## Error Handling\n\nErrors are JSON on stderr with an error code:\n\n```json\n{\"error\":true,\"code\":\"INSUFFICIENT_BALANCE\",\"message\":\"not enough unlocked funds\"}\n```\n\nCommon codes: `CONFIG_MISSING`, `RPC_UNREACHABLE`, `WALLET_NOT_LOADED`, `INSUFFICIENT_BALANCE`, `INVALID_ADDRESS`, `NETWORK_MISMATCH`, `TX_NOT_FOUND`\n\nSee `references/error-runbook.md` for detailed recovery steps.\n\n## Testing\n\nTests use an in-process Python mock RPC server - no daemon or network required.\n\n```bash\nbats tests/                    # Run all tests\nbats tests/send_xmr.bats      # Run single test file\n```\n\nRequires: `bats`, `python3`\n\n## Documentation\n\n- `SKILL.md` - Full agent-facing reference\n- `references/rpc-reference.md` - RPC method details\n- `references/error-runbook.md` - Per-error recovery steps\n- `references/env-reference.md` - Environment variable table\n- `docs/GETTING_STARTED.md` - Install walkthrough\n\n## WARNING\nNever fund your agent's Monero wallet with more than what you are willing to potentially lose. Agents make mistakes and misunderstand instructions all the time.\n\n## License\n\nMIT\n\n## Donations\n\nIf you find this useful, donations are appreciated:\n\n**Monero:**\n```\n82fPMdPyWS5jEvW3TzH8ibWmrj2Uu1hmNNo7n1W2bdyMEGTDEUN6ecXYHjn6TnAxan9N3LhDS678KfzagsVuMYYk3hXZ2gR\n```\n\nFile v0.1.2:_meta.json\n\n{\n  \"ownerId\": \"kn76dhwaqd2zm8bn4qhjp3c7bd8bcppg\",\n  \"slug\": \"agenta-monero\",\n  \"version\": \"0.1.2\",\n  \"publishedAt\": 1785258846093\n}\n\nFile v0.1.2:references/env-reference.md\n\n# Environment Variables\n\nAll configuration is read from `.env` (parsed safely — never sourced) at the skill root. Copy `.env.example` to `.env` and edit; run `./setup.sh` after changing it. Values shown are defaults.\n\n## Connection\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_RPC_URL` | `http://127.0.0.1:18088` | URL of the running `monero-wallet-rpc`. |\n| `MONERO_RPC_USER` | _(empty)_ | RPC authentication username. Written into `$MONERO_LOCK_DIR/.netrc` (mode `0600`). |\n| `MONERO_RPC_PASSWORD` | _(empty)_ | RPC authentication password. Written into `.netrc`; never passed on the command line. |\n| `MONERO_WALLET_NAME` | _(empty)_ | Wallet name; must match the wallet loaded in the RPC server. |\n\n## Network\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_NETWORK` | `mainnet` | `mainnet` \\| `stagenet`. `validate_address` compares each address's `nettype` against this to derive `network_match`. |\n\n## Lifecycle\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_LIFECYCLE` | `none` | `none` = assume the wallet RPC is already running (the supported mode). `full` = the agent is expected to manage daemon + wallet lifecycle (reserved). |\n\n## Remote node (optional)\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_REMOTE_NODE` | _(empty)_ | Remote node hostname/IP, if used. |\n| `MONERO_REMOTE_PORT` | _(empty)_ | Remote node port. |\n\n## Display\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_CONFIRMATIONS` | `10` | Blocks before a payment is considered `confirmed`. Used by `verify_payment`, `get_transfer`, `list_incoming`. |\n| `MONERO_AMOUNT_FORMAT` | `xmr` | `xmr` \\| `piconero`. Output amount rendering (scripts emit XMR decimal strings by default). |\n\n## Refresh\n\nThere is no `sync` RPC; the wallet refreshes from the daemon via `refresh`, which can take seconds-to-minutes. Refresh is **operation-aware** (see `rpc-reference.md` for the per-op table).\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_AUTO_REFRESH` | `true` | `true` = refresh before balance/transfer/verify ops; `false` = never auto-refresh. |\n| `MONERO_REFRESH_MIN_INTERVAL` | `30` | Minimum seconds between refreshes (caching). A refresh is skipped if the last one was more recent than this. Stored in `$MONERO_LOCK_DIR/.last_refresh`. |\n| `MONERO_REFRESH_TIMEOUT` | `120` | Maximum seconds for a single `refresh` operation. |\n\n**Override:** any auto-refreshing script accepts `--no-refresh` (works in **any** argument position) to skip the refresh step — useful for fast read-only checks when you can tolerate slightly stale data.\n\n## Retry\n\nThe retry helper (`lib/retry.sh`) is **available and unit-tested, but NOT currently applied** to any script RPC call — all scripts call `rpc_call` directly. `send_xmr` and `sweep_all` are intentionally never retried (non-idempotent); `get_transfer` and `check_tx_proof` are intentionally direct so retries don't mask the retry-safety probe / proof classification. Transient codes surface immediately; agents should retry read-only ops themselves (never sends/sweeps). The variables below are reserved for future use and have **no effect today**.\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_RETRY_MAX` | `2` | (Reserved, not currently applied.) Maximum retry attempts for transient errors (`RPC_UNREACHABLE`, `DAEMON_DISCONNECTED`, `SYNC_FAILED`, `REFRESH_FAILED`, `RATE_LIMITED`). |\n| `MONERO_RETRY_BACKOFF` | `1` | (Reserved, not currently applied.) Initial backoff in seconds; **doubles per retry** (1, 2, 4, ...). |\n\n## Concurrency\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_LOCK_DIR` | `/tmp/agenta-monero` | Directory for the lock file + netrc. Created with mode `0700`. |\n| `MONERO_LOCK_TIMEOUT` | `60` | Maximum seconds to wait to acquire the `flock`. Contention surfaces as `RATE_LIMITED`. |\n\nEvery script acquires an exclusive `flock` on `$MONERO_LOCK_DIR/agenta-monero.lock` before any RPC, coordinating multiple local agent processes against the wallet RPC's own serialization. The lock is released on exit.\n\n## Advanced\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_RPC_TIMEOUT` | `30` | curl timeout in seconds for individual RPC calls. |\n| `MONERO_RPC_SSL_CACERT` | _(empty)_ | Path to a CA cert for self-signed TLS. |\n| `MONERO_RPC_SSL_CAPATH` | _(empty)_ | Path to a CA cert directory. |\n\n`setup.sh` warns if `MONERO_RPC_URL` uses `http://` for a non-localhost host.\n\nFile v0.1.2:references/error-runbook.md\n\n# Error Recovery Runbook\n\nFull recovery procedures for every error code emitted by Agenta-Monero scripts. Every error is emitted to **stderr** as a single-line (compact) JSON object and the script exits non-zero — parse it with `jq`, not line-by-line:\n\n```json\n{\n  \"error\": true,\n  \"code\": \"WALLET_NOT_LOADED\",\n  \"message\": \"Wallet 'my_wallet' is not loaded in the RPC server\"\n}\n```\n\nParse `code` to branch; read `message` for specifics. (The `suggestion` key is reserved in the emitter but not currently populated — use the Recovery column below for guidance.)\n\n## Error codes (full table)\n\n| Code | Meaning | Retryable | Recovery |\n|------|---------|:---------:|----------|\n| `CONFIG_MISSING` | Required env var not set, or a required `--flag` omitted | No | Run `./setup.sh` to create `.env`, fill required values. For missing flags, supply the required argument (`--address`, `--amount`, `--tx-hash`, `--proof`, etc.). |\n| `CONFIG_INVALID` | `.env` contains invalid syntax or shell metacharacters | No | Inspect `.env` for metacharacters or malformed lines; fix and retry. Never `source .env` — it is parsed safely by design. |\n| `RPC_UNREACHABLE` | Cannot connect to `monero-wallet-rpc` | Yes | Confirm `monero-wallet-rpc` is running and `MONERO_RPC_URL` is correct; start it if not. **For a send/sweep timeout, this code means the transaction status is UNKNOWN — do NOT treat it as \"absent\" and do NOT retry the send;** fix connectivity and re-check with `get_transfer.sh --tx-hash`. |\n| `WALLET_NOT_LOADED` | Wallet name doesn't match the loaded wallet | No | Open the correct wallet in the RPC server (`open_wallet`); verify `MONERO_WALLET_NAME`. |\n| `WALLET_LOCKED` | Wallet file locked by another process | No | Find the holder (`lsof | grep wallet.keys`); kill it or wait for release. |\n| `DAEMON_DISCONNECTED` | Wallet RPC can't reach the daemon | Yes | Check daemon status; restart `monerod` if needed. |\n| `INSUFFICIENT_BALANCE` | Not enough unlocked funds | No | `check_balance.sh` to see available funds; wait for unlocks or reduce the amount. |\n| `AMOUNT_INVALID` | Amount negative, too many decimals (>12), or exceeds balance | No | Correct the amount string (positive decimal, <=12 fractional digits). |\n| `INVALID_ADDRESS` | Address format/checksum invalid | No | Re-check the address; do not use it. |\n| `NETWORK_MISMATCH` | Address valid but on the wrong network | No | Use an address for the configured `MONERO_NETWORK` (mainnet/stagenet). |\n| `INVALID_INPUT` | Bad argument value (priority not 0-4, tx-hash not 64 lowercase hex, label too long/has control chars, `--dest` not a JSON array) | No | Correct the argument value. |\n| `SYNC_FAILED` | Wallet sync failed | Yes | Run `sync_status.sh` to diagnose; may need to restart wallet RPC. |\n| `REFRESH_FAILED` | Wallet refresh failed | Yes | Run `sync_status.sh`; may need to restart wallet RPC; pass `--no-refresh` to bypass on auto-refreshing ops if you can tolerate stale data. |\n| `TX_RELAY_FAILED` | Transaction created but relay failed | No | `get_transfer.sh --tx-hash` to check state; the tx may need manual relay. |\n| `RATE_LIMITED` | Too many requests / lock acquisition timeout | Yes | Wait and retry; reduce call frequency. |\n| `TX_NOT_FOUND` | Transaction hash not found in wallet | No | Re-check the hash. **For a send-timeout retry-safety check, this specifically means the tx is genuinely absent -> safe to retry the send.** |\n| `PROOF_INVALID` | Payment proof verification failed | No | Reject the proof; ask the payer to re-issue with `get_tx_proof.sh`. |\n\nAdditional codes that may surface from RPC plumbing: `DEST_JSON_INVALID` (`--dest` is not a valid JSON array of `{address,amount}`) and `RPC_ERROR` (generic wallet-side RPC error not matching a specific code).\n\n## Edge cases\n\n- **Wallet RPC not running:** `rpc_check_connection` fails fast with `RPC_UNREACHABLE`.\n- **Wallet file locked:** detected via RPC error message; mapped to `WALLET_LOCKED`.\n- **Wrong network:** `validate_address` returns `network_match=false` -> `NETWORK_MISMATCH` (distinct from a malformed address -> `INVALID_ADDRESS`).\n- **Zero balance:** `check_balance` returns `0.0` values gracefully.\n- **No transactions:** `list_incoming`/`list_outgoing` return `[]`.\n- **Partial sync:** `sync_status` reports only wallet `height` + `daemon_connected` (`true` iff the wallet RPC responded to both probes). It deliberately does **not** claim synced/not-synced — the wallet RPC cannot honestly report the daemon's sync target — so it never gives false confidence. For daemon sync progress, query `monerod` directly.\n- **Timeout:** curl timeout `30`s default (`MONERO_RPC_TIMEOUT`); refresh timeout `120`s (`MONERO_REFRESH_TIMEOUT`).\n- **Large amount precision:** all internal arithmetic is integer piconeros; XMR decimal conversion is string-based, never floating-point.\n- **Concurrent access:** scripts take an exclusive `flock` on `$MONERO_LOCK_DIR/agenta-monero.lock` (timeout `MONERO_LOCK_TIMEOUT`); lock contention surfaces as `RATE_LIMITED`.\n\n## Retry logic (available, but NOT currently applied)\n\nThe retry helper (`lib/retry.sh`) is **available and unit-tested, but is NOT currently applied to script RPC calls** — all scripts call `rpc_call` directly.\n\n- `MONERO_RETRY_MAX` (default `2`) — maximum retry attempts for transient errors.\n- `MONERO_RETRY_BACKOFF` (default `1`) — initial backoff in seconds; **doubles per retry** (1, 2, 4, ...).\n\nThese variables are reserved for future use and have **no effect today**. `is_retryable` classifies the transient codes above (`RPC_UNREACHABLE`, `DAEMON_DISCONNECTED`, `SYNC_FAILED`, `REFRESH_FAILED`, `RATE_LIMITED`), but no script routes its calls through `retry_with_backoff`. Transient codes therefore surface **immediately**.\n\nThis is intentional for the destructive paths: **`send_xmr` and `sweep_all` must never be auto-retried** (non-idempotent — an automatic retry could double-spend). Drive their retry manually via the retry-safety decision gate in SKILL.md (timeout -> `get_transfer.sh --tx-hash` -> retry only on `TX_NOT_FOUND`; never on `RPC_UNREACHABLE`). `get_transfer` and `check_tx_proof` are also intentionally direct so that an automatic retry would not mask the retry-safety probe or proof classification. For read-only ops that surface a transient code, **the agent should retry them itself**.\n\n## Send retry-safety decision gate (recap)\n\n```text\nsend_xmr timed out / uncertain\n        |\n        v\nDo you have a tx_hash?\n        |\n        +-- NO (pure transport failure / RPC_UNREACHABLE, no payload)\n        |       -> status UNKNOWN: do NOT retry; fix connectivity, then\n        |          reconcile via list_outgoing.sh (match amount/timestamp)\n        |\n        +-- YES -> get_transfer.sh --tx-hash <hash>\n                |\n                +-- success (tx present)         -> DONE  (do NOT re-send)\n                +-- code == TX_NOT_FOUND         -> SAFE to retry the send\n                +-- code == RPC_UNREACHABLE      -> STOP: status UNKNOWN, fix connectivity, re-check\n                +-- (any other code)             -> STOP: diagnose before acting\n```\n\nThe asymmetry is deliberate: `TX_NOT_FOUND` is a wallet-side \"this hash is not here\" answer; `RPC_UNREACHABLE` means \"I could not ask the wallet at all\". Treating the latter as \"absent\" risks a double-spend.\n\nFile v0.1.2:references/rpc-reference.md\n\n# RPC Reference\n\nFull detail for every operation: exact flags, the underlying JSON-RPC `method` + `params`, the complete output object, behavior notes, and whether the script auto-refreshes. All RPC methods are POSTed to `$MONERO_RPC_URL/json_rpc` as `{\"jsonrpc\":\"2.0\",\"id\":\"...\",\"method\":\"<m>\",\"params\":{...}}` with netrc auth. Amounts inside `params` are integer **piconeros** (1 XMR = 10^12); amounts in script output are XMR decimal strings.\n\n## Refresh classification\n\n| Script | Auto-refresh? | Why |\n|--------|:-------------:|-----|\n| `create_address` | No | Address creation does not depend on chain state. |\n| `send_xmr` | Yes | Needs current balance to validate sufficiency. |\n| `estimate_fee` | No | Fee uses current mempool, not a full refresh. |\n| `sweep_all` | Yes | Needs current balance to know the sweepable amount. |\n| `check_balance` | Yes | Balance depends on chain state. |\n| `list_incoming` | Yes | Transfer list depends on chain state. |\n| `list_outgoing` | Yes | Transfer list depends on chain state. |\n| `verify_payment` | Yes | Confirmation count depends on chain state. |\n| `get_transfer` | Yes | Transfer details depend on chain state. |\n| `get_tx_proof` | No | Proof generation does not depend on chain state. |\n| `check_tx_proof` | Yes | Confirmation count in proof depends on chain state. |\n| `list_addresses` | No | Address listing does not depend on chain state (uses `get_address`, not `get_balance`). |\n| `validate_address` | No | Validation is purely format/checksum/network. |\n| `sync_status` | No | This *is* the status check (point-in-time). |\n\nEvery auto-refreshing script accepts `--no-refresh` (works in any argument position).\n\n---\n\n## create_address.sh\n\n**Flags:** `--label \"optional label\"` (optional), `--account N` (optional, default `0`).\n\n**RPC:** `create_address`\n```json\n{\"method\":\"create_address\",\"params\":{\"account_index\":0,\"label\":\"Payment from Alice\"}}\n```\n\n**Output:**\n```json\n{\"address\":\"88bc...\",\"address_index\":5,\"account\":0}\n```\nValidates label length (<=255 chars, no control characters). Does not auto-refresh.\n\n## send_xmr.sh\n\n**Flags:**\n- Single destination: `--address \"ADDR\" --amount \"1.5\"` (required unless `--dest`).\n- Multi-destination: `--dest '[{\"address\":\"ADDR1\",\"amount\":\"1.0\"},{\"address\":\"ADDR2\",\"amount\":\"2.0\"}]'` (valid JSON array — bare comma-separated streams are rejected).\n- `--priority 0` (default `0`; range 0-4 where **0=default, 1=unimportant, 2=normal, 3=elevated, 4=priority**).\n- `--get-tx-key` (return the transaction key; if omitted, `get_tx_key:false`).\n- `--dry-run` (calls `transfer` with `do_not_relay:true`; returns fee + tx hash without broadcasting).\n\n**RPC:** `transfer`\n```json\n{\"method\":\"transfer\",\"params\":{\"destinations\":[{\"address\":\"ADDR\",\"amount\":1500000000000}],\"priority\":0,\"get_tx_key\":true,\"do_not_relay\":false}}\n```\n(`amount` is piconeros.)\n\n**Output:**\n```json\n{\"tx_hash\":\"7663438...\",\"fee\":\"0.0000869\",\"amount\":\"1.5\",\"tx_key\":\"...\"}\n```\n`tx_key` is present only when `--get-tx-key` is supplied.\n\n**Behavior:** validates each destination via `validate_address` (one RPC per destination — not parallelized); validates amounts (positive, <=12 decimals); pre-checks balance via `get_balance`; converts to piconeros; calls `transfer`. **Not idempotent / not auto-retried.** On timeout, use `get_transfer.sh --tx-hash` before retrying (see SKILL.md retry-safety).\n\n## estimate_fee.sh\n\n**Flags:** same as `send_xmr.sh` (`--address`/`--amount` or `--dest`, `--priority`). Does **not** accept `--get-tx-key` or `--dry-run` (it is always a dry run).\n\n**RPC:** `transfer` with `do_not_relay:true`, `get_tx_key:false`.\n```json\n{\"method\":\"transfer\",\"params\":{\"destinations\":[{\"address\":\"ADDR\",\"amount\":1500000000000}],\"priority\":0,\"get_tx_key\":false,\"do_not_relay\":true}}\n```\n\n**Output:**\n```json\n{\"fee\":\"0.0000869\",\"amount\":\"1.5\",\"priority\":0,\"num_destinations\":1}\n```\nDoes not broadcast, does not auto-refresh. Validates addresses/amounts identically to `send_xmr`.\n\n## sweep_all.sh\n\n**Flags:** `--address \"ADDR\"` (required), `--account N` (optional, default `0`), `--subaddress N` (optional — sweep one subaddress; omit for all), `--priority 0` (optional, default `0`), `--dry-run` (optional).\n\n**RPC:** `sweep_all`\n```json\n{\"method\":\"sweep_all\",\"params\":{\"address\":\"ADDR\",\"account_index\":0,\"priority\":0,\"do_not_relay\":false}}\n```\nWith `--subaddress N`, `params` additionally includes `\"subaddr_indices\":[N]`.\n\n**Output:**\n```json\n{\"tx_hash\":\"7663438...\",\"fee\":\"0.0000869\",\"amount\":\"8.2\"}\n```\nValidates the destination address before sweeping. **Same non-idempotency caveat as `send_xmr`** — not auto-retried.\n\n## check_balance.sh\n\n**Flags:** `--account N` (optional, default `0`).\n\n**RPC:** `refresh` (if auto-refresh enabled and interval elapsed), then `get_balance`:\n```json\n{\"method\":\"get_balance\",\"params\":{\"account_index\":0}}\n```\n\n**Output:**\n```json\n{\"balance\":\"10.5\",\"unlocked_balance\":\"8.2\",\"blocks_to_unlock\":42,\"time_to_unlock\":30240,\"account\":0}\n```\n`blocks_to_unlock` and `time_to_unlock` are **read directly from the native `get_balance` response** (the wallet RPC computes them — no client-side derivation).\n\n## get_transfer.sh\n\n**Flags:** `--tx-hash \"HASH\"` (required; 64 lowercase hex chars).\n\n**RPC:** `refresh` (if enabled), then `get_transfer_by_txid`:\n```json\n{\"method\":\"get_transfer_by_txid\",\"params\":{\"txid\":\"c36258a...\"}}\n```\n\n**Output:**\n```json\n{\"tx_hash\":\"c36258a...\",\"amount\":\"1.5\",\"fee\":\"0.0000435\",\"direction\":\"in\",\"confirmations\":15,\"address\":\"77Vx9cs...\",\"address_index\":3,\"timestamp\":1535918400,\"confirmed\":true,\"unlock_time\":0}\n```\n`direction` is the wallet's transfer `type` (`in`/`out`/`pool`/`pending`). `confirmed` is `confirmations >= MONERO_CONFIRMATIONS`.\n\n**Failure modes (critical for send retry-safety):**\n- `TX_NOT_FOUND` — hash is genuinely absent from the wallet (wallet-side error or empty result). For a send-timeout check, this means \"safe to retry\".\n- `RPC_UNREACHABLE` — transport/daemon down (could not check). The transaction status is **unknown**, not absent. Propagated verbatim; **do not** treat as a \"safe to retry\" signal.\n\n## verify_payment.sh\n\n**Flags:** either `--tx-hash \"HASH\"`, **or** `--address \"ADDR\" --expected-amount \"1.5\"` (mutually exclusive).\n\n**RPC:**\n- tx-hash mode: `get_transfer_by_txid` `{\"txid\":\"HASH\"}`.\n- address mode: `get_transfers` `{\"in\":true,\"out\":false,\"pool\":true,\"pending\":true}`, then client-side match on `address` + exact piconero `amount`.\n\n**Output:**\n```json\n{\"verified\":true,\"confirmations\":12,\"amount\":\"1.5\",\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"address_index\":3,\"confirmed\":true}\n```\n`verified:true` requires the transfer to be incoming **and** at/above `MONERO_CONFIRMATIONS`. `amount` is `null` when no match is found (and `verified:false`).\n\n## get_tx_proof.sh\n\n**Flags:** `--tx-hash \"HASH\"` `--address \"ADDR\"` (both required).\n\n**RPC:** `get_tx_proof`\n```json\n{\"method\":\"get_tx_proof\",\"params\":{\"txid\":\"c36258a...\",\"address\":\"77Vx9cs...\"}}\n```\n\n**Output:**\n```json\n{\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"proof\":\"ProofV1...\"}\n```\nGenerates a proof shareable with a third party. Does not auto-refresh.\n\n## check_tx_proof.sh\n\n**Flags:** `--tx-hash \"HASH\"` `--address \"ADDR\"` `--proof \"PROOF\"` (all required).\n\n**RPC:** `check_tx_proof`\n```json\n{\"method\":\"check_tx_proof\",\"params\":{\"txid\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"signature\":\"ProofV1...\"}}\n```\n(`proof` maps to the RPC's `signature` param.)\n\n**Output:**\n```json\n{\"verified\":true,\"confirmations\":15,\"amount\":\"1.5\",\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\"}\n```\nOn failure (wallet rejects the proof, `good=false`, or RPC error other than `RPC_UNREACHABLE`) returns `PROOF_INVALID`. `RPC_UNREACHABLE` is surfaced as-is (connectivity failure, not an invalid proof).\n\n## list_incoming.sh\n\n**Flags:**\n- (default): confirmed + unconfirmed.\n- `--all`: explicit alias for default.\n- `--confirmed-only`: only `confirmations >= MONERO_CONFIRMATIONS` (takes precedence over `--all` if both given).\n- `--since-block N`, `--since-timestamp N`, `--limit N` (default `100`), `--account N` (default `0`).\n\n**RPC:** `refresh` (if enabled), then `get_transfers`:\n```json\n{\"method\":\"get_transfers\",\"params\":{\"in\":true,\"out\":false,\"pool\":true,\"pending\":true,\"filter_by_height\":true,\"min_height\":1523000,\"account_index\":0}}\n```\n\n**Output** (array; empty `[]` when none):\n```json\n[{\"tx_hash\":\"c36258a...\",\"amount\":\"1.5\",\"confirmations\":15,\"address\":\"77Vx9cs...\",\"address_index\":3,\"timestamp\":1535918400,\"confirmed\":true,\"unlock_time\":0}]\n```\n\n## list_outgoing.sh\n\n**Flags:** `--since-block N`, `--since-timestamp N`, `--limit N` (default `100`), `--account N` (default `0`).\n\n**RPC:** `refresh` (if enabled), then `get_transfers` with `out:true` (and `in:false`).\n\n**Output** (array; empty `[]` when none):\n```json\n[{\"tx_hash\":\"a1b2c3...\",\"amount\":\"0.5\",\"fee\":\"0.0000435\",\"timestamp\":1535918500,\"address\":\"77Vx9cs...\",\"address_index\":3,\"unlock_time\":0}]\n```\n\n## list_addresses.sh\n\n**Flags:** `--account N` (optional, default `0`).\n\n**RPC:** `get_address` `{\"account_index\":0}` (uses `get_address`, not `get_balance`'s `per_subaddress`, because the latter only lists addresses with activity).\n\n**Output** (array):\n```json\n[{\"index\":0,\"address\":\"55LTR8...\",\"label\":\"Primary account\",\"balance\":\"0.5\",\"unlocked_balance\":\"0.5\"}]\n```\nDoes not auto-refresh.\n\n## validate_address.sh\n\n**Flags:** `--address \"ADDR\"` (required).\n\n**RPC:** `validate_address` **with `any_net_type:true`** so the real `nettype` is returned:\n```json\n{\"method\":\"validate_address\",\"params\":{\"address\":\"ADDR\",\"any_net_type\":true,\"allow_openalias\":false}}\n```\nRPC returns `valid`, `nettype`, `subaddress`, `integrated`, `openalias_address`.\n\n**Output:**\n```json\n{\"valid\":true,\"network\":\"mainnet\",\"network_match\":true,\"subaddress\":false,\"integrated\":false}\n```\n`network`/`network_match` are derived client-side: `network` is the RPC's `nettype`; `network_match` is `nettype == MONERO_NETWORK`. There is **no `checksum_valid` field** — the checksum is part of `valid`. This keeps `INVALID_ADDRESS` (`valid=false`) distinct from `NETWORK_MISMATCH` (`valid=true`, `network_match=false`). Does not auto-refresh.\n\n## sync_status.sh\n\n**Flags:** none.\n\n**RPC:** `get_height` and `get_version`, both via `/json_rpc`.\n\n**Output:**\n```json\n{\"height\":1523651,\"daemon_connected\":true,\"wallet_version\":196613}\n```\n`daemon_connected` is a **real reachability proxy**: `true` iff both `get_height` and `get_version` succeeded (if either fails the script exits `RPC_UNREACHABLE`). `wallet_version` is the raw integer from `get_version` (a packed integer such as `196613`, **not** a dotted string). The wallet RPC cannot honestly report the daemon's `target_height` or sync progress, so `synced`/`target_height` are intentionally **not** emitted (a prior version reported an always-true `synced`, which gave false confidence). Point-in-time; does not auto-refresh (it is the status check itself).\n\nFile v0.1.2:Agenta-Monero Security Review.md\n\n## agenta-monero\n\nSkill@tibbar-etihwv0.1.0Updated 5h ago\n\n## SkillSpector\n\n![](https://www.nvidia.com/favicon.ico)By NVIDIA\n\nVulnerability Patterns\n\n- Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands\n- Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration\n- Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access\n- Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep\n- Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults\n- Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger\n- MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration\n- Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code\n- Output HandlingUnvalidated Output Injection, Cross-Context Output, Unbounded Output\n- System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration\n- Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation\n- Rogue AgentSelf-Modification, Session Persistence\n- Behavioral ASTexec() Call, eval() Call, Dynamic Import\n- Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain\n- YARA SignaturesMalware Match, Webshell Match, Cryptominer Match\n- MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection\n\nShow less\n\nFindings (14)\n\n### Lp3\n\nMedium\n\nCategory\n\nMCP Least Privilege\n\nContent\n\n---\n\nConfidence\n\n93% confidence\n\nFinding\n\nThe skill clearly performs shell execution and file writes, including creating `.env`, `.netrc`, PID files, and launching `monero-wallet-rpc`, yet no declared permissions are documented. In an agent setting this weakens security boundaries because operators may approve or invoke the skill without understanding that it can persist secrets and start local processes.\n\n### Context-Inappropriate Capability\n\nMedium\n\nContent\n\n# --- Emit final JSON ---\njq -nc \\\n  --argjson ready \"$ready\" \\\n  --arg rpc_user \"$RPC_USER\" \\\n  --arg rpc_password \"$RPC_PASSWORD\" \\\n  --argjson rpc_port \"$RPC_PORT\" \\\n  --argjson wallet_pid \"${WALLET_PID:-null}\" \\\n  --arg wallet_rpc_log \"$LOG_FILE\" \\\n  --argjson warnings \"$warnings_json\" \\\n  '{ready:$ready, rpc_user:$rpc_user, rpc_password:$rpc_password, rpc_port:$rpc_port, wallet_pid:$wallet_pid, wallet_rpc_log:$wallet_rpc_log, warnings:$warnings}'\n\nConfidence\n\n97% confidence\n\nFinding\n\nThe script returns freshly generated RPC credentials, port, PID, and log path in stdout JSON. In an agent or automation context, stdout is commonly captured by orchestrators, logs, transcripts, or other tools, so this unnecessarily broadens secret exposure and gives attackers both authentication material and operational details for the wallet RPC process.\n\n### Missing User Warnings\n\nMedium\n\nContent\n\n> Autonomous Monero (XMR) payments for Hermes and Openclaw agents via shell. JSON-in, JSON-out wrappers over `monero-wallet-rpc` for sending, receiving, verifying, and sweeping — composable into agent-driven workflows.\n\nConfidence\n\n91% confidence\n\nFinding\n\nThe README prominently presents autonomous XMR sending, receiving, and sweeping for agent workflows, but it does not clearly warn that cryptocurrency transfers are irreversible and may cause permanent financial loss if an agent is misconfigured or tricked. In an agent-execution context, documenting high-risk payment actions without an explicit caution increases the chance of unsafe automation and accidental fund transfers.\n\n### Missing User Warnings\n\nMedium\n\nContent\n\n| `sweep_all.sh` | Sweep wallet funds to a destination |\n\nConfidence\n\n95% confidence\n\nFinding\n\nThe `sweep_all.sh` command is described as sweeping wallet funds to a destination, but there is no adjacent caution that this can drain essentially all available funds from the wallet. Because this skill is designed for agent-driven workflows, omission of a visible warning makes accidental or malicious-triggered total-balance transfer more dangerous than in a purely manual tool.\n\n### Missing User Warnings\n\nMedium\n\nContent\n\n- Write `.env` (chmod 600) with all values including `MONERO_WALLET_PASSWORD`.\n\nConfidence\n\n95% confidence\n\nFinding\n\nThe setup flow instructs storing `MONERO_WALLET_PASSWORD` in a persistent `.env` file and does not prominently warn users about the sensitivity and persistence of that secret. Because this skill manages real cryptocurrency funds, compromise of that file can directly enable wallet access and theft, especially on multi-user systems, backups, or agent workspaces with broad read access.\n\n### Vague Triggers\n\nMedium\n\nContent\n\nTell your Hermes agent: **\"Set up Monero payments.\"** The agent will:\n\nConfidence\n\n91% confidence\n\nFinding\n\nThe agent-trigger phrase 'Set up Monero payments.' is broad enough that ordinary user requests could unintentionally invoke a workflow that handles wallet paths, credentials, and service startup. In a cryptocurrency skill, accidental activation is more dangerous than usual because the resulting setup path touches sensitive secrets and can prepare the environment for real-funds operations.\n\n### Missing User Warnings\n\nHigh\n\nContent\n\njq -nc \\\n  --argjson ready \"$ready\" \\\n  --arg rpc_user \"$RPC_USER\" \\\n  --arg rpc_password \"$RPC_PASSWORD\" \\\n  --argjson rpc_port \"$RPC_PORT\" \\\n  --argjson wallet_pid \"${WALLET_PID:-null}\" \\\n  --arg wallet_rpc_log \"$LOG_FILE\" \\\n  --argjson warnings \"$warnings_json\" \\\n  '{ready:$ready, rpc_user:$rpc_user, rpc_password:$rpc_password, rpc_port:$rpc_port, wallet_pid:$wallet_pid, wallet_rpc_log:$wallet_rpc_log, warnings:$warnings}'\n\nConfidence\n\n99% confidence\n\nFinding\n\nThe final JSON includes rpc_user and rpc_password without any disclosure warning or masking. In this skill context, those credentials directly control a local Monero wallet RPC service capable of payment and wallet operations, so leaking them can enable unauthorized wallet access or fund movement if the service becomes reachable to other local users, containers, or forwarded interfaces.\n\n### Missing User Warnings\n\nMedium\n\nContent\n\nres=$(rpc_call transfer \"$params\")\n\nConfidence\n\n92% confidence\n\nFinding\n\nThe script performs a live Monero `transfer` by default and only avoids relaying when `--dry-run` is explicitly provided. In an agent skill context, this creates a real risk of unintended irreversible fund movement if upstream prompts, parameters, or tool invocations are mistaken, manipulated, or insufficiently confirmed by the user.\n\n### Missing User Warnings\n\nHigh\n\nContent\n\nres=$(rpc_call sweep_all \"$params\")\n\nConfidence\n\n92% confidence\n\nFinding\n\nThis script invokes the Monero wallet RPC `sweep_all` operation directly and will relay the transaction unless `--dry-run` is explicitly supplied. Because sweeping transfers essentially all available funds and is irreversible once broadcast, the lack of an explicit confirmation, interactive warning, or safer default materially increases the chance of accidental full-balance loss from misuse, automation mistakes, or prompt/agent abuse. In the context of a payment-management skill, this is especially dangerous because the tool is designed to move real cryptocurrency, so an unintended invocation can immediately cause unrecoverable asset transfer.\n\n### Missing User Warnings\n\nMedium\n\nContent\n\n@test \"script_init exports MONERO_WALLET_PASSWORD from .env\" {\n  d=\"$(mktemp -d)\"; printf 'MONERO_NETWORK=\"mainnet\"\\nMONERO_RPC_URL=\"http://127.0.0.1:18099\"\\nMONERO_LOCK_DIR=\"%s\"\\nMONERO_WALLET_PASSWORD=\"secret123\"\\n' \"$(mktemp -d)\" > \"$d/.env\"\n  mkdir -p \"$d/lib\" \"$d/scripts\"\n  cp \"$LIB\"/*.sh \"$d/lib/\"\n  cat > \"$d/scripts/x.sh\" <<'SH'\n#!/usr/bin/env bash\nset -euo pipefail\nsource \"$(dirname \"${BASH_SOURCE[0]}\")/../lib/common.sh\"\nscript_init\necho \"wp=${MONERO_WALLET_PASSWORD}\"\nSH\n  chmod +x \"$d/scripts/x.sh\"\n  run env -u MONERO_RPC_URL -u MONERO_NETWORK -u MONERO_LOCK_DIR -u MONERO_CONFIRMATIONS -u MONERO_WALLET_PASSWORD \\\n\nConfidence\n\n97% confidence\n\nFinding\n\nThis test writes a wallet password to a temporary .env file, loads it into the environment, and then echoes the secret into test output. Even though the value is a dummy test password, the pattern normalizes unsafe secret-handling behavior and could leak real credentials if the test is adapted, copied, or run with non-test values in CI logs or developer consoles.\n\n### Credential Access\n\nHigh\n\nCategory\n\nPrivilege Escalation\n\nContent\n\nNETRC_FILE=\"$dir/.netrc\"\n\nConfidence\n\n82% confidence\n\nFinding\n\n/.netrc\n\n### Credential Access\n\nHigh\n\nCategory\n\nPrivilege Escalation\n\nContent\n\n# --- Write .env ---\n\nConfidence\n\n88% confidence\n\nFinding\n\n.env\n\n### Credential Access\n\nHigh\n\nCategory\n\nPrivilege Escalation\n\nContent\n\n@test \"script_init exports MONERO_WALLET_PASSWORD from .env\" {\n\nConfidence\n\n89% confidence\n\nFinding\n\n.env\"\n\n### Tool Parameter Abuse\n\nHigh\n\nCategory\n\nTool Misuse\n\nContent\n\nrm -f \"$PID_FILE\" \"$PORT_FILE\" 2>/dev/null || true\n\nConfidence\n\n94% confidence\n\nFinding\n\nrm -f \"$PID_FILE\" \"$PORT_FILE\" 2>/dev/\n\nFile v0.1.2:docs/GETTING_STARTED.md\n\n# Getting Started with Agenta-Monero\n\nA guide for **new users** to install the Agenta-Monero skill and connect it to Monero (local node or remote node).\n\n---\n\n## How this skill fits together (read this first)\n\n```\n┌─────────────┐    JSON-RPC     ┌────────────────────┐    P2P     ┌──────────────┐\n│   Agent     │ ─────────────▶ │ monero-wallet-rpc  │ ─────────▶ │   monerod    │\n│  + skill    │   127.0.0.1    │  (you run this)    │            │ (the daemon) │\n└─────────────┘    :18088       └────────────────────┘            └──────────────┘\n                     ▲                                                     ▲\n                     │                                                     │\n              the skill talks                                        can be LOCAL\n              to THIS (the wallet                  (you run `monerod`)  ── or REMOTE ──\n              RPC, always on your                                       (a public node)\n              machine)\n```\n\n---\n\n## Quick Start — Choose Your Path\n\n### Path 1: Agent-Driven (recommended)\n\nTell your Hermes agent: **\"Set up the Agenta-Monero skill.\"** The agent will:\n1. Ask for your wallet file path and password.\n2. Ask: local daemon or remote node?\n3. Generate secure credentials, write `.env`, start `monero-wallet-rpc`, and verify readiness.\n\nThe agent passes flags: `--wallet-path`, `--wallet-password`, `--network`, `--daemon-type`, `--force`\n\n**Prerequisites:** `monero-wallet-rpc` installed + a wallet file created.\n- Download Monero CLI tools: https://getmonero.org/downloads/\n- Create a wallet: `monero-wallet-cli --generate-new-wallet ~/Monero/wallets/main --password 'PASS'`\n- (Stagenet for testing: add `--stagenet`, use https://stagenet-faucet.xmr-tw.org/ for free funds)\n\n### Path 2: Interactive Script\n\n```bash\n./scripts/interactive_setup.sh\n```\nFollow the prompts — it does the same as Path 1 but you drive it yourself.\n\n### Path 3: Step-by-Step (Advanced)\n\nSee the detailed walkthrough below. Use this if you want full control over each component.\n\n---\n\nTwo things to understand:\n\n1. **The skill always talks to `monero-wallet-rpc` on your own machine** (`http://127.0.0.1:18088`). You run `monero-wallet-rpc`; it holds your wallet file and keys.\n2. **`monero-wallet-rpc` talks to a `monerod` daemon**, which can be:\n   - **Local** — you run `monerod` yourself (full node, best privacy, slow first sync), or\n   - **Remote** — a public node (fast setup, lighter). Use `--untrusted-daemon` for privacy.\n\nSo \"**connect to a remote node**\" means telling your *wallet-rpc* to use a remote daemon — **not** pointing the skill at a remote server. The skill's `MONERO_RPC_URL` stays `http://127.0.0.1:18088`.\n\n> **First time? Use stagenet** (`--stagenet`, ports `38xxx`). Mainnet syncs for hours–days and real funds are at risk. See the stagenet path below.\n\n---\n\n## Prerequisites\n\n- **OS:** Linux or macOS (Windows not supported)\n- **Monero CLI tools** (`monerod`, `monero-wallet-cli`, `monero-wallet-rpc`) ≥ **0.18.0** — from https://getmonero.org/downloads/ or your package manager.\n- **Bash ≥ 4**, `curl`, `jq`, `flock` (util-linux) — standard on Linux/macOS (`brew install jq` on macOS).\n- **Agent:** Hermes or OpenClaw installed.\n\nCheck:\n```bash\nmonero-wallet-rpc --version\nbash --version | head -1\ncommand -v curl jq flock\n```\n\n---\n\n## Step 1 — Create a wallet (once)\n\nCreate a wallet file with `monero-wallet-cli`. **Write down the 25-word seed** it shows — that's the only way to recover funds.\n\n**Mainnet:**\n```bash\nmkdir -p ~/Monero/wallets\nmonero-wallet-cli --generate-new-wallet ~/Monero/wallets/main --password 'WALLET_PASS'\n# ... note the seed mnemonic, then type `exit`\n```\n\n**Stagenet (recommended for testing):**\n```bash\nmkdir -p ~/Monero/stagenet\nmonero-wallet-cli --stagenet --generate-new-wallet ~/Monero/stagenet/wallet --password 'WALLET_PASS'\n```\n\n> Fund a stagenet wallet free at https://stagenet-faucet.xmr-tw.org/ (or search \"monero stagenet faucet\").\n\n---\n\n## Step 2 — Start the daemon (choose local OR remote)\n\n### Option A — Local node (full node, best privacy)\n\n**Mainnet** (sync takes a long time the first run):\n```bash\nmonerod --detach              # or run in a foreground terminal\n```\n**Stagenet:**\n```bash\nmonerod --stagenet --detach\n```\nDaemon RPC ports: **mainnet `18081`**, **stagenet `38081`**. Check progress: `monerod -- status` or `tail -f ~/.bitmonero/bitmonero.log`.\n\n### Option B — Remote node (fast, no local sync)\n\nSkip running `monerod`; instead point `monero-wallet-rpc` at a public node in Step 3 with `--daemon-address <host>:<port> --untrusted-daemon`. Public nodes: https://monero.fail/ (pick one on your network — mainnet `:18081`, stagenet `:38081`).\n\n> **Privacy:** always use `--untrusted-daemon` with a remote node so your wallet doesn't reveal more than necessary to a third party.\n\n---\n\n## Step 3 — Start `monero-wallet-rpc` (the thing the skill talks to)\n\nRun this in its own terminal (or `--detach`). It loads your wallet and listens on `127.0.0.1:18088`.\n\n**Mainnet + LOCAL daemon:**\n```bash\nmonero-wallet-rpc \\\n  --wallet-file ~/Monero/wallets/main --password 'WALLET_PASS' \\\n  --rpc-bind-port 18088 --rpc-login username:password \\\n  --daemon-address 127.0.0.1:18081 --trusted-daemon\n```\n\n**Mainnet + REMOTE daemon (no local `monerod`):**\n```bash\nmonero-wallet-rpc \\\n  --wallet-file ~/Monero/wallets/main --password 'WALLET_PASS' \\\n  --rpc-bind-port 18088 --rpc-login username:password \\\n  --daemon-address node.example.com:18081 --untrusted-daemon\n```\n\n**Stagenet + LOCAL daemon (recommended for first run):**\n```bash\nmonero-wallet-rpc --stagenet \\\n  --wallet-file ~/Monero/stagenet/wallet --password 'WALLET_PASS' \\\n  --rpc-bind-port 38088 --rpc-login username:password \\\n  --daemon-address 127.0.0.1:38081 --trusted-daemon\n```\n\nNotes:\n- `--rpc-login username:password` — choose your own username and a strong password; the skill authenticates with these (via a netrc file, never on the command line).\n- `--rpc-bind-ip 127.0.0.1` is the default (loopback only). Do **not** expose the wallet RPC to the network without TLS + auth.\n- **Remote wallet-RPC** (uncommon — wallet-rpc on another server): add `--rpc-ssl enabled --rpc-ssl-autodetect`, bind to `0.0.0.0`, and set the skill's `MONERO_RPC_URL=https://server:port` plus `MONERO_RPC_SSL_CACERT` if self-signed.\n\nLeave it running, then verify it responds:\n```bash\ncurl -u username:password --digest \\\n  -X POST http://127.0.0.1:18088/json_rpc \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_height\"}' -H 'Content-Type: application/json'\n```\n\n---\n\n## Step 4 — Install the skill (manual copy — recommended)\n\n**Do I tell the agent to install it?** No. Hermes and OpenClaw **auto-discover** any skill directory containing a `SKILL.md` under their skills folder. So you place the skill there yourself; the agent picks it up automatically.\n\n**Why manual copy (not `hermes skills install`)?** `hermes skills install <url>` is for skills published to a hub/URL and pulls only `SKILL.md` + detected references. This skill is **script-heavy** (`scripts/*.sh`, `lib/*.sh`); a manual copy guarantees every file lands in place.\n\n**Hermes:**\n```bash\nmkdir -p ~/.hermes/skills/finance\ncp -r agenta-monero ~/.hermes/skills/finance/agenta-monero\ncd ~/.hermes/skills/finance/agenta-monero\n```\n\n**OpenClaw:**\n```bash\nmkdir -p ~/.openclaw/workspace/skills/finance\ncp -r agenta-monero ~/.openclaw/workspace/skills/finance/agenta-monero\ncd ~/.openclaw/workspace/skills/finance/agenta-monero\n```\n\n(If you've published the skill to a GitHub repo and prefer the CLI: `hermes skills install https://your-repo/SKILL.md` — but verify `scripts/` and `lib/` came along afterwards.)\n\n---\n\n## Step 5 — Configure `.env`\n\n```bash\n# Hermes:\ncd ~/.hermes/skills/finance/agenta-monero\n\n# OpenClaw:\ncd ~/.openclaw/workspace/skills/finance/agenta-monero\n\ncp .env.example .env\nchmod 600 .env\n```\n\nEdit `.env` — set at least these:\n```bash\nMONERO_RPC_URL=\"http://127.0.0.1:18088\"   # 127.0.0.1:38088 for stagenet\nMONERO_RPC_USER=\"username\"               # same as --rpc-login username from Step 3\nMONERO_RPC_PASSWORD=\"password\"            # same as --rpc-login password from Step 3\nMONERO_NETWORK=\"mainnet\"                  # mainnet | stagenet\n```\nLeave the rest at defaults. Keep `.env` out of version control (the skill's `.gitignore` already excludes it).\n\n---\n\n## Step 6 — Run `setup.sh` (readiness check)\n\n```bash\n./setup.sh\n```\nExpect:\n```json\n{\"ready\":true,\"deps_ok\":true,\"config_ok\":true,\"connection_ok\":true,\"wallet_loaded\":true,\"version\":196613,\"warnings\":[]}\n```\n- `ready:true` → you're set.\n- `connection_ok:false` → wallet-rpc isn't running / wrong port or creds (see Troubleshooting).\n- `wallet_loaded:false` → wallet-rpc is up but no wallet is loaded. Fix by starting wallet-rpc with `--wallet-file` (Step 3), then re-run `setup.sh`.\n\n---\n\n## Step 7 — Use it\n\nYou can now either **ask the Hermes agent** in plain language, or **run scripts directly**.\n\nAsk the agent, e.g.:\n> \"Generate a Monero subaddress labelled 'invoice 42'.\"\n> \"Send 1.5 XMR to 88bc…, dry-run first to preview the fee.\"\n> \"Check my balance and how many blocks are locked.\"\n\nOr run a script directly (from the skill directory):\n```bash\n./scripts/sync_status.sh\n./scripts/create_address.sh --label \"invoice 42\"\n./scripts/estimate_fee.sh --address 88bc… --amount 1.5\n./scripts/send_xmr.sh --address 88bc… --amount 1.5 --dry-run    # preview, no broadcast\n./scripts/send_xmr.sh --address 88bc… --amount 1.5              # actually send\n./scripts/get_transfer.sh --tx-hash <hash>                      # confirm it landed\n./scripts/check_balance.sh\n```\n\nEvery script prints JSON on stdout and structured errors on stderr. Full per-operation details: see `SKILL.md` and `references/`.\n\n---\n\n## Troubleshooting\n\n| Symptom | Likely cause / fix |\n|---|---|\n| `RPC_UNREACHABLE` | wallet-rpc not running, wrong `MONERO_RPC_URL` port, or wrong `--rpc-login` creds. Re-run the curl check in Step 3. |\n| `connection_ok:false` from setup | same as above. |\n| `wallet_loaded:false` | wallet-rpc is up but no wallet open — start it with `--wallet-file … --password …`. |\n| `CONFIG_INVALID` on `.env` | a line has shell metacharacters (`$ \\` ( ) { } ; | & < >`) — the parser rejects them on purpose; simplify the value. |\n| Send times out / unsure if it sent | **do not just retry.** Run `./scripts/get_transfer.sh --tx-hash <hash>`. `TX_NOT_FOUND` → safe to retry. `RPC_UNREACHABLE` → status unknown, fix connectivity first, do **not** retry. |\n| Huge `daemon_connected`/stale balance | wallet isn't synced. Let `monerod` finish syncing (or wait for `monero-wallet-rpc` to refresh). |\n| Remote node rejected / slow | pick a different node from https://monero.fail/; keep `--untrusted-daemon`. |\n\nMore: `references/error-runbook.md`.\n\n---\n\n## Lifecycle Management\n\nAfter setup, `monero-wallet-rpc` runs in the background. Manage it with the following.\n\n### Start\n\nRun `./scripts/interactive_setup.sh --force` to restart with the existing `.env`, or start `monero-wallet-rpc` manually (see Step 3).\n\n### Stop\n\n```bash\n./scripts/stop_wallet_rpc.sh\n# or: kill $(cat $MONERO_LOCK_DIR/wallet-rpc.pid)\n```\n\n### Check status\n\n```bash\n./scripts/wallet_rpc_status.sh\n```\n\nEmits JSON: `running`, `pid`, `port`.\n\n---\n\n## Security checklist\n\n- ✅ `.env` is `chmod 600` and not committed.\n- ✅ wallet-rpc bound to `127.0.0.1` (default); strong `--rpc-login` secret.\n- ⚠️ **Process-table exposure:** `monero-wallet-rpc` accepts the wallet password only via `--password` (CLI), so it is visible in `ps aux` / `/proc/<pid>/cmdline` for the daemon's lifetime. This is an upstream limitation. Run on a single-user system, or restrict process-table visibility (dedicated user account, container, or PID namespace).\n- ✅ `--untrusted-daemon` for any remote node.\n- ✅ Test on **stagenet** before touching mainnet funds.\n- ✅ `--dry-run` / `estimate_fee.sh` before every real send.\n- ✅ Back up the 25-word wallet seed offline.\n\n## Next steps\n- Day-to-day usage & workflows: `SKILL.md`.\n- RPC details / error recovery / env vars: `references/`.\n\nFile v0.1.2:skill-card.md\n\n## Description:\n\nAgenta-Monero helps agents make and receive Monero (XMR) payments by creating addresses, checking balances, sending funds, estimating fees, verifying payments and proofs, sweeping funds, and managing wallet operations through monero-wallet-rpc.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[tibbar-etihw](https://clawhub.ai/user/tibbar-etihw)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers, operators, and agent users can use this skill to automate Monero wallet workflows such as receiving payments, sending or sweeping XMR with explicit approval, reconciling transactions, and verifying payment proofs.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Monero transactions are irreversible, and send or sweep actions can permanently move funds.\n\nMitigation: Require explicit human approval for every mainnet send or sweep, validate recipient addresses and amounts, and test workflows on stagenet before handling real funds.\n\nRisk: Local wallet state can expose wallet credentials or affect unrelated processes on shared systems.\n\nMitigation: Run the skill under an isolated single-user account or container, set MONERO_LOCK_DIR to a private directory, and avoid shared CI or multi-user machines until runtime-directory and PID-validation issues are fixed.\n\nRisk: .env and related runtime files can contain wallet passwords or RPC credentials.\n\nMitigation: Keep .env out of version control, backups, sync tools, and logs; restrict file permissions and review local workspace access before use.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/tibbar-etihw/skills/agenta-monero)\n- [Server-resolved GitHub provenance](https://github.com/tibbar-etihw/agenta-monero)\n- [Getting Started guide](docs/GETTING_STARTED.md)\n- [Environment Variables](references/env-reference.md)\n- [Error Recovery Runbook](references/error-runbook.md)\n- [RPC Reference](references/rpc-reference.md)\n- [Monero CLI downloads](https://getmonero.org/downloads/)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with shell commands and JSON command outputs]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Commands emit JSON objects or arrays on success and structured JSON errors on failure.]\n\n## Skill Version(s):\n\n0.1.2 (source: server release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v0.1.2:tests/fixtures/ca_acc/create_address.json\n\n{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"result\":{\"address\":\"SubAddr5\",\"address_index\":7}}\n\nFile v0.1.2:tests/fixtures/ca_nolabel/create_address.json\n\n{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"result\":{\"address\":\"Sub9\",\"address_index\":9}}\n\nFile v0.1.2:tests/fixtures/ca_q/create_address.json\n\n{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"result\":{\"address\":\"Q\",\"address_index\":2}}\n\nArchive v0.1.1: 226 files, 109091 bytes\n\nFiles: .env.example (875b), .gitignore (239b), docs (0b), docs/GETTING_STARTED.md (12436b), lib (0b), lib/common.sh (1195b), lib/config.sh (1322b), lib/format.sh (1436b), lib/retry.sh (742b), lib/rpc.sh (2353b), lib/validate.sh (846b), README.md (5703b), references (0b), references/env-reference.md (4659b), references/error-runbook.md (7331b), references/rpc-reference.md (10918b), scripts (0b), scripts/check_balance.sh (602b), scripts/check_tx_proof.sh (1751b), scripts/create_address.sh (608b), scripts/estimate_fee.sh (2416b), scripts/get_transfer.sh (2567b), scripts/get_tx_proof.sh (902b), scripts/interactive_setup.sh (9294b), scripts/list_addresses.sh (481b), scripts/list_incoming.sh (1526b), scripts/list_outgoing.sh (1286b), scripts/send_xmr.sh (3070b), scripts/stop_wallet_rpc.sh (1486b), scripts/sweep_all.sh (2720b), scripts/sync_status.sh (1004b), scripts/validate_address.sh (898b), scripts/verify_payment.sh (3098b), scripts/wallet_rpc_status.sh (1202b), setup.sh (3725b), SKILL.md (21264b), tests (0b), tests/check_balance.bats (853b), tests/check_tx_proof.bats (5529b), tests/common.bats (3538b), tests/config.bats (1871b), tests/create_address.bats (3648b), tests/estimate_fee.bats (3568b), tests/fixtures (0b), tests/fixtures/.gitkeep (0b), tests/fixtures/ca (0b), tests/fixtures/ca_acc (0b), tests/fixtures/ca_acc/create_address.json (76b), tests/fixtures/ca_nolabel (0b), tests/fixtures/ca_nolabel/create_address.json (72b), tests/fixtures/ca_q (0b), tests/fixtures/ca_q/create_address.json (69b), tests/fixtures/ca/create_address.json (76b), tests/fixtures/check_balance (0b), tests/fixtures/check_balance/get_balance.json (140b), tests/fixtures/check_balance/refresh.json (38b), tests/fixtures/ctp_bad (0b), tests/fixtures/ctp_bad/check_tx_proof.json (88b), tests/fixtures/ctp_bad/refresh.json (38b), tests/fixtures/ctp_err (0b), tests/fixtures/ctp_err/check_tx_proof.ERR.json (76b), tests/fixtures/ctp_err/refresh.json (38b), tests/fixtures/ctp_nr (0b), tests/fixtures/ctp_nr/check_tx_proof.json (99b), tests/fixtures/ctp_ok (0b), tests/fixtures/ctp_ok/check_tx_proof.json (100b), tests/fixtures/ctp_ok/refresh.json (38b), tests/fixtures/ef (0b), tests/fixtures/ef_bad (0b), tests/fixtures/ef_bad/transfer.json (111b), tests/fixtures/ef_bad/validate_address.json (51b), tests/fixtures/ef_multi (0b), tests/fixtures/ef_multi/transfer.json (109b), tests/fixtures/ef_multi/validate_address.json (108b), tests/fixtures/ef/transfer.json (111b), tests/fixtures/ef/validate_address.json (108b), tests/fixtures/gt (0b), tests/fixtures/gt_empty (0b), tests/fixtures/gt_empty/get_transfer_by_txid.json (38b), tests/fixtures/gt_empty/refresh.json (38b)\n\nFile v0.1.1:SKILL.md\n\n---\nname: agenta-monero\ndescription: \"Use when making or receiving Monero (XMR) payments. Generates addresses, sends payments, checks balances, verifies transactions, generates and verifies payment proofs, estimates fees, sweeps funds, and manages wallet operations via a self-hosted monero-wallet-rpc node. Keywords: monero, xmr, cryptocurrency, payments, wallet, send, receive, payment proof.\"\nlicense: MIT\ncompatibility: \"Requires bash 4+, curl, jq, flock (util-linux), and a running monero-wallet-rpc >= 0.18.0.\"\nmetadata:\n  hermes:\n    category: finance\n    tags: [monero, cryptocurrency, payments, wallet, xmr]\n    related_skills: []\n  version: \"0.2.0\"\n  author: Private Payments\n  permissions:\n    shell_execution: true\n    file_writes:\n      - \".env (chmod 600) — RPC credentials + wallet password\"\n      - \"$MONERO_LOCK_DIR/.netrc (chmod 600) — ephemeral RPC auth\"\n      - \"$MONERO_LOCK_DIR/wallet-rpc.pid — process tracking\"\n      - \"$MONERO_LOCK_DIR/wallet-rpc.port — port tracking\"\n      - \"$MONERO_LOCK_DIR/.last_refresh — refresh timestamp\"\n    process_management: \"starts/stops monero-wallet-rpc as a background process\"\n    network_access: \"HTTP POST to $MONERO_RPC_URL/json_rpc (localhost by default)\"\n    credential_access: \"reads .env for RPC + wallet credentials; writes .netrc for curl auth\"\n---\n\n# Agenta-Monero\n\nShell wrappers over `monero-wallet-rpc` for autonomous Monero (XMR) payments. All scripts emit JSON to stdout (success) or a structured error JSON to stderr; they compose into receive/send/verify/sweep workflows. Money math is integer piconeros internally; XMR decimal strings appear in output.\n\n> **WARNING — IRREVERSIBLE FINANCIAL OPERATIONS**\n>\n> - Monero transactions are **irreversible**. Once broadcast, funds cannot be recovered.\n> - `send_xmr.sh` and `sweep_all.sh` **broadcast by default**. Use `--dry-run` to preview without sending.\n> - `sweep_all.sh` transfers **all unlocked funds** from the wallet (or subaddress) to a single destination. A mistaken or maliciously triggered sweep can drain the entire balance.\n> - Always validate the recipient address (`validate_address.sh`) and confirm the amount before executing a send or sweep.\n> - The `.env` file contains `MONERO_WALLET_PASSWORD` and RPC credentials. It is created with `chmod 600`, but on multi-user systems, shared CI, or agent workspaces with broad read access, an attacker who reads `.env` can access the wallet and move funds. Secure the file and the system accordingly.\n\n**Use when:** generating receive addresses, sending/sweeping XMR, checking balance, verifying an incoming payment or a payment proof, estimating fees, or reconciling transactions by hash.\n\n## Prerequisites\n\n- **Install Monero CLI tools** (≥ 0.18.0): download from https://getmonero.org/downloads/ — you need at minimum `monero-wallet-rpc`. Also create a wallet file: `monero-wallet-cli --generate-new-wallet ~/Monero/wallets/main --password 'PASS'` (write down the 25-word seed).\n- **Bash ≥ 4**, `curl`, `jq`, `flock` (util-linux) — standard on Linux/macOS (`brew install jq` on macOS).\n- **First-time setup:** run `./scripts/interactive_setup.sh` (interactive prompts) **or** tell the Hermes agent \"Set up the Agenta-Monero skill\" (agent-driven; see First-Time Setup below). Both paths generate RPC credentials, write `.env`, start `monero-wallet-rpc`, and verify readiness.\n- After setup, every script runs from the skill root. Invoke `./setup.sh` again after changing `.env`.\n\n## Permissions & Capabilities\n\nThis skill performs the following actions. Operators should review these before approving or invoking the skill in automated workflows:\n\n| Capability | Details |\n|------------|---------|\n| **Shell execution** | Runs `curl`, `jq`, `flock`, `monero-wallet-rpc`, and standard shell utilities |\n| **File writes** | `.env` (chmod 600), `.netrc` (chmod 600, ephemeral), PID/port files, lock files, refresh timestamp |\n| **Process management** | Starts and stops `monero-wallet-rpc` as a background daemon (PID tracked in `$MONERO_LOCK_DIR`) |\n| **Network access** | HTTP POST to `$MONERO_RPC_URL/json_rpc` (localhost by default; can be configured for remote) |\n| **Credential access** | Reads `.env` for RPC user/password and wallet password; writes `.netrc` for curl auth; never emits credentials in stdout |\n\nAll credential files are created with restrictive permissions (`0600` for files, `0700` for the lock directory). The `.env` file is parsed safely (never sourced) and shell metacharacters are rejected.\n\n## First-Time Setup\n\nWhen a user asks to set up the Agenta-Monero skill, follow this workflow.\n\n**Path A — Agent-driven (recommended):**\n1. Ask: \"What's the path to your wallet file?\"\n2. Ask: \"What's the wallet password?\"\n3. Ask: \"Local daemon or remote node?\"\n   - If remote: \"What's the daemon address? (e.g. node.example.com:18081)\"\n4. Check: `command -v monero-wallet-rpc` — if missing, print install guidance (https://getmonero.org/downloads/) and stop.\n5. Run: `./scripts/interactive_setup.sh --wallet-path \"PATH\" --wallet-password \"PASS\" --network mainnet --daemon-type local [--daemon-address \"HOST:PORT\" if remote] --force`\n6. Read the JSON output. If `ready:true` → done. If `ready:false` → check `warnings` and troubleshoot.\n7. To check wallet-rpc status later: `./scripts/wallet_rpc_status.sh`. To stop it: `./scripts/stop_wallet_rpc.sh`.\n\n**Path B — Manual interactive script:**\nTell the user to run `./scripts/interactive_setup.sh` and follow the prompts.\n\n**Both paths:**\n- Generate random RPC credentials (12-char user, 24-char password).\n- Write `.env` (chmod 600) with all values including `MONERO_WALLET_PASSWORD`.\n  - **Caution:** `.env` persists on disk and contains the wallet password. On multi-user systems or CI, ensure the file is not world-readable, not committed to version control, and not included in backups or log captures.\n- Start `monero-wallet-rpc` as a background process (PID stored in `$MONERO_LOCK_DIR/wallet-rpc.pid`).\n- Run `./setup.sh` and report readiness.\n- **Credentials are not emitted in stdout JSON.** They exist only in `.env` (chmod 600). If the user needs to see them, read from `.env` directly.\n\n## Quick reference\n\nOne compact block per operation. **Load `references/rpc-reference.md` when you need exact JSON-RPC params, full output field lists, or per-operation refresh classification.**\n\n```text\ncreate_address.sh  --label \"Payment from Alice\" [--account 0]   -> {address, address_index, account}\nsend_xmr.sh        --address ADDR --amount \"1.5\"                -> {tx_hash, fee, amount[, tx_key]}\n                   [--priority 0] [--get-tx-key] [--dry-run]\n                   [--dest '[{\"address\":\"A\",\"amount\":\"1.0\"}]']\nestimate_fee.sh    --address ADDR --amount \"1.5\" [--priority 0] -> {fee, amount, priority, num_destinations}\nsweep_all.sh       --address ADDR [--account 0] [--subaddress N]-->{tx_hash, fee, amount}\n                   [--priority 0] [--dry-run]\ncheck_balance.sh   [--account 0]                                -> {balance, unlocked_balance, blocks_to_unlock, time_to_unlock, account}\nget_transfer.sh    --tx-hash HASH                               -> {tx_hash, amount, fee, direction, confirmations, address, address_index, timestamp, confirmed, unlock_time}\nverify_payment.sh  --tx-hash HASH | --address ADDR --expected-amount \"1.5\" -> {verified, confirmations, tx_hash, address, address_index, confirmed, amount}\nget_tx_proof.sh    --tx-hash HASH --address ADDR                -> {tx_hash, address, proof}\ncheck_tx_proof.sh  --tx-hash HASH --address ADDR --proof PROOF  -> {verified, confirmations, amount, tx_hash, address}\nlist_incoming.sh   [--confirmed-only|--all] [--since-block N]   -> [{tx_hash, amount, confirmations, address, address_index, timestamp, confirmed, unlock_time}]\n                   [--since-timestamp N] [--limit 100] [--account 0]\nlist_outgoing.sh   [--since-block N] [--since-timestamp N]      -> [{tx_hash, amount, fee, timestamp, address, address_index, unlock_time}]\n                   [--limit 100] [--account 0]\nlist_addresses.sh  [--account 0]                                -> [{index, address, label, balance, unlocked_balance}]\nvalidate_address.sh --address ADDR                              -> {valid, network, network_match, subaddress, integrated}\nsync_status.sh                                                   -> {height, daemon_connected, wallet_version}\n```\n\nConcrete output examples (stdout; success is one JSON object per line):\n\n```json\n// create_address.sh\n{\"address\":\"88bc...\",\"address_index\":5,\"account\":0}\n// send_xmr.sh --address ... --amount \"1.5\"\n{\"tx_hash\":\"7663438...\",\"fee\":\"0.0000869\",\"amount\":\"1.5\"}\n// estimate_fee.sh --address ... --amount \"1.5\"\n{\"fee\":\"0.0000869\",\"amount\":\"1.5\",\"priority\":0,\"num_destinations\":1}\n// sweep_all.sh --address DEST --dry-run\n{\"tx_hash\":\"\",\"fee\":\"0.0000869\",\"amount\":\"8.2\"}\n// check_balance.sh\n{\"balance\":\"10.5\",\"unlocked_balance\":\"8.2\",\"blocks_to_unlock\":42,\"time_to_unlock\":30240,\"account\":0}\n// get_transfer.sh --tx-hash ...\n{\"tx_hash\":\"c36258a...\",\"amount\":\"1.5\",\"fee\":\"0.0000435\",\"direction\":\"in\",\"confirmations\":15,\"address\":\"77Vx9cs...\",\"address_index\":3,\"timestamp\":1535918400,\"confirmed\":true,\"unlock_time\":0}\n// verify_payment.sh --tx-hash ...\n{\"verified\":true,\"confirmations\":12,\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"address_index\":3,\"confirmed\":true,\"amount\":\"1.5\"}\n// get_tx_proof.sh --tx-hash ... --address ...\n{\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"proof\":\"ProofV1...\"}\n// check_tx_proof.sh --tx-hash ... --address ... --proof ...\n{\"verified\":true,\"confirmations\":15,\"amount\":\"1.5\",\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\"}\n// validate_address.sh --address ...\n{\"valid\":true,\"network\":\"mainnet\",\"network_match\":true,\"subaddress\":false,\"integrated\":false}\n// sync_status.sh\n{\"height\":1523651,\"daemon_connected\":true,\"wallet_version\":196613}\n// list_incoming.sh (array element)\n{\"tx_hash\":\"c36258a...\",\"amount\":\"1.5\",\"confirmations\":15,\"address\":\"77Vx9cs...\",\"address_index\":3,\"timestamp\":1535918400,\"confirmed\":true,\"unlock_time\":0}\n```\n\nAmounts in outputs are XMR decimal strings (e.g. `\"1.5\"`). `--dry-run` and `estimate_fee` preview without broadcasting.\n\n## Gotchas (verified facts — get these right)\n\n- **No `sync` RPC.** The wallet refreshes from the daemon via `refresh`, which can take seconds-to-minutes. Refresh is **operation-aware**: balance/transfer/verify ops auto-refresh; address-management, `validate_address`, `estimate_fee`, `get_tx_proof`, and `sync_status` do not. Override with `--no-refresh` on any auto-refresh op (**`--no-refresh` works in any argument position**).\n- **`blocks_to_unlock` / `time_to_unlock` are native `get_balance` fields.** Read them directly — never derive them. `check_balance` surfaces both. They are `0` when no funds are locked, or `null` if the wallet omits them — treat `0`/`null` as \"nothing locked\".\n- **Priority values: `0=default, 1=unimportant, 2=normal, 3=elevated, 4=priority`.** The default is **`0`** (wallet decides). Do **not** default to `1` — that literally means \"unimportant\". Send/sweep/estimate accept `--priority 0-4`.\n- **Single `/json_rpc` endpoint.** Every wallet method this skill uses — including `get_height` and `get_version` — is POSTed to `$MONERO_RPC_URL/json_rpc`. There is no root-path call anywhere.\n- **`validate_address` uses real RPC fields.** The RPC is called with `any_net_type:true` so the real `nettype` is returned; `network_match` is derived client-side by comparing `nettype` to `MONERO_NETWORK`. There is **no `checksum_valid` field** (the checksum is part of `valid`). This keeps `INVALID_ADDRESS` (bad format/checksum) distinct from `NETWORK_MISMATCH` (valid but wrong network).\n- **Money is integer piconeros (1 XMR = 10^12).** Never use floating-point for amounts. All arithmetic is integer piconero; the XMR decimal strings in output come from the scripts' string-based conversion. Amounts must be positive and have <=12 decimals.\n- **Sends and sweeps are not idempotent and are NOT auto-retried.** On timeout/uncertain result, check `get_transfer.sh --tx-hash` **before** retrying (see retry-safety workflow). Use `--dry-run` / `estimate_fee` to preview.\n- **Credentials use netrc (never `curl -u`); `.env` is parsed, never sourced.** The netrc lives at `$MONERO_LOCK_DIR/.netrc` (mode `0600`). All user values are passed to the RPC via `jq --arg`/`--argjson` — never by string interpolation.\n\n## Workflows\n\nWorkflows are rendered as checklists. Money/identity paths (send, sweep, verify) are prescriptive: follow the order. Every destructive workflow ends with a verify-after-act step.\n\n### Receive a Payment\n\n- [ ] `scripts/create_address.sh --label \"Payment from Alice\"` — note the returned `address`.\n- [ ] Share `address` with the payer.\n- [ ] `scripts/check_balance.sh` (or `scripts/list_incoming.sh --since-block <height>`).\n- [ ] `scripts/verify_payment.sh --address \"ADDR\" --expected-amount \"1.5\"` — wait until `verified:true`.\n- [ ] `scripts/get_tx_proof.sh --tx-hash \"HASH\" --address \"ADDR\"` — hand the payer the `proof` for their records.\n\n### Send a Payment (plan -> validate -> execute)\n\n> **Irreversible:** `send_xmr.sh` broadcasts a real transaction by default. Use `--dry-run` to preview. Always validate the address and confirm the amount before executing.\n\n- [ ] **Plan:** `scripts/estimate_fee.sh --address \"RECIPIENT\" --amount \"2.5\"` — preview `fee`.\n- [ ] **Validate:** `scripts/validate_address.sh --address \"RECIPIENT\"` — confirm `valid:true` and `network_match:true`.\n- [ ] **Balance:** `scripts/check_balance.sh` — confirm `unlocked_balance >= 2.5`.\n- [ ] **Preview (optional):** `scripts/send_xmr.sh --address \"RECIPIENT\" --amount \"2.5\" --dry-run` — confirm fee/amount without broadcasting.\n- [ ] **Execute:** `scripts/send_xmr.sh --address \"RECIPIENT\" --amount \"2.5\"` — note the `tx_hash`.\n- [ ] **Verify:** `scripts/get_transfer.sh --tx-hash \"<tx_hash>\"` — confirm it was recorded (and `confirmed` once enough blocks pass).\n\n### Send a Payment — retry safety (DECISION GATE)\n\nSends are not idempotent. **Never retry blindly on timeout.** Run this gate first:\n\n- [ ] Attempt: `scripts/send_xmr.sh --address \"RECIPIENT\" --amount \"2.5\"`.\n- [ ] If it returns a `tx_hash` (success) -> **done; do NOT re-send.**\n- [ ] If it **times out / returns an uncertain result**, whether you can use `get_transfer` depends on having a hash:\n  - **You have a `tx_hash`** (from the send response, or a prior attempt you're unsure about) -> call `scripts/get_transfer.sh --tx-hash \"<tx_hash>\"` and branch on the **error code**:\n    - `TX_NOT_FOUND` -> the transaction is genuinely absent from the wallet -> **safe to retry the send.**\n    - `RPC_UNREACHABLE` -> the wallet RPC / daemon could not be reached -> the transaction status is **unknown**, not absent -> **do NOT retry the send;** fix connectivity (`sync_status.sh`, restart `monero-wallet-rpc`/`monerod`) and re-check `get_transfer` before doing anything else.\n    - any success result -> the tx exists -> **do NOT re-send.**\n  - **You have NO `tx_hash`** (pure transport failure / `RPC_UNREACHABLE` with no payload) -> there is nothing to look up; status is **unknown**. **Do NOT retry the send.** Fix connectivity first, then reconcile with `scripts/list_outgoing.sh` (match by amount/timestamp) to detect any tx that may have been created before re-evaluating.\n\n### Verify a Payment Proof\n\n- [ ] Collect from the payer: `tx_hash`, `address`, and `proof` string.\n- [ ] `scripts/check_tx_proof.sh --tx-hash \"HASH\" --address \"ADDR\" --proof \"PROOF\"`.\n- [ ] Act on `verified`: `true` => proof is cryptographically valid (read `amount`, `confirmations`). `false` / `PROOF_INVALID` => reject and ask the payer to re-issue.\n\n### Sweep Funds (plan -> validate -> execute)\n\n> **Irreversible and high-impact:** `sweep_all.sh` transfers **all unlocked funds** to a single destination by default. A mistaken address or amount can drain the entire wallet. Always use `--dry-run` first and verify the previewed amount.\n\n- [ ] `scripts/check_balance.sh` — read `unlocked_balance` (the sweepable amount).\n- [ ] `scripts/validate_address.sh --address \"DESTINATION\"` — `valid:true` + `network_match:true`.\n- [ ] `scripts/sweep_all.sh --address \"DESTINATION\" --dry-run` — preview `amount` + `fee` without sending.\n- [ ] `scripts/sweep_all.sh --address \"DESTINATION\"` — execute; note `tx_hash`.\n- [ ] (Optional) `scripts/get_transfer.sh --tx-hash \"<tx_hash>\"` — confirm. Same retry-safety caveat as sends applies.\n\n### Check for Payments (with filtering)\n\n- [ ] `scripts/sync_status.sh` — confirm `daemon_connected:true` and that `height` is recent (else data may be stale). `list_incoming` auto-refreshes unless `MONERO_AUTO_REFRESH=false` or you pass `--no-refresh`; if auto-refresh is off and you need fresh data, re-enable it (there is no standalone refresh script).\n- [ ] `scripts/list_incoming.sh --since-block <height> --limit 50` — recent incoming transfers.\n- [ ] Read `confirmations` / `confirmed` per row (threshold = `MONERO_CONFIRMATIONS`, default `10`).\n- [ ] To pin a specific payment: `scripts/verify_payment.sh --tx-hash \"HASH\"` (or `--address` + `--expected-amount`).\n\n## Error codes\n\nEvery error is a JSON object on **stderr** plus a non-zero exit. It is **compact (single-line)** — but always parse it with `jq`, never line-by-line. The object has exactly `error`, `code`, and `message` (the `suggestion` key is reserved in the emitter but not currently populated; use the table below for recovery text):\n\n```json\n{\n  \"error\": true,\n  \"code\": \"TX_NOT_FOUND\",\n  \"message\": \"no transfer found for txid 7663438…\"\n}\n```\n\n**Load `references/error-runbook.md` when a script returns an error code and you need detailed, per-code recovery steps.**\n\n| Code | Meaning | Retryable | One-line recovery |\n|------|---------|:---------:|-------------------|\n| `CONFIG_MISSING` | Required env var / arg not set | No | Run `./setup.sh`; supply the missing `--flag`. |\n| `CONFIG_INVALID` | `.env` has bad syntax/metachars | No | Inspect `.env`; fix malformed lines; do not source it. |\n| `RPC_UNREACHABLE` | Cannot reach monero-wallet-rpc | Yes | Start/check `monero-wallet-rpc`; re-check. (Do NOT treat a send timeout with this code as \"tx absent\".) |\n| `WALLET_NOT_LOADED` | Wallet name != loaded wallet | No | `open_wallet` the right wallet; check `MONERO_WALLET_NAME`. |\n| `WALLET_LOCKED` | Wallet file locked elsewhere | No | Find/kill the holder (`lsof \\| grep wallet.keys`) or wait. |\n| `DAEMON_DISCONNECTED` | Wallet RPC can't reach daemon | Yes | Check/restart `monerod`. |\n| `INSUFFICIENT_BALANCE` | Not enough unlocked funds | No | `check_balance.sh`; wait for unlocks or reduce amount. |\n| `AMOUNT_INVALID` | Amount <=0 / >12 decimals / >balance | No | Correct the amount string. |\n| `INVALID_ADDRESS` | Bad format/checksum | No | Re-check the address; do not use. |\n| `NETWORK_MISMATCH` | Valid address, wrong network | No | Use an address for `MONERO_NETWORK` (mainnet/stagenet). |\n| `INVALID_INPUT` | Bad flag value (e.g. priority 0-4, tx-hash, label) | No | Correct the argument value. |\n| `SYNC_FAILED` / `REFRESH_FAILED` | Wallet sync/refresh failed | Yes | `sync_status.sh`; may need to restart wallet RPC. |\n| `TX_RELAY_FAILED` | Tx created but not broadcast | No | `get_transfer.sh --tx-hash`; may need manual relay. |\n| `RATE_LIMITED` | Lock acquisition timed out / daemon busy | Yes | Wait; reduce call frequency. |\n| `TX_NOT_FOUND` | Hash unknown to this wallet | No | Re-check the hash; for sends this means \"safe to retry\" (see retry-safety). |\n| `PROOF_INVALID` | Payment proof verification failed | No | Reject; ask payer to re-issue proof. |\n\nTransient codes (`RPC_UNREACHABLE`, `DAEMON_DISCONNECTED`, `SYNC_FAILED`, `REFRESH_FAILED`, `RATE_LIMITED`) surface **immediately** — they are **not** auto-retried by the scripts. The retry helper (`lib/retry.sh`) exists and is unit-tested, but is **not** currently applied to any script RPC call (all scripts call `rpc_call` directly). `send_xmr`/`sweep_all` are intentionally never retried (non-idempotent). `get_transfer` and `check_tx_proof` are intentionally direct so they don't mask the retry-safety probe / proof classification. If a read-only op returns a transient code, **the agent should retry it itself** (never retry sends/sweeps — drive those via the decision gate above).\n\n## Refresh & concurrency\n\n- **Refresh:** controlled by `MONERO_AUTO_REFRESH` (default `true`) and `MONERO_REFRESH_MIN_INTERVAL` (default `30`s; a refresh is skipped if one happened within this window). Auto-refreshing ops accept `--no-refresh` to skip. The last-refresh timestamp lives in `$MONERO_LOCK_DIR/.last_refresh`.\n- **Concurrency:** every script takes an exclusive `flock` on `$MONERO_LOCK_DIR/agenta-monero.lock` (timeout `MONERO_LOCK_TIMEOUT`, default `60`s) before any RPC; lock contention surfaces as `RATE_LIMITED`. The lock is released on exit, coordinating multiple local agent processes against the wallet RPC's own serialization.\n\n**Load `references/env-reference.md` when you need the full environment-variable table (connection, network, refresh, retry, concurrency, TLS knobs) or the complete refresh-strategy / retry-backoff details.**\n\nFile v0.1.1:README.md\n\n# Agenta-Monero\n\n> Autonomous Monero (XMR) payments for Hermes and Openclaw agents via shell. JSON-in, JSON-out wrappers over `monero-wallet-rpc` for sending, receiving, verifying, and sweeping. Composable into agent-driven workflows.\n\n> **WARNING — Irreversible Financial Operations**\n>\n> Monero transactions are **irreversible**. `send_xmr.sh` and `sweep_all.sh` broadcast by default — use `--dry-run` to preview. `sweep_all.sh` transfers **all unlocked funds** to one destination; a mistaken or maliciously triggered sweep can drain the entire wallet balance. Always validate addresses and confirm amounts before executing.\n\n## What It Does\n\n| Command | Description |\n|---------|-------------|\n| `create_address.sh` | Generate a receive address with label |\n| `send_xmr.sh` | Send XMR (supports `--dry-run`) |\n| `sweep_all.sh` | Sweep **all** wallet funds to a destination (supports `--dry-run`) |\n| `check_balance.sh` | Check balance + unlock status |\n| `estimate_fee.sh` | Preview fees before sending |\n| `validate_address.sh` | Verify address format and network |\n| `get_transfer.sh` | Look up a transaction by hash |\n| `verify_payment.sh` | Confirm a payment was received |\n| `get_tx_proof.sh` / `check_tx_proof.sh` | Generate or verify payment proofs |\n| `list_incoming.sh` / `list_outgoing.sh` | List transactions with filtering |\n| `list_addresses.sh` | List subaddresses with balances |\n| `sync_status.sh` | Check daemon connection + wallet height |\n| `interactive_setup.sh` | First-time setup wizard |\n| `wallet_rpc_status.sh` / `stop_wallet_rpc.sh` | Manage the RPC daemon |\n\n## Prerequisites\n\n- **OS:** Linux or macOS (Windows not supported)\n- **Monero CLI tools** >= 0.18.0 ([download](https://getmonero.org/downloads/)) - at minimum `monero-wallet-rpc`\n- **Bash** >= 4, `curl`, `jq`, `flock` (util-linux)\n\n## Installation\n\n**Hermes:**\n```bash\ngit clone https://github.com/tibbar-etihw/agenta-monero.git ~/.hermes/skills/finance/agenta-monero\n```\n\n**OpenClaw:**\n```bash\ngit clone https://github.com/tibbar-etihw/agenta-monero.git ~/.openclaw/workspace/skills/finance/agenta-monero\n```\n\nOr tell your agent:\n> \"Install the agenta-monero skill from https://github.com/tibbar-etihw/agenta-monero\"\n\n**New to this?** See the [Getting Started guide](docs/GETTING_STARTED.md) for a detailed walkthrough covering wallet creation, daemon setup, and first-time configuration.\n\n## Configuration\n\nYour agent configures everything. Simply prompt it with:\n\n> \"Set up the Agenta-Monero skill.\"\n\n---\n\n<details>\n<summary>Manual configuration (advanced)</summary>\n\nCopy `.env.example` to `.env` and fill in your values:\n\n```bash\ncp .env.example .env\n```\n\nRequired variables:\n- `MONERO_RPC_URL` - wallet RPC endpoint (default: `http://127.0.0.1:18088`)\n- `MONERO_RPC_USER` / `MONERO_RPC_PASSWORD` - RPC credentials\n- `MONERO_WALLET_NAME` - must match the loaded wallet\n- `MONERO_WALLET_PASSWORD` - wallet password\n- `MONERO_NETWORK` - `mainnet` or `stagenet`\n\n> **Caution:** `.env` contains `MONERO_WALLET_PASSWORD` and RPC credentials. It is created with `chmod 600`, but on multi-user systems, shared CI, or agent workspaces with broad read access, anyone who reads this file can access the wallet and move funds. Do not commit `.env` to version control or include it in backups/log captures.\n\n</details>\n\n## Usage Examples\n\n```bash\n# Create a receive address\n./scripts/create_address.sh --label \"Payment from Alice\"\n\n# Check your balance\n./scripts/check_balance.sh\n\n# Send XMR (dry run first)\n./scripts/send_xmr.sh --address \"RECIPIENT\" --amount \"1.5\" --dry-run\n./scripts/send_xmr.sh --address \"RECIPIENT\" --amount \"1.5\"\n\n# Verify a payment\n./scripts/verify_payment.sh --tx-hash \"HASH\" --expected-amount \"1.5\"\n\n# Estimate fees\n./scripts/estimate_fee.sh --address \"RECIPIENT\" --amount \"1.5\"\n\n# List recent incoming transactions\n./scripts/list_incoming.sh --since-block 1500000 --limit 50\n```\n\n## How It Works\n\nAll scripts communicate with `monero-wallet-rpc` via a single `/json_rpc` endpoint. Credentials are stored in a netrc file (never passed via command line). The `.env` file is parsed safely - never sourced.\n\n- **Auto-refresh**: Balance/transfer/verify operations auto-refresh the wallet. Use `--no-refresh` to skip.\n- **Concurrency**: Scripts use file locking (`flock`) to coordinate multiple processes.\n- **Money math**: All amounts are integer piconeros internally (1 XMR = 10^12). XMR decimal strings appear in output.\n\n## Error Handling\n\nErrors are JSON on stderr with an error code:\n\n```json\n{\"error\":true,\"code\":\"INSUFFICIENT_BALANCE\",\"message\":\"not enough unlocked funds\"}\n```\n\nCommon codes: `CONFIG_MISSING`, `RPC_UNREACHABLE`, `WALLET_NOT_LOADED`, `INSUFFICIENT_BALANCE`, `INVALID_ADDRESS`, `NETWORK_MISMATCH`, `TX_NOT_FOUND`\n\nSee `references/error-runbook.md` for detailed recovery steps.\n\n## Testing\n\nTests use an in-process Python mock RPC server - no daemon or network required.\n\n```bash\nbats tests/                    # Run all tests\nbats tests/send_xmr.bats      # Run single test file\n```\n\nRequires: `bats`, `python3`\n\n## Documentation\n\n- `SKILL.md` - Full agent-facing reference\n- `references/rpc-reference.md` - RPC method details\n- `references/error-runbook.md` - Per-error recovery steps\n- `references/env-reference.md` - Environment variable table\n- `docs/GETTING_STARTED.md` - Install walkthrough\n\n## WARNING\nNever fund your agent's Monero wallet with more than what you are willing to potentially lose. Agents make mistakes and misunderstand instructions all the time.\n\n## License\n\nMIT\n\n## Donations\n\nIf you find this useful, donations are appreciated:\n\n**Monero:**\n```\n82fPMdPyWS5jEvW3TzH8ibWmrj2Uu1hmNNo7n1W2bdyMEGTDEUN6ecXYHjn6TnAxan9N3LhDS678KfzagsVuMYYk3hXZ2gR\n```\n\nFile v0.1.1:_meta.json\n\n{\n  \"ownerId\": \"kn76dhwaqd2zm8bn4qhjp3c7bd8bcppg\",\n  \"slug\": \"agenta-monero\",\n  \"version\": \"0.1.1\",\n  \"publishedAt\": 1785246237330\n}\n\nFile v0.1.1:references/env-reference.md\n\n# Environment Variables\n\nAll configuration is read from `.env` (parsed safely — never sourced) at the skill root. Copy `.env.example` to `.env` and edit; run `./setup.sh` after changing it. Values shown are defaults.\n\n## Connection\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_RPC_URL` | `http://127.0.0.1:18088` | URL of the running `monero-wallet-rpc`. |\n| `MONERO_RPC_USER` | _(empty)_ | RPC authentication username. Written into `$MONERO_LOCK_DIR/.netrc` (mode `0600`). |\n| `MONERO_RPC_PASSWORD` | _(empty)_ | RPC authentication password. Written into `.netrc`; never passed on the command line. |\n| `MONERO_WALLET_NAME` | _(empty)_ | Wallet name; must match the wallet loaded in the RPC server. |\n\n## Network\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_NETWORK` | `mainnet` | `mainnet` \\| `stagenet`. `validate_address` compares each address's `nettype` against this to derive `network_match`. |\n\n## Lifecycle\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_LIFECYCLE` | `none` | `none` = assume the wallet RPC is already running (the supported mode). `full` = the agent is expected to manage daemon + wallet lifecycle (reserved). |\n\n## Remote node (optional)\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_REMOTE_NODE` | _(empty)_ | Remote node hostname/IP, if used. |\n| `MONERO_REMOTE_PORT` | _(empty)_ | Remote node port. |\n\n## Display\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_CONFIRMATIONS` | `10` | Blocks before a payment is considered `confirmed`. Used by `verify_payment`, `get_transfer`, `list_incoming`. |\n| `MONERO_AMOUNT_FORMAT` | `xmr` | `xmr` \\| `piconero`. Output amount rendering (scripts emit XMR decimal strings by default). |\n\n## Refresh\n\nThere is no `sync` RPC; the wallet refreshes from the daemon via `refresh`, which can take seconds-to-minutes. Refresh is **operation-aware** (see `rpc-reference.md` for the per-op table).\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_AUTO_REFRESH` | `true` | `true` = refresh before balance/transfer/verify ops; `false` = never auto-refresh. |\n| `MONERO_REFRESH_MIN_INTERVAL` | `30` | Minimum seconds between refreshes (caching). A refresh is skipped if the last one was more recent than this. Stored in `$MONERO_LOCK_DIR/.last_refresh`. |\n| `MONERO_REFRESH_TIMEOUT` | `120` | Maximum seconds for a single `refresh` operation. |\n\n**Override:** any auto-refreshing script accepts `--no-refresh` (works in **any** argument position) to skip the refresh step — useful for fast read-only checks when you can tolerate slightly stale data.\n\n## Retry\n\nThe retry helper (`lib/retry.sh`) is **available and unit-tested, but NOT currently applied** to any script RPC call — all scripts call `rpc_call` directly. `send_xmr` and `sweep_all` are intentionally never retried (non-idempotent); `get_transfer` and `check_tx_proof` are intentionally direct so retries don't mask the retry-safety probe / proof classification. Transient codes surface immediately; agents should retry read-only ops themselves (never sends/sweeps). The variables below are reserved for future use and have **no effect today**.\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_RETRY_MAX` | `2` | (Reserved, not currently applied.) Maximum retry attempts for transient errors (`RPC_UNREACHABLE`, `DAEMON_DISCONNECTED`, `SYNC_FAILED`, `REFRESH_FAILED`, `RATE_LIMITED`). |\n| `MONERO_RETRY_BACKOFF` | `1` | (Reserved, not currently applied.) Initial backoff in seconds; **doubles per retry** (1, 2, 4, ...). |\n\n## Concurrency\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_LOCK_DIR` | `/tmp/agenta-monero` | Directory for the lock file + netrc. Created with mode `0700`. |\n| `MONERO_LOCK_TIMEOUT` | `60` | Maximum seconds to wait to acquire the `flock`. Contention surfaces as `RATE_LIMITED`. |\n\nEvery script acquires an exclusive `flock` on `$MONERO_LOCK_DIR/agenta-monero.lock` before any RPC, coordinating multiple local agent processes against the wallet RPC's own serialization. The lock is released on exit.\n\n## Advanced\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_RPC_TIMEOUT` | `30` | curl timeout in seconds for individual RPC calls. |\n| `MONERO_RPC_SSL_CACERT` | _(empty)_ | Path to a CA cert for self-signed TLS. |\n| `MONERO_RPC_SSL_CAPATH` | _(empty)_ | Path to a CA cert directory. |\n\n`setup.sh` warns if `MONERO_RPC_URL` uses `http://` for a non-localhost host.\n\nFile v0.1.1:references/error-runbook.md\n\n# Error Recovery Runbook\n\nFull recovery procedures for every error code emitted by Agenta-Monero scripts. Every error is emitted to **stderr** as a single-line (compact) JSON object and the script exits non-zero — parse it with `jq`, not line-by-line:\n\n```json\n{\n  \"error\": true,\n  \"code\": \"WALLET_NOT_LOADED\",\n  \"message\": \"Wallet 'my_wallet' is not loaded in the RPC server\"\n}\n```\n\nParse `code` to branch; read `message` for specifics. (The `suggestion` key is reserved in the emitter but not currently populated — use the Recovery column below for guidance.)\n\n## Error codes (full table)\n\n| Code | Meaning | Retryable | Recovery |\n|------|---------|:---------:|----------|\n| `CONFIG_MISSING` | Required env var not set, or a required `--flag` omitted | No | Run `./setup.sh` to create `.env`, fill required values. For missing flags, supply the required argument (`--address`, `--amount`, `--tx-hash`, `--proof`, etc.). |\n| `CONFIG_INVALID` | `.env` contains invalid syntax or shell metacharacters | No | Inspect `.env` for metacharacters or malformed lines; fix and retry. Never `source .env` — it is parsed safely by design. |\n| `RPC_UNREACHABLE` | Cannot connect to `monero-wallet-rpc` | Yes | Confirm `monero-wallet-rpc` is running and `MONERO_RPC_URL` is correct; start it if not. **For a send/sweep timeout, this code means the transaction status is UNKNOWN — do NOT treat it as \"absent\" and do NOT retry the send;** fix connectivity and re-check with `get_transfer.sh --tx-hash`. |\n| `WALLET_NOT_LOADED` | Wallet name doesn't match the loaded wallet | No | Open the correct wallet in the RPC server (`open_wallet`); verify `MONERO_WALLET_NAME`. |\n| `WALLET_LOCKED` | Wallet file locked by another process | No | Find the holder (`lsof | grep wallet.keys`); kill it or wait for release. |\n| `DAEMON_DISCONNECTED` | Wallet RPC can't reach the daemon | Yes | Check daemon status; restart `monerod` if needed. |\n| `INSUFFICIENT_BALANCE` | Not enough unlocked funds | No | `check_balance.sh` to see available funds; wait for unlocks or reduce the amount. |\n| `AMOUNT_INVALID` | Amount negative, too many decimals (>12), or exceeds balance | No | Correct the amount string (positive decimal, <=12 fractional digits). |\n| `INVALID_ADDRESS` | Address format/checksum invalid | No | Re-check the address; do not use it. |\n| `NETWORK_MISMATCH` | Address valid but on the wrong network | No | Use an address for the configured `MONERO_NETWORK` (mainnet/stagenet). |\n| `INVALID_INPUT` | Bad argument value (priority not 0-4, tx-hash not 64 lowercase hex, label too long/has control chars, `--dest` not a JSON array) | No | Correct the argument value. |\n| `SYNC_FAILED` | Wallet sync failed | Yes | Run `sync_status.sh` to diagnose; may need to restart wallet RPC. |\n| `REFRESH_FAILED` | Wallet refresh failed | Yes | Run `sync_status.sh`; may need to restart wallet RPC; pass `--no-refresh` to bypass on auto-refreshing ops if you can tolerate stale data. |\n| `TX_RELAY_FAILED` | Transaction created but relay failed | No | `get_transfer.sh --tx-hash` to check state; the tx may need manual relay. |\n| `RATE_LIMITED` | Too many requests / lock acquisition timeout | Yes | Wait and retry; reduce call frequency. |\n| `TX_NOT_FOUND` | Transaction hash not found in wallet | No | Re-check the hash. **For a send-timeout retry-safety check, this specifically means the tx is genuinely absent -> safe to retry the send.** |\n| `PROOF_INVALID` | Payment proof verification failed | No | Reject the proof; ask the payer to re-issue with `get_tx_proof.sh`. |\n\nAdditional codes that may surface from RPC plumbing: `DEST_JSON_INVALID` (`--dest` is not a valid JSON array of `{address,amount}`) and `RPC_ERROR` (generic wallet-side RPC error not matching a specific code).\n\n## Edge cases\n\n- **Wallet RPC not running:** `rpc_check_connection` fails fast with `RPC_UNREACHABLE`.\n- **Wallet file locked:** detected via RPC error message; mapped to `WALLET_LOCKED`.\n- **Wrong network:** `validate_address` returns `network_match=false` -> `NETWORK_MISMATCH` (distinct from a malformed address -> `INVALID_ADDRESS`).\n- **Zero balance:** `check_balance` returns `0.0` values gracefully.\n- **No transactions:** `list_incoming`/`list_outgoing` return `[]`.\n- **Partial sync:** `sync_status` reports only wallet `height` + `daemon_connected` (`true` iff the wallet RPC responded to both probes). It deliberately does **not** claim synced/not-synced — the wallet RPC cannot honestly report the daemon's sync target — so it never gives false confidence. For daemon sync progress, query `monerod` directly.\n- **Timeout:** curl timeout `30`s default (`MONERO_RPC_TIMEOUT`); refresh timeout `120`s (`MONERO_REFRESH_TIMEOUT`).\n- **Large amount precision:** all internal arithmetic is integer piconeros; XMR decimal conversion is string-based, never floating-point.\n- **Concurrent access:** scripts take an exclusive `flock` on `$MONERO_LOCK_DIR/agenta-monero.lock` (timeout `MONERO_LOCK_TIMEOUT`); lock contention surfaces as `RATE_LIMITED`.\n\n## Retry logic (available, but NOT currently applied)\n\nThe retry helper (`lib/retry.sh`) is **available and unit-tested, but is NOT currently applied to script RPC calls** — all scripts call `rpc_call` directly.\n\n- `MONERO_RETRY_MAX` (default `2`) — maximum retry attempts for transient errors.\n- `MONERO_RETRY_BACKOFF` (default `1`) — initial backoff in seconds; **doubles per retry** (1, 2, 4, ...).\n\nThese variables are reserved for future use and have **no effect today**. `is_retryable` classifies the transient codes above (`RPC_UNREACHABLE`, `DAEMON_DISCONNECTED`, `SYNC_FAILED`, `REFRESH_FAILED`, `RATE_LIMITED`), but no script routes its calls through `retry_with_backoff`. Transient codes therefore surface **immediately**.\n\nThis is intentional for the destructive paths: **`send_xmr` and `sweep_all` must never be auto-retried** (non-idempotent — an automatic retry could double-spend). Drive their retry manually via the retry-safety decision gate in SKILL.md (timeout -> `get_transfer.sh --tx-hash` -> retry only on `TX_NOT_FOUND`; never on `RPC_UNREACHABLE`). `get_transfer` and `check_tx_proof` are also intentionally direct so that an automatic retry would not mask the retry-safety probe or proof classification. For read-only ops that surface a transient code, **the agent should retry them itself**.\n\n## Send retry-safety decision gate (recap)\n\n```text\nsend_xmr timed out / uncertain\n        |\n        v\nDo you have a tx_hash?\n        |\n        +-- NO (pure transport failure / RPC_UNREACHABLE, no payload)\n        |       -> status UNKNOWN: do NOT retry; fix connectivity, then\n        |          reconcile via list_outgoing.sh (match amount/timestamp)\n        |\n        +-- YES -> get_transfer.sh --tx-hash <hash>\n                |\n                +-- success (tx present)         -> DONE  (do NOT re-send)\n                +-- code == TX_NOT_FOUND         -> SAFE to retry the send\n                +-- code == RPC_UNREACHABLE      -> STOP: status UNKNOWN, fix connectivity, re-check\n                +-- (any other code)             -> STOP: diagnose before acting\n```\n\nThe asymmetry is deliberate: `TX_NOT_FOUND` is a wallet-side \"this hash is not here\" answer; `RPC_UNREACHABLE` means \"I could not ask the wallet at all\". Treating the latter as \"absent\" risks a double-spend.\n\nFile v0.1.1:references/rpc-reference.md\n\n# RPC Reference\n\nFull detail for every operation: exact flags, the underlying JSON-RPC `method` + `params`, the complete output object, behavior notes, and whether the script auto-refreshes. All RPC methods are POSTed to `$MONERO_RPC_URL/json_rpc` as `{\"jsonrpc\":\"2.0\",\"id\":\"...\",\"method\":\"<m>\",\"params\":{...}}` with netrc auth. Amounts inside `params` are integer **piconeros** (1 XMR = 10^12); amounts in script output are XMR decimal strings.\n\n## Refresh classification\n\n| Script | Auto-refresh? | Why |\n|--------|:-------------:|-----|\n| `create_address` | No | Address creation does not depend on chain state. |\n| `send_xmr` | Yes | Needs current balance to validate sufficiency. |\n| `estimate_fee` | No | Fee uses current mempool, not a full refresh. |\n| `sweep_all` | Yes | Needs current balance to know the sweepable amount. |\n| `check_balance` | Yes | Balance depends on chain state. |\n| `list_incoming` | Yes | Transfer list depends on chain state. |\n| `list_outgoing` | Yes | Transfer list depends on chain state. |\n| `verify_payment` | Yes | Confirmation count depends on chain state. |\n| `get_transfer` | Yes | Transfer details depend on chain state. |\n| `get_tx_proof` | No | Proof generation does not depend on chain state. |\n| `check_tx_proof` | Yes | Confirmation count in proof depends on chain state. |\n| `list_addresses` | No | Address listing does not depend on chain state (uses `get_address`, not `get_balance`). |\n| `validate_address` | No | Validation is purely format/checksum/network. |\n| `sync_status` | No | This *is* the status check (point-in-time). |\n\nEvery auto-refreshing script accepts `--no-refresh` (works in any argument position).\n\n---\n\n## create_address.sh\n\n**Flags:** `--label \"optional label\"` (optional), `--account N` (optional, default `0`).\n\n**RPC:** `create_address`\n```json\n{\"method\":\"create_address\",\"params\":{\"account_index\":0,\"label\":\"Payment from Alice\"}}\n```\n\n**Output:**\n```json\n{\"address\":\"88bc...\",\"address_index\":5,\"account\":0}\n```\nValidates label length (<=255 chars, no control characters). Does not auto-refresh.\n\n## send_xmr.sh\n\n**Flags:**\n- Single destination: `--address \"ADDR\" --amount \"1.5\"` (required unless `--dest`).\n- Multi-destination: `--dest '[{\"address\":\"ADDR1\",\"amount\":\"1.0\"},{\"address\":\"ADDR2\",\"amount\":\"2.0\"}]'` (valid JSON array — bare comma-separated streams are rejected).\n- `--priority 0` (default `0`; range 0-4 where **0=default, 1=unimportant, 2=normal, 3=elevated, 4=priority**).\n- `--get-tx-key` (return the transaction key; if omitted, `get_tx_key:false`).\n- `--dry-run` (calls `transfer` with `do_not_relay:true`; returns fee + tx hash without broadcasting).\n\n**RPC:** `transfer`\n```json\n{\"method\":\"transfer\",\"params\":{\"destinations\":[{\"address\":\"ADDR\",\"amount\":1500000000000}],\"priority\":0,\"get_tx_key\":true,\"do_not_relay\":false}}\n```\n(`amount` is piconeros.)\n\n**Output:**\n```json\n{\"tx_hash\":\"7663438...\",\"fee\":\"0.0000869\",\"amount\":\"1.5\",\"tx_key\":\"...\"}\n```\n`tx_key` is present only when `--get-tx-key` is supplied.\n\n**Behavior:** validates each destination via `validate_address` (one RPC per destination — not parallelized); validates amounts (positive, <=12 decimals); pre-checks balance via `get_balance`; converts to piconeros; calls `transfer`. **Not idempotent / not auto-retried.** On timeout, use `get_transfer.sh --tx-hash` before retrying (see SKILL.md retry-safety).\n\n## estimate_fee.sh\n\n**Flags:** same as `send_xmr.sh` (`--address`/`--amount` or `--dest`, `--priority`). Does **not** accept `--get-tx-key` or `--dry-run` (it is always a dry run).\n\n**RPC:** `transfer` with `do_not_relay:true`, `get_tx_key:false`.\n```json\n{\"method\":\"transfer\",\"params\":{\"destinations\":[{\"address\":\"ADDR\",\"amount\":1500000000000}],\"priority\":0,\"get_tx_key\":false,\"do_not_relay\":true}}\n```\n\n**Output:**\n```json\n{\"fee\":\"0.0000869\",\"amount\":\"1.5\",\"priority\":0,\"num_destinations\":1}\n```\nDoes not broadcast, does not auto-refresh. Validates addresses/amounts identically to `send_xmr`.\n\n## sweep_all.sh\n\n**Flags:** `--address \"ADDR\"` (required), `--account N` (optional, default `0`), `--subaddress N` (optional — sweep one subaddress; omit for all), `--priority 0` (optional, default `0`), `--dry-run` (optional).\n\n**RPC:** `sweep_all`\n```json\n{\"method\":\"sweep_all\",\"params\":{\"address\":\"ADDR\",\"account_index\":0,\"priority\":0,\"do_not_relay\":false}}\n```\nWith `--subaddress N`, `params` additionally includes `\"subaddr_indices\":[N]`.\n\n**Output:**\n```json\n{\"tx_hash\":\"7663438...\",\"fee\":\"0.0000869\",\"amount\":\"8.2\"}\n```\nValidates the destination address before sweeping. **Same non-idempotency caveat as `send_xmr`** — not auto-retried.\n\n## check_balance.sh\n\n**Flags:** `--account N` (optional, default `0`).\n\n**RPC:** `refresh` (if auto-refresh enabled and interval elapsed), then `get_balance`:\n```json\n{\"method\":\"get_balance\",\"params\":{\"account_index\":0}}\n```\n\n**Output:**\n```json\n{\"balance\":\"10.5\",\"unlocked_balance\":\"8.2\",\"blocks_to_unlock\":42,\"time_to_unlock\":30240,\"account\":0}\n```\n`blocks_to_unlock` and `time_to_unlock` are **read directly from the native `get_balance` response** (the wallet RPC computes them — no client-side derivation).\n\n## get_transfer.sh\n\n**Flags:** `--tx-hash \"HASH\"` (required; 64 lowercase hex chars).\n\n**RPC:** `refresh` (if enabled), then `get_transfer_by_txid`:\n```json\n{\"method\":\"get_transfer_by_txid\",\"params\":{\"txid\":\"c36258a...\"}}\n```\n\n**Output:**\n```json\n{\"tx_hash\":\"c36258a...\",\"amount\":\"1.5\",\"fee\":\"0.0000435\",\"direction\":\"in\",\"confirmations\":15,\"address\":\"77Vx9cs...\",\"address_index\":3,\"timestamp\":1535918400,\"confirmed\":true,\"unlock_time\":0}\n```\n`direction` is the wallet's transfer `type` (`in`/`out`/`pool`/`pending`). `confirmed` is `confirmations >= MONERO_CONFIRMATIONS`.\n\n**Failure modes (critical for send retry-safety):**\n- `TX_NOT_FOUND` — hash is genuinely absent from the wallet (wallet-side error or empty result). For a send-timeout check, this means \"safe to retry\".\n- `RPC_UNREACHABLE` — transport/daemon down (could not check). The transaction status is **unknown**, not absent. Propagated verbatim; **do not** treat as a \"safe to retry\" signal.\n\n## verify_payment.sh\n\n**Flags:** either `--tx-hash \"HASH\"`, **or** `--address \"ADDR\" --expected-amount \"1.5\"` (mutually exclusive).\n\n**RPC:**\n- tx-hash mode: `get_transfer_by_txid` `{\"txid\":\"HASH\"}`.\n- address mode: `get_transfers` `{\"in\":true,\"out\":false,\"pool\":true,\"pending\":true}`, then client-side match on `address` + exact piconero `amount`.\n\n**Output:**\n```json\n{\"verified\":true,\"confirmations\":12,\"amount\":\"1.5\",\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"address_index\":3,\"confirmed\":true}\n```\n`verified:true` requires the transfer to be incoming **and** at/above `MONERO_CONFIRMATIONS`. `amount` is `null` when no match is found (and `verified:false`).\n\n## get_tx_proof.sh\n\n**Flags:** `--tx-hash \"HASH\"` `--address \"ADDR\"` (both required).\n\n**RPC:** `get_tx_proof`\n```json\n{\"method\":\"get_tx_proof\",\"params\":{\"txid\":\"c36258a...\",\"address\":\"77Vx9cs...\"}}\n```\n\n**Output:**\n```json\n{\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"proof\":\"ProofV1...\"}\n```\nGenerates a proof shareable with a third party. Does not auto-refresh.\n\n## check_tx_proof.sh\n\n**Flags:** `--tx-hash \"HASH\"` `--address \"ADDR\"` `--proof \"PROOF\"` (all required).\n\n**RPC:** `check_tx_proof`\n```json\n{\"method\":\"check_tx_proof\",\"params\":{\"txid\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"signature\":\"ProofV1...\"}}\n```\n(`proof` maps to the RPC's `signature` param.)\n\n**Output:**\n```json\n{\"verified\":true,\"confirmations\":15,\"amount\":\"1.5\",\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\"}\n```\nOn failure (wallet rejects the proof, `good=false`, or RPC error other than `RPC_UNREACHABLE`) returns `PROOF_INVALID`. `RPC_UNREACHABLE` is surfaced as-is (connectivity failure, not an invalid proof).\n\n## list_incoming.sh\n\n**Flags:**\n- (default): confirmed + unconfirmed.\n- `--all`: explicit alias for default.\n- `--confirmed-only`: only `confirmations >= MONERO_CONFIRMATIONS` (takes precedence over `--all` if both given).\n- `--since-block N`, `--since-timestamp N`, `--limit N` (default `100`), `--account N` (default `0`).\n\n**RPC:** `refresh` (if enabled), then `get_transfers`:\n```json\n{\"method\":\"get_transfers\",\"params\":{\"in\":true,\"out\":false,\"pool\":true,\"pending\":true,\"filter_by_height\":true,\"min_height\":1523000,\"account_index\":0}}\n```\n\n**Output** (array; empty `[]` when none):\n```json\n[{\"tx_hash\":\"c36258a...\",\"amount\":\"1.5\",\"confirmations\":15,\"address\":\"77Vx9cs...\",\"address_index\":3,\"timestamp\":1535918400,\"confirmed\":true,\"unlock_time\":0}]\n```\n\n## list_outgoing.sh\n\n**Flags:** `--since-block N`, `--since-timestamp N`, `--limit N` (default `100`), `--account N` (default `0`).\n\n**RPC:** `refresh` (if enabled), then `get_transfers` with `out:true` (and `in:false`).\n\n**Output** (array; empty `[]` when none):\n```json\n[{\"tx_hash\":\"a1b2c3...\",\"amount\":\"0.5\",\"fee\":\"0.0000435\",\"timestamp\":1535918500,\"address\":\"77Vx9cs...\",\"address_index\":3,\"unlock_time\":0}]\n```\n\n## list_addresses.sh\n\n**Flags:** `--account N` (optional, default `0`).\n\n**RPC:** `get_address` `{\"account_index\":0}` (uses `get_address`, not `get_balance`'s `per_subaddress`, because the latter only lists addresses with activity).\n\n**Output** (array):\n```json\n[{\"index\":0,\"address\":\"55LTR8...\",\"label\":\"Primary account\",\"balance\":\"0.5\",\"unlocked_balance\":\"0.5\"}]\n```\nDoes not auto-refresh.\n\n## validate_address.sh\n\n**Flags:** `--address \"ADDR\"` (required).\n\n**RPC:** `validate_address` **with `any_net_type:true`** so the real `nettype` is returned:\n```json\n{\"method\":\"validate_address\",\"params\":{\"address\":\"ADDR\",\"any_net_type\":true,\"allow_openalias\":false}}\n```\nRPC returns `valid`, `nettype`, `subaddress`, `integrated`, `openalias_address`.\n\n**Output:**\n```json\n{\"valid\":true,\"network\":\"mainnet\",\"network_match\":true,\"subaddress\":false,\"integrated\":false}\n```\n`network`/`network_match` are derived client-side: `network` is the RPC's `nettype`; `network_match` is `nettype == MONERO_NETWORK`. There is **no `checksum_valid` field** — the checksum is part of `valid`. This keeps `INVALID_ADDRESS` (`valid=false`) distinct from `NETWORK_MISMATCH` (`valid=true`, `network_match=false`). Does not auto-refresh.\n\n## sync_status.sh\n\n**Flags:** none.\n\n**RPC:** `get_height` and `get_version`, both via `/json_rpc`.\n\n**Output:**\n```json\n{\"height\":1523651,\"daemon_connected\":true,\"wallet_version\":196613}\n```\n`daemon_connected` is a **real reachability proxy**: `true` iff both `get_height` and `get_version` succeeded (if either fails the script exits `RPC_UNREACHABLE`). `wallet_version` is the raw integer from `get_version` (a packed integer such as `196613`, **not** a dotted string). The wallet RPC cannot honestly report the daemon's `target_height` or sync progress, so `synced`/`target_height` are intentionally **not** emitted (a prior version reported an always-true `synced`, which gave false confidence). Point-in-time; does not auto-refresh (it is the status check itself).\n\nFile v0.1.1:docs/GETTING_STARTED.md\n\n# Getting Started with Agenta-Monero\n\nA guide for **new users** to install the Agenta-Monero skill and connect it to Monero (local node or remote node).\n\n---\n\n## How this skill fits together (read this first)\n\n```\n┌─────────────┐    JSON-RPC     ┌────────────────────┐    P2P     ┌──────────────┐\n│   Agent     │ ─────────────▶ │ monero-wallet-rpc  │ ─────────▶ │   monerod    │\n│  + skill    │   127.0.0.1    │  (you run this)    │            │ (the daemon) │\n└─────────────┘    :18088       └────────────────────┘            └──────────────┘\n                     ▲                                                     ▲\n                     │                                                     │\n              the skill talks                                        can be LOCAL\n              to THIS (the wallet                  (you run `monerod`)  ── or REMOTE ──\n              RPC, always on your                                       (a public node)\n              machine)\n```\n\n---\n\n## Quick Start — Choose Your Path\n\n### Path 1: Agent-Driven (recommended)\n\nTell your Hermes agent: **\"Set up Monero payments.\"** The agent will:\n1. Ask for your wallet file path and password.\n2. Ask: local daemon or remote node?\n3. Generate secure credentials, write `.env`, start `monero-wallet-rpc`, and verify readiness.\n\nThe agent passes flags: `--wallet-path`, `--wallet-password`, `--network`, `--daemon-type`, `--force`\n\n**Prerequisites:** `monero-wallet-rpc` installed + a wallet file created.\n- Download Monero CLI tools: https://getmonero.org/downloads/\n- Create a wallet: `monero-wallet-cli --generate-new-wallet ~/Monero/wallets/main --password 'PASS'`\n- (Stagenet for testing: add `--stagenet`, use https://stagenet-faucet.xmr-tw.org/ for free funds)\n\n### Path 2: Interactive Script\n\n```bash\n./scripts/interactive_setup.sh\n```\nFollow the prompts — it does the same as Path 1 but you drive it yourself.\n\n### Path 3: Step-by-Step (Advanced)\n\nSee the detailed walkthrough below. Use this if you want full control over each component.\n\n---\n\nTwo things to understand:\n\n1. **The skill always talks to `monero-wallet-rpc` on your own machine** (`http://127.0.0.1:18088`). You run `monero-wallet-rpc`; it holds your wallet file and keys.\n2. **`monero-wallet-rpc` talks to a `monerod` daemon**, which can be:\n   - **Local** — you run `monerod` yourself (full node, best privacy, slow first sync), or\n   - **Remote** — a public node (fast setup, lighter). Use `--untrusted-daemon` for privacy.\n\nSo \"**connect to a remote node**\" means telling your *wallet-rpc* to use a remote daemon — **not** pointing the skill at a remote server. The skill's `MONERO_RPC_URL` stays `http://127.0.0.1:18088`.\n\n> **First time? Use stagenet** (`--stagenet`, ports `38xxx`). Mainnet syncs for hours–days and real funds are at risk. See the stagenet path below.\n\n---\n\n## Prerequisites\n\n- **OS:** Linux or macOS (Windows not supported)\n- **Monero CLI tools** (`monerod`, `monero-wallet-cli`, `monero-wallet-rpc`) ≥ **0.18.0** — from https://getmonero.org/downloads/ or your package manager.\n- **Bash ≥ 4**, `curl`, `jq`, `flock` (util-linux) — standard on Linux/macOS (`brew install jq` on macOS).\n- **Agent:** Hermes or OpenClaw installed.\n\nCheck:\n```bash\nmonero-wallet-rpc --version\nbash --version | head -1\ncommand -v curl jq flock\n```\n\n---\n\n## Step 1 — Create a wallet (once)\n\nCreate a wallet file with `monero-wallet-cli`. **Write down the 25-word seed** it shows — that's the only way to recover funds.\n\n**Mainnet:**\n```bash\nmkdir -p ~/Monero/wallets\nmonero-wallet-cli --generate-new-wallet ~/Monero/wallets/main --password 'WALLET_PASS'\n# ... note the seed mnemonic, then type `exit`\n```\n\n**Stagenet (recommended for testing):**\n```bash\nmkdir -p ~/Monero/stagenet\nmonero-wallet-cli --stagenet --generate-new-wallet ~/Monero/stagenet/wallet --password 'WALLET_PASS'\n```\n\n> Fund a stagenet wallet free at https://stagenet-faucet.xmr-tw.org/ (or search \"monero stagenet faucet\").\n\n---\n\n## Step 2 — Start the daemon (choose local OR remote)\n\n### Option A — Local node (full node, best privacy)\n\n**Mainnet** (sync takes a long time the first run):\n```bash\nmonerod --detach              # or run in a foreground terminal\n```\n**Stagenet:**\n```bash\nmonerod --stagenet --detach\n```\nDaemon RPC ports: **mainnet `18081`**, **stagenet `38081`**. Check progress: `monerod -- status` or `tail -f ~/.bitmonero/bitmonero.log`.\n\n### Option B — Remote node (fast, no local sync)\n\nSkip running `monerod`; instead point `monero-wallet-rpc` at a public node in Step 3 with `--daemon-address <host>:<port> --untrusted-daemon`. Public nodes: https://monero.fail/ (pick one on your network — mainnet `:18081`, stagenet `:38081`).\n\n> **Privacy:** always use `--untrusted-daemon` with a remote node so your wallet doesn't reveal more than necessary to a third party.\n\n---\n\n## Step 3 — Start `monero-wallet-rpc` (the thing the skill talks to)\n\nRun this in its own terminal (or `--detach`). It loads your wallet and listens on `127.0.0.1:18088`.\n\n**Mainnet + LOCAL daemon:**\n```bash\nmonero-wallet-rpc \\\n  --wallet-file ~/Monero/wallets/main --password 'WALLET_PASS' \\\n  --rpc-bind-port 18088 --rpc-login username:password \\\n  --daemon-address 127.0.0.1:18081 --trusted-daemon\n```\n\n**Mainnet + REMOTE daemon (no local `monerod`):**\n```bash\nmonero-wallet-rpc \\\n  --wallet-file ~/Monero/wallets/main --password 'WALLET_PASS' \\\n  --rpc-bind-port 18088 --rpc-login username:password \\\n  --daemon-address node.example.com:18081 --untrusted-daemon\n```\n\n**Stagenet + LOCAL daemon (recommended for first run):**\n```bash\nmonero-wallet-rpc --stagenet \\\n  --wallet-file ~/Monero/stagenet/wallet --password 'WALLET_PASS' \\\n  --rpc-bind-port 38088 --rpc-login username:password \\\n  --daemon-address 127.0.0.1:38081 --trusted-daemon\n```\n\nNotes:\n- `--rpc-login username:password` — choose your own username and a strong password; the skill authenticates with these (via a netrc file, never on the command line).\n- `--rpc-bind-ip 127.0.0.1` is the default (loopback only). Do **not** expose the wallet RPC to the network without TLS + auth.\n- **Remote wallet-RPC** (uncommon — wallet-rpc on another server): add `--rpc-ssl enabled --rpc-ssl-autodetect`, bind to `0.0.0.0`, and set the skill's `MONERO_RPC_URL=https://server:port` plus `MONERO_RPC_SSL_CACERT` if self-signed.\n\nLeave it running, then verify it responds:\n```bash\ncurl -u username:password --digest \\\n  -X POST http://127.0.0.1:18088/json_rpc \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"method\":\"get_height\"}' -H 'Content-Type: application/json'\n```\n\n---\n\n## Step 4 — Install the skill (manual copy — recommended)\n\n**Do I tell the agent to install it?** No. Hermes and OpenClaw **auto-discover** any skill directory containing a `SKILL.md` under their skills folder. So you place the skill there yourself; the agent picks it up automatically.\n\n**Why manual copy (not `hermes skills install`)?** `hermes skills install <url>` is for skills published to a hub/URL and pulls only `SKILL.md` + detected references. This skill is **script-heavy** (`scripts/*.sh`, `lib/*.sh`); a manual copy guarantees every file lands in place.\n\n**Hermes:**\n```bash\nmkdir -p ~/.hermes/skills/finance\ncp -r agenta-monero ~/.hermes/skills/finance/agenta-monero\ncd ~/.hermes/skills/finance/agenta-monero\n```\n\n**OpenClaw:**\n```bash\nmkdir -p ~/.openclaw/workspace/skills/finance\ncp -r agenta-monero ~/.openclaw/workspace/skills/finance/agenta-monero\ncd ~/.openclaw/workspace/skills/finance/agenta-monero\n```\n\n(If you've published the skill to a GitHub repo and prefer the CLI: `hermes skills install https://your-repo/SKILL.md` — but verify `scripts/` and `lib/` came along afterwards.)\n\n---\n\n## Step 5 — Configure `.env`\n\n```bash\n# Hermes:\ncd ~/.hermes/skills/finance/agenta-monero\n\n# OpenClaw:\ncd ~/.openclaw/workspace/skills/finance/agenta-monero\n\ncp .env.example .env\nchmod 600 .env\n```\n\nEdit `.env` — set at least these:\n```bash\nMONERO_RPC_URL=\"http://127.0.0.1:18088\"   # 127.0.0.1:38088 for stagenet\nMONERO_RPC_USER=\"username\"               # same as --rpc-login username from Step 3\nMONERO_RPC_PASSWORD=\"password\"            # same as --rpc-login password from Step 3\nMONERO_NETWORK=\"mainnet\"                  # mainnet | stagenet\n```\nLeave the rest at defaults. Keep `.env` out of version control (the skill's `.gitignore` already excludes it).\n\n---\n\n## Step 6 — Run `setup.sh` (readiness check)\n\n```bash\n./setup.sh\n```\nExpect:\n```json\n{\"ready\":true,\"deps_ok\":true,\"config_ok\":true,\"connection_ok\":true,\"wallet_loaded\":true,\"version\":196613,\"warnings\":[]}\n```\n- `ready:true` → you're set.\n- `connection_ok:false` → wallet-rpc isn't running / wrong port or creds (see Troubleshooting).\n- `wallet_loaded:false` → wallet-rpc is up but no wallet is loaded. Fix by starting wallet-rpc with `--wallet-file` (Step 3), then re-run `setup.sh`.\n\n---\n\n## Step 7 — Use it\n\nYou can now either **ask the Hermes agent** in plain language, or **run scripts directly**.\n\nAsk the agent, e.g.:\n> \"Generate a Monero subaddress labelled 'invoice 42'.\"\n> \"Send 1.5 XMR to 88bc…, dry-run first to preview the fee.\"\n> \"Check my balance and how many blocks are locked.\"\n\nOr run a script directly (from the skill directory):\n```bash\n./scripts/sync_status.sh\n./scripts/create_address.sh --label \"invoice 42\"\n./scripts/estimate_fee.sh --address 88bc… --amount 1.5\n./scripts/send_xmr.sh --address 88bc… --amount 1.5 --dry-run    # preview, no broadcast\n./scripts/send_xmr.sh --address 88bc… --amount 1.5              # actually send\n./scripts/get_transfer.sh --tx-hash <hash>                      # confirm it landed\n./scripts/check_balance.sh\n```\n\nEvery script prints JSON on stdout and structured errors on stderr. Full per-operation details: see `SKILL.md` and `references/`.\n\n---\n\n## Troubleshooting\n\n| Symptom | Likely cause / fix |\n|---|---|\n| `RPC_UNREACHABLE` | wallet-rpc not running, wrong `MONERO_RPC_URL` port, or wrong `--rpc-login` creds. Re-run the curl check in Step 3. |\n| `connection_ok:false` from setup | same as above. |\n| `wallet_loaded:false` | wallet-rpc is up but no wallet open — start it with `--wallet-file … --password …`. |\n| `CONFIG_INVALID` on `.env` | a line has shell metacharacters (`$ \\` ( ) { } ; | & < >`) — the parser rejects them on purpose; simplify the value. |\n| Send times out / unsure if it sent | **do not just retry.** Run `./scripts/get_transfer.sh --tx-hash <hash>`. `TX_NOT_FOUND` → safe to retry. `RPC_UNREACHABLE` → status unknown, fix connectivity first, do **not** retry. |\n| Huge `daemon_connected`/stale balance | wallet isn't synced. Let `monerod` finish syncing (or wait for `monero-wallet-rpc` to refresh). |\n| Remote node rejected / slow | pick a different node from https://monero.fail/; keep `--untrusted-daemon`. |\n\nMore: `references/error-runbook.md`.\n\n---\n\n## Lifecycle Management\n\nAfter setup, `monero-wallet-rpc` runs in the background. Manage it with the following.\n\n### Start\n\nRun `./scripts/interactive_setup.sh --force` to restart with the existing `.env`, or start `monero-wallet-rpc` manually (see Step 3).\n\n### Stop\n\n```bash\n./scripts/stop_wallet_rpc.sh\n# or: kill $(cat $MONERO_LOCK_DIR/wallet-rpc.pid)\n```\n\n### Check status\n\n```bash\n./scripts/wallet_rpc_status.sh\n```\n\nEmits JSON: `running`, `pid`, `port`.\n\n---\n\n## Security checklist\n\n- ✅ `.env` is `chmod 600` and not committed.\n- ✅ wallet-rpc bound to `127.0.0.1` (default); strong `--rpc-login` secret.\n- ⚠️ **Process-table exposure:** `monero-wallet-rpc` accepts the wallet password only via `--password` (CLI), so it is visible in `ps aux` / `/proc/<pid>/cmdline` for the daemon's lifetime. This is an upstream limitation. Run on a single-user system, or restrict process-table visibility (dedicated user account, container, or PID namespace).\n- ✅ `--untrusted-daemon` for any remote node.\n- ✅ Test on **stagenet** before touching mainnet funds.\n- ✅ `--dry-run` / `estimate_fee.sh` before every real send.\n- ✅ Back up the 25-word wallet seed offline.\n\n## Next steps\n- Day-to-day usage & workflows: `SKILL.md`.\n- RPC details / error recovery / env vars: `references/`.\n\nFile v0.1.1:tests/fixtures/ca_acc/create_address.json\n\n{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"result\":{\"address\":\"SubAddr5\",\"address_index\":7}}\n\nFile v0.1.1:tests/fixtures/ca_nolabel/create_address.json\n\n{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"result\":{\"address\":\"Sub9\",\"address_index\":9}}\n\nFile v0.1.1:tests/fixtures/ca_q/create_address.json\n\n{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"result\":{\"address\":\"Q\",\"address_index\":2}}\n\nFile v0.1.1:tests/fixtures/ca/create_address.json\n\n{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"result\":{\"address\":\"SubAddr1\",\"address_index\":3}}\n\nFile v0.1.1:tests/fixtures/check_balance/get_balance.json\n\n{\"jsonrpc\":\"2.0\",\"id\":\"0\",\"result\":{\"balance\":10500000000000,\"unlocked_balance\":8200000000000,\"blocks_to_unlock\":42,\"time_to_unlock\":30240}}","readmeExcerpt":"Skill: agenta-monero Owner: tibbar-etihw Summary: Use when making or receiving Monero (XMR) payments. Generates addresses, sends payments, checks balances, verifies transactions, generates and verifies payment proofs, estimates fees, sweeps funds, and manages wallet operations via a self-hosted monero-wallet-rpc node. Keywords: monero, xmr, cryptocurrency, payments, wallet, send, receive, payment proof. Tags: latest:","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"create_address.sh  --label \"Payment from Alice\" [--account 0]   -> {address, address_index, account}\nsend_xmr.sh        --address ADDR --amount \"1.5\"                -> {tx_hash, fee, amount[, tx_key]}\n                   [--priority 0] [--get-tx-key] [--dry-run] [--confirm]\n                   [--dest '[{\"address\":\"A\",\"amount\":\"1.0\"}]']\nestimate_fee.sh    --address ADDR --amount \"1.5\" [--priority 0] -> {fee, amount, priority, num_destinations}\nsweep_all.sh       --address ADDR [--account 0] [--subaddress N]-->{tx_hash, fee, amount}\n                   [--priority 0] [--dry-run] [--confirm]\ncheck_balance.sh   [--account 0]                                -> {balance, unlocked_balance, blocks_to_unlock, time_to_unlock, account}\nget_transfer.sh    --tx-hash HASH                               -> {tx_hash, amount, fee, direction, confirmations, address, address_index, timestamp, confirmed, unlock_time}\nverify_payment.sh  --tx-hash HASH | --address ADDR --expected-amount \"1.5\" -> {verified, confirmations, tx_hash, address, address_index, confirmed, amount}\nget_tx_proof.sh    --tx-hash HASH --address ADDR                -> {tx_hash, address, proof}\ncheck_tx_proof.sh  --tx-hash HASH --address ADDR --proof PROOF  -> {verified, confirmations, amount, tx_hash, address}\nlist_incoming.sh   [--confirmed-only|--all] [--since-block N]   -> [{tx_hash, amount, confirmations, address, address_index, timestamp, confirmed, unlock_time}]\n                   [--since-timestamp N] [--limit 100] [--account 0]\nlist_outgoing.sh   [--since-block N] [--since-timestamp N]      -> [{tx_hash, amount, fee, timestamp, address, address_index, unlock_time}]\n                   [--limit 100] [--account 0]\nlist_addresses.sh  [--account 0]                                -> [{index, address, label, balance, unlocked_balance}]\nvalidate_address.sh --address ADDR                              -> {valid, network, network_match, subaddress, integrated}\nsync_status.sh                                                   "},{"language":"json","snippet":"// create_address.sh\n{\"address\":\"88bc...\",\"address_index\":5,\"account\":0}\n// send_xmr.sh --address ... --amount \"1.5\"\n{\"tx_hash\":\"7663438...\",\"fee\":\"0.0000869\",\"amount\":\"1.5\"}\n// estimate_fee.sh --address ... --amount \"1.5\"\n{\"fee\":\"0.0000869\",\"amount\":\"1.5\",\"priority\":0,\"num_destinations\":1}\n// sweep_all.sh --address DEST --dry-run\n{\"tx_hash\":\"\",\"fee\":\"0.0000869\",\"amount\":\"8.2\"}\n// check_balance.sh\n{\"balance\":\"10.5\",\"unlocked_balance\":\"8.2\",\"blocks_to_unlock\":42,\"time_to_unlock\":30240,\"account\":0}\n// get_transfer.sh --tx-hash ...\n{\"tx_hash\":\"c36258a...\",\"amount\":\"1.5\",\"fee\":\"0.0000435\",\"direction\":\"in\",\"confirmations\":15,\"address\":\"77Vx9cs...\",\"address_index\":3,\"timestamp\":1535918400,\"confirmed\":true,\"unlock_time\":0}\n// verify_payment.sh --tx-hash ...\n{\"verified\":true,\"confirmations\":12,\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"address_index\":3,\"confirmed\":true,\"amount\":\"1.5\"}\n// get_tx_proof.sh --tx-hash ... --address ...\n{\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\",\"proof\":\"ProofV1...\"}\n// check_tx_proof.sh --tx-hash ... --address ... --proof ...\n{\"verified\":true,\"confirmations\":15,\"amount\":\"1.5\",\"tx_hash\":\"c36258a...\",\"address\":\"77Vx9cs...\"}\n// validate_address.sh --address ...\n{\"valid\":true,\"network\":\"mainnet\",\"network_match\":true,\"subaddress\":false,\"integrated\":false}\n// sync_status.sh\n{\"height\":1523651,\"daemon_connected\":true,\"wallet_version\":196613}\n// list_incoming.sh (array element)\n{\"tx_hash\":\"c36258a...\",\"amount\":\"1.5\",\"confirmations\":15,\"address\":\"77Vx9cs...\",\"address_index\":3,\"timestamp\":1535918400,\"confirmed\":true,\"unlock_time\":0}"},{"language":"json","snippet":"{\n  \"error\": true,\n  \"code\": \"TX_NOT_FOUND\",\n  \"message\": \"no transfer found for txid 7663438…\"\n}"},{"language":"bash","snippet":"git clone https://github.com/tibbar-etihw/agenta-monero.git ~/.hermes/skills/finance/agenta-monero"},{"language":"bash","snippet":"git clone https://github.com/tibbar-etihw/agenta-monero.git ~/.openclaw/workspace/skills/finance/agenta-monero"},{"language":"bash","snippet":"cp .env.example .env"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: agenta-monero\ndescription: \"Use when making or receiving Monero (XMR) payments. Generates addresses, sends payments, checks balances, verifies transactions, generates and verifies payment proofs, estimates fees, sweeps funds, and manages wallet operations via a self-hosted monero-wallet-rpc node. Keywords: monero, xmr, cryptocurrency, payments, wallet, send, receive, payment proof.\"\nlicense: MIT\ncompatibility: \"Requires bash 4+, curl, jq, flock (util-linux), and a running monero-wallet-rpc >= 0.18.0.\"\nmetadata:\n  hermes:\n    category: finance\n    tags: [monero, cryptocurrency, payments, wallet, xmr]\n    related_skills: []\n  version: \"0.3.0\"\n  author: Private Payments\n  permissions:\n    shell_execution: true\n    file_writes:\n      - \".env (chmod 600) — RPC credentials + wallet password\"\n      - \"$MONERO_LOCK_DIR/.netrc (chmod 600) — ephemeral RPC auth\"\n      - \"$MONERO_LOCK_DIR/wallet-rpc.pid — process tracking\"\n      - \"$MONERO_LOCK_DIR/wallet-rpc.port — port tracking\"\n      - \"$MONERO_LOCK_DIR/.last_refresh — refresh timestamp\"\n    process_management: \"starts/stops monero-wallet-rpc as a background process\"\n    network_access: \"HTTP POST to $MONERO_RPC_URL/json_rpc (localhost by default)\"\n    credential_access: \"reads .env for RPC + wallet credentials; writes .netrc for curl auth\"\n---\n\n# Agenta-Monero\n\nShell wrappers over `monero-wallet-rpc` for autonomous Monero (XMR) payments. All scripts emit JSON to stdout (success) or a structured error JSON to stderr; they compose into receive/send/verify/sweep workflows. Money math is integer piconeros internally; XMR decimal strings appear in output.\n\n> **WARNING — IRREVERSIBLE FINANCIAL OPERATIONS**\n>\n> - Monero transactions are **irreversible**. Once broadcast, funds cannot be recovered.\n> - `send_xmr.sh` and `sweep_all.sh` **require `--confirm` to broadcast**. Without it, they refuse to relay. Use `--dry-run` to preview without `--confirm`.\n> - `sweep_all.sh` transfers **all unlocked funds** from the wallet (or subaddress) to a single destination. A mistaken or maliciously triggered sweep can drain the entire balance.\n> - Always validate the recipient address (`validate_address.sh`) and confirm the amount before executing a send or sweep.\n> - The `.env` file contains `MONERO_WALLET_PASSWORD` and RPC credentials. It is created with `chmod 600`, but on multi-user systems, shared CI, or agent workspaces with broad read access, an attacker who reads `.env` can access the wallet and move funds. Secure the file and the system accordingly.\n\n**Use when:** generating receive addresses, sending/sweeping XMR, checking balance, verifying an incoming payment or a payment proof, estimating fees, or reconciling transactions by hash.\n\n## Prerequisites\n\n- **Install Monero CLI tools** (≥ 0.18.0): download from https://getmonero.org/downloads/ — you need at minimum `monero-wallet-rpc`. Also create a wallet file: `monero-wallet-cli --generate-new-wallet ~/Monero/wallets/main --password 'PASS'` (write down the 2"},{"path":"README.md","content":"# Agenta-Monero\n\n> Autonomous Monero (XMR) payments for Hermes and Openclaw agents via shell. JSON-in, JSON-out wrappers over `monero-wallet-rpc` for sending, receiving, verifying, and sweeping. Composable into agent-driven workflows.\n\n> **WARNING — Irreversible Financial Operations**\n>\n> Monero transactions are **irreversible**. `send_xmr.sh` and `sweep_all.sh` broadcast by default — use `--dry-run` to preview. `sweep_all.sh` transfers **all unlocked funds** to one destination; a mistaken or maliciously triggered sweep can drain the entire wallet balance. Always validate addresses and confirm amounts before executing.\n\n## What It Does\n\n| Command | Description |\n|---------|-------------|\n| `create_address.sh` | Generate a receive address with label |\n| `send_xmr.sh` | Send XMR (requires `--confirm`, supports `--dry-run`) |\n| `sweep_all.sh` | Sweep **all** wallet funds to a destination (requires `--confirm`, supports `--dry-run`) |\n| `check_balance.sh` | Check balance + unlock status |\n| `estimate_fee.sh` | Preview fees before sending |\n| `validate_address.sh` | Verify address format and network |\n| `get_transfer.sh` | Look up a transaction by hash |\n| `verify_payment.sh` | Confirm a payment was received |\n| `get_tx_proof.sh` / `check_tx_proof.sh` | Generate or verify payment proofs |\n| `list_incoming.sh` / `list_outgoing.sh` | List transactions with filtering |\n| `list_addresses.sh` | List subaddresses with balances |\n| `sync_status.sh` | Check daemon connection + wallet height |\n| `interactive_setup.sh` | First-time setup wizard |\n| `wallet_rpc_status.sh` / `stop_wallet_rpc.sh` | Manage the RPC daemon |\n\n## Prerequisites\n\n- **OS:** Linux or macOS (Windows not supported)\n- **Monero CLI tools** >= 0.18.0 ([download](https://getmonero.org/downloads/)) - at minimum `monero-wallet-rpc`\n- **Bash** >= 4, `curl`, `jq`, `flock` (util-linux)\n\n## Installation\n\n**Hermes:**\n```bash\ngit clone https://github.com/tibbar-etihw/agenta-monero.git ~/.hermes/skills/finance/agenta-monero\n```\n\n**OpenClaw:**\n```bash\ngit clone https://github.com/tibbar-etihw/agenta-monero.git ~/.openclaw/workspace/skills/finance/agenta-monero\n```\n\nOr tell your agent:\n> \"Install the agenta-monero skill from https://github.com/tibbar-etihw/agenta-monero\"\n\n**New to this?** See the [Getting Started guide](docs/GETTING_STARTED.md) for a detailed walkthrough covering wallet creation, daemon setup, and first-time configuration.\n\n## Configuration\n\nYour agent configures everything. Simply prompt it with:\n\n> \"Set up the Agenta-Monero skill.\"\n\n---\n\n<details>\n<summary>Manual configuration (advanced)</summary>\n\nCopy `.env.example` to `.env` and fill in your values:\n\n```bash\ncp .env.example .env\n```\n\nRequired variables:\n- `MONERO_RPC_URL` - wallet RPC endpoint (default: `http://127.0.0.1:18088`)\n- `MONERO_RPC_USER` / `MONERO_RPC_PASSWORD` - RPC credentials\n- `MONERO_WALLET_NAME` - must match the loaded wallet\n- `MONERO_WALLET_PASSWORD` - wallet password\n- `MONERO_NETWORK` - `mainnet` or `stagenet`\n\n>"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn76dhwaqd2zm8bn4qhjp3c7bd8bcppg\",\n  \"slug\": \"agenta-monero\",\n  \"version\": \"0.1.2\",\n  \"publishedAt\": 1785258846093\n}"},{"path":"references/env-reference.md","content":"# Environment Variables\n\nAll configuration is read from `.env` (parsed safely — never sourced) at the skill root. Copy `.env.example` to `.env` and edit; run `./setup.sh` after changing it. Values shown are defaults.\n\n## Connection\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_RPC_URL` | `http://127.0.0.1:18088` | URL of the running `monero-wallet-rpc`. |\n| `MONERO_RPC_USER` | _(empty)_ | RPC authentication username. Written into `$MONERO_LOCK_DIR/.netrc` (mode `0600`). |\n| `MONERO_RPC_PASSWORD` | _(empty)_ | RPC authentication password. Written into `.netrc`; never passed on the command line. |\n| `MONERO_WALLET_NAME` | _(empty)_ | Wallet name; must match the wallet loaded in the RPC server. |\n\n## Network\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_NETWORK` | `mainnet` | `mainnet` \\| `stagenet`. `validate_address` compares each address's `nettype` against this to derive `network_match`. |\n\n## Lifecycle\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_LIFECYCLE` | `none` | `none` = assume the wallet RPC is already running (the supported mode). `full` = the agent is expected to manage daemon + wallet lifecycle (reserved). |\n\n## Remote node (optional)\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_REMOTE_NODE` | _(empty)_ | Remote node hostname/IP, if used. |\n| `MONERO_REMOTE_PORT` | _(empty)_ | Remote node port. |\n\n## Display\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_CONFIRMATIONS` | `10` | Blocks before a payment is considered `confirmed`. Used by `verify_payment`, `get_transfer`, `list_incoming`. |\n| `MONERO_AMOUNT_FORMAT` | `xmr` | `xmr` \\| `piconero`. Output amount rendering (scripts emit XMR decimal strings by default). |\n\n## Refresh\n\nThere is no `sync` RPC; the wallet refreshes from the daemon via `refresh`, which can take seconds-to-minutes. Refresh is **operation-aware** (see `rpc-reference.md` for the per-op table).\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `MONERO_AUTO_REFRESH` | `true` | `true` = refresh before balance/transfer/verify ops; `false` = never auto-refresh. |\n| `MONERO_REFRESH_MIN_INTERVAL` | `30` | Minimum seconds between refreshes (caching). A refresh is skipped if the last one was more recent than this. Stored in `$MONERO_LOCK_DIR/.last_refresh`. |\n| `MONERO_REFRESH_TIMEOUT` | `120` | Maximum seconds for a single `refresh` operation. |\n\n**Override:** any auto-refreshing script accepts `--no-refresh` (works in **any** argument position) to skip the refresh step — useful for fast read-only checks when you can tolerate slightly stale data.\n\n## Retry\n\nThe retry helper (`lib/retry.sh`) is **available and unit-tested, but NOT currently applied** to any script RPC call — all scripts call `rpc_call` directly. `send_xmr` and `sweep_all` are intentionally never retried (non-idempotent); `get_transfer` and"},{"path":"references/error-runbook.md","content":"# Error Recovery Runbook\n\nFull recovery procedures for every error code emitted by Agenta-Monero scripts. Every error is emitted to **stderr** as a single-line (compact) JSON object and the script exits non-zero — parse it with `jq`, not line-by-line:\n\n```json\n{\n  \"error\": true,\n  \"code\": \"WALLET_NOT_LOADED\",\n  \"message\": \"Wallet 'my_wallet' is not loaded in the RPC server\"\n}\n```\n\nParse `code` to branch; read `message` for specifics. (The `suggestion` key is reserved in the emitter but not currently populated — use the Recovery column below for guidance.)\n\n## Error codes (full table)\n\n| Code | Meaning | Retryable | Recovery |\n|------|---------|:---------:|----------|\n| `CONFIG_MISSING` | Required env var not set, or a required `--flag` omitted | No | Run `./setup.sh` to create `.env`, fill required values. For missing flags, supply the required argument (`--address`, `--amount`, `--tx-hash`, `--proof`, etc.). |\n| `CONFIG_INVALID` | `.env` contains invalid syntax or shell metacharacters | No | Inspect `.env` for metacharacters or malformed lines; fix and retry. Never `source .env` — it is parsed safely by design. |\n| `RPC_UNREACHABLE` | Cannot connect to `monero-wallet-rpc` | Yes | Confirm `monero-wallet-rpc` is running and `MONERO_RPC_URL` is correct; start it if not. **For a send/sweep timeout, this code means the transaction status is UNKNOWN — do NOT treat it as \"absent\" and do NOT retry the send;** fix connectivity and re-check with `get_transfer.sh --tx-hash`. |\n| `WALLET_NOT_LOADED` | Wallet name doesn't match the loaded wallet | No | Open the correct wallet in the RPC server (`open_wallet`); verify `MONERO_WALLET_NAME`. |\n| `WALLET_LOCKED` | Wallet file locked by another process | No | Find the holder (`lsof | grep wallet.keys`); kill it or wait for release. |\n| `DAEMON_DISCONNECTED` | Wallet RPC can't reach the daemon | Yes | Check daemon status; restart `monerod` if needed. |\n| `INSUFFICIENT_BALANCE` | Not enough unlocked funds | No | `check_balance.sh` to see available funds; wait for unlocks or reduce the amount. |\n| `AMOUNT_INVALID` | Amount negative, too many decimals (>12), or exceeds balance | No | Correct the amount string (positive decimal, <=12 fractional digits). |\n| `INVALID_ADDRESS` | Address format/checksum invalid | No | Re-check the address; do not use it. |\n| `NETWORK_MISMATCH` | Address valid but on the wrong network | No | Use an address for the configured `MONERO_NETWORK` (mainnet/stagenet). |\n| `INVALID_INPUT` | Bad argument value (priority not 0-4, tx-hash not 64 lowercase hex, label too long/has control chars, `--dest` not a JSON array) | No | Correct the argument value. |\n| `SYNC_FAILED` | Wallet sync failed | Yes | Run `sync_status.sh` to diagnose; may need to restart wallet RPC. |\n| `REFRESH_FAILED` | Wallet refresh failed | Yes | Run `sync_status.sh`; may need to restart wallet RPC; pass `--no-refresh` to bypass on auto-refreshing ops if you can tolerate stale data. |\n| `TX_RELAY_FAILED` | Transaction created bu"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2101,"uniquenessScore":39,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T10:43:21.018Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T10:43:21.018Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T00:22:12.857Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}