{"id":"3abdde43-e433-4539-a759-0f8d80632b31","entityType":"agent","slug":"clawhub-rustok-wallet","name":"Rustok Agentic Wallet","canonicalUrl":"https://www.xpersona.co/agent/clawhub-rustok-wallet","canonicalPath":"/agent/clawhub-rustok-wallet","generatedAt":"2026-10-10T06:43:39.765Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T23:52:08.372Z","emptyReason":null},"description":"Self-custody Ethereum agent wallet - one container image, keys never leave your machine. Reads balances and DeFi positions. Sending is gated in a separate console, never the agent chat: approve each payment, or confirm autonomous mode once and it pays alone. No spending limits, you assume all risk.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.9K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s173q029wxh3tq4t0exr2f1fzn8accy0:wallet","sourceUrl":"https://clawhub.ai/rustok/wallet","homepage":"https://clawhub.ai/rustok/skills/wallet","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/rustok/wallet","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/rustok/skills/wallet","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":65,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Rustok Agentic Wallet 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-09T23:52:08.372Z","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-09T23:52:08.372Z","emptyReason":null},"stars":null,"forks":null,"downloads":1867,"packageName":null,"latestVersion":"0.11.0","tractionLabel":"1.9K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T23:52:08.371Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T23:52:08.372Z","lastCrawledAt":"2026-10-09T23:52:08.371Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T23:52:08.371Z","lastVerifiedAt":null,"highlights":[{"version":"0.11.0","createdAt":"2026-08-20T05:00:59.882Z","changelog":"## rustok-wallet-tui 0.11.0 - Updated onboarding instructions to use the correct versioned install script for 0.11.0. - Expanded documentation: clarified how mode switching works and what happens to parked transactions. - Added details explaining that both enabling and disabling autonomous mode require explicit user action in the console, and what to expect when the mode changes mid-session. - Removed the `skill-card.md` file.","fileCount":4,"zipByteSize":11288},{"version":"0.10.0","createdAt":"2026-08-16T12:31:34.796Z","changelog":"rustok-wallet-tui v0.10.0 - Updated installer script references from v0.9.8 to v0.10.0 in onboarding instructions. - The onboarding step now specifies the user chooses a 6-digit approval PIN when creating the wallet (instead of both phrase and PIN being printed). - Removed skill-card.md from the package. - No functional or behavioral changes to wallet usage, guarantees, or features documented.","fileCount":4,"zipByteSize":10650},{"version":"0.9.8","createdAt":"2026-08-12T18:12:22.804Z","changelog":"**rustok-wallet-tui 0.9.8 – Changelog** - Signing messages (`sign_message`/EIP-191) is now refused outright in all modes; previous behavior (ungated signing) is no longer supported. - Documentation updated to clearly state that message signing is not available (not a risk, nor a supported feature); signature approval/parking is planned but unimplemented. - Removed outdated documentation files.","fileCount":4,"zipByteSize":10634},{"version":"0.9.5","createdAt":"2026-08-12T11:31:42.148Z","changelog":"rustok-wallet-tui 0.9.5 - Gas limits now include headroom to reduce risk of burnt fees during contract execution. - ERC-20 token support is now documented; registered tokens are reported in the wallet interface. - `rustok connect --force` now explicitly lists which registration will be dropped before rebuilding. - Removed the sample skill card: skill-card.md.","fileCount":4,"zipByteSize":10066},{"version":"0.9.4","createdAt":"2026-08-10T12:18:33.821Z","changelog":"- Updated installer references to version 0.9.4 in documentation. - Removed the skill-card.md file.","fileCount":4,"zipByteSize":8923},{"version":"0.9.3","createdAt":"2026-08-09T10:44:00.461Z","changelog":"- Bump version to 0.9.3. - Update installation instructions and references to use wallet-tui-v0.9.3 in all relevant URLs and code blocks. - Remove the outdated skill summary card file (skill-card.md).","fileCount":4,"zipByteSize":9052},{"version":"0.9.2","createdAt":"2026-08-09T06:25:32.973Z","changelog":"- Bumped wallet skill version to 0.9.2. - Updated installation instructions in the documentation to reference the new version number and installer URL. - Removed sample file: skill-card.md. - No changes to functionality or wallet features; this is a documentation and housekeeping update.","fileCount":4,"zipByteSize":8966},{"version":"0.9.1","createdAt":"2026-08-08T12:26:09.729Z","changelog":"- Expanded documentation to clarify autonomous mode: sending funds on-chain is now user-gated in a separate console unless autonomous mode is confirmed once per wallet, after which the wallet can send autonomously. - Updated onboarding instructions and script URLs from version 0.9.0 to 0.9.1. - Improved descriptions to more clearly explain transaction gating, the role of user confirmation, and the autonomous mode workflow. - Removed the sample skill card file (skill-card.md). - No functional or behavioral code changes; improvements are documentation/clarity-focused.","fileCount":4,"zipByteSize":8951}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s173q029wxh3tq4t0exr2f1fzn8accy0:wallet","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s173q029wxh3tq4t0exr2f1fzn8accy0:wallet` 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/rustok/wallet 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-rustok-wallet/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-rustok-wallet/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-rustok-wallet/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-rustok-wallet/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-rustok-wallet/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-rustok-wallet/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-10T06:43:39.763Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-rustok-wallet/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-rustok-wallet/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-rustok-wallet/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-rustok-wallet/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-09T23:52:08.372Z","emptyReason":null},"readme":"Skill: Rustok Agentic Wallet\n\nOwner: rustok\n\nSummary: Self-custody Ethereum agent wallet - one container image, keys never leave your machine. Reads balances and DeFi positions. Sending is gated in a separate console, never the agent chat: approve each payment, or confirm autonomous mode once and it pays alone. No spending limits, you assume all risk.\n\nTags: latest:0.11.0\n\nVersion history:\n\nv0.11.0 | 2026-08-20T05:00:59.882Z | user\n\n## rustok-wallet-tui 0.11.0\n\n- Updated onboarding instructions to use the correct versioned install script for 0.11.0.\n- Expanded documentation: clarified how mode switching works and what happens to parked transactions.\n- Added details explaining that both enabling and disabling autonomous mode require explicit user action in the console, and what to expect when the mode changes mid-session.\n- Removed the `skill-card.md` file.\n\nv0.10.0 | 2026-08-16T12:31:34.796Z | user\n\nrustok-wallet-tui v0.10.0\n\n- Updated installer script references from v0.9.8 to v0.10.0 in onboarding instructions.\n- The onboarding step now specifies the user chooses a 6-digit approval PIN when creating the wallet (instead of both phrase and PIN being printed).\n- Removed skill-card.md from the package.\n- No functional or behavioral changes to wallet usage, guarantees, or features documented.\n\nv0.9.8 | 2026-08-12T18:12:22.804Z | user\n\n**rustok-wallet-tui 0.9.8 – Changelog**\n\n- Signing messages (`sign_message`/EIP-191) is now refused outright in all modes; previous behavior (ungated signing) is no longer supported.\n- Documentation updated to clearly state that message signing is not available (not a risk, nor a supported feature); signature approval/parking is planned but unimplemented.\n- Removed outdated documentation files.\n\nv0.9.5 | 2026-08-12T11:31:42.148Z | user\n\nrustok-wallet-tui 0.9.5\n\n- Gas limits now include headroom to reduce risk of burnt fees during contract execution.\n- ERC-20 token support is now documented; registered tokens are reported in the wallet interface.\n- `rustok connect --force` now explicitly lists which registration will be dropped before rebuilding.\n- Removed the sample skill card: skill-card.md.\n\nv0.9.4 | 2026-08-10T12:18:33.821Z | user\n\n- Updated installer references to version 0.9.4 in documentation.\n- Removed the skill-card.md file.\n\nv0.9.3 | 2026-08-09T10:44:00.461Z | user\n\n- Bump version to 0.9.3.\n- Update installation instructions and references to use wallet-tui-v0.9.3 in all relevant URLs and code blocks.\n- Remove the outdated skill summary card file (skill-card.md).\n\nv0.9.2 | 2026-08-09T06:25:32.973Z | user\n\n- Bumped wallet skill version to 0.9.2.\n- Updated installation instructions in the documentation to reference the new version number and installer URL.\n- Removed sample file: skill-card.md.\n- No changes to functionality or wallet features; this is a documentation and housekeeping update.\n\nv0.9.1 | 2026-08-08T12:26:09.729Z | user\n\n- Expanded documentation to clarify autonomous mode: sending funds on-chain is now user-gated in a separate console unless autonomous mode is confirmed once per wallet, after which the wallet can send autonomously.\n- Updated onboarding instructions and script URLs from version 0.9.0 to 0.9.1.\n- Improved descriptions to more clearly explain transaction gating, the role of user confirmation, and the autonomous mode workflow.\n- Removed the sample skill card file (skill-card.md).\n- No functional or behavioral code changes; improvements are documentation/clarity-focused.\n\nv0.9.0 | 2026-08-08T10:27:24.863Z | user\n\n- Added documentation on \"autonomous mode,\" detailing how and when it requires user confirmation for on-chain sends.\n- Clarified that a wallet in autonomous mode still parks every send until manually confirmed in the console.\n- Provided user guidance for troubleshooting parked sends related to unconfirmed autonomous mode, with clear instructions not to retry.\n- Updated install script URLs and related instructions to reference version 0.9.0.\n- Removed the file skill-card.md from the distribution.\n\nv0.8.5 | 2026-08-06T11:24:14.964Z | user\n\n- Version bump to 0.8.5.\n- Updated onboarding and install instructions to use the new 0.8.5 version URLs and tags.\n- Removed the unused file: skill-card.md.\n\nv0.8.4 | 2026-08-04T13:09:17.226Z | user\n\nrustok-wallet-tui v0.8.4\n\n- Updated installer, image, and documentation references to version 0.8.4.\n- Added explicit link to docs/CAVEATS.md for a comprehensive list of guarantees and limitations.\n- Removed the sample file skill-card.md.\n- No functional changes to the wallet agent or usage flow.\n\nv0.8.3 | 2026-08-03T15:05:19.521Z | user\n\n- Removed the outdated skill-card.md file.\n- Bumped version to 0.8.3.\n- Updated onboarding instructions: requires users to download and read install.sh before running, emphasizing script auditability and security.\n- Updated install command and references to use version 0.8.3.\n- Podman example now uses secret mount with mode, uid, and gid for better security.\n- Improved documentation clarity and detail on setup and security practices.\n\nv0.8.2 | 2026-07-22T11:23:50.405Z | user\n\nInstaller and shim stop overclaiming. uninstall --purge-keys now refuses through a pipe BEFORE dismantling anything (it used to refuse after removing the shim, PATH block, secrets and registrations). Teardown no longer reports work it failed to do. cosign detection runs the tool instead of asking command -v, so a broken cosign is no longer reported as absent. An unwritable shell profile no longer fails an install that already succeeded. doctor and status are read-only and point a fresh install at rustok init. Honest about limits: the RPC URL guarantee holds only after connect, update pulls by tag without re-verifying, and cosign 2.x cannot read these signatures (use cosign 3+ or install without it). Wallet behaviour unchanged.\n\nv0.8.1 | 2026-07-22T07:24:29.215Z | user\n\ncosign is no longer a prerequisite. The image is pulled by digest (that is what fixes the bytes you get); cosign, when present and runnable, verifies who built it. A missing or broken cosign is reported and skipped, not treated as a failure; a working cosign that disagrees still stops the install. Note: cosign 2.x cannot read these signatures (stored as OCI referrers) — use cosign 3+, or install without cosign. Wallet behaviour is unchanged from 0.8.0.\n\nv0.8.0 | 2026-07-21T09:51:03.154Z | user\n\nOne-command install: curl|sh installs the rustok shim, then rustok init / connect / console. The wallet image is signed in CI and pulled by digest. Keyring password can arrive as a file (docker parity with podman secrets). Wallets are discovered by label, never a fixed container name. Docker users on 0.7.1 must reinstall: the image version is chosen by the shim, and the shim does not update itself.\n\nv0.7.1 | 2026-07-15T10:25:00.071Z | auto\n\n- Update all references and usage examples to v0.7.1 Docker image.\n- Remove outdated skill-card.md.\n- Refresh documentation and health check script to match version update.\n- No functional or interface changes; version bump and cleanup only.\n\nv0.7.0 | 2026-07-15T08:32:05.966Z | auto\n\nrustok-wallet-tui v0.7.0\n\n- Updated Docker image tags and instructions to v0.7.0 throughout documentation and config examples.\n- Removed deprecated skill-card.md file.\n- Minor cleanup and refinements to health-check script and metadata files.\n- No breaking changes to user setup or main workflows.\n\nv0.6.0 | 2026-07-12T06:38:43.066Z | user\n\nFirst console-edition listing: honest threat model (what's protected on-chain vs. message signing), self-custody Ethereum agent wallet over MCP stdio.\n\nArchive index:\n\nArchive v0.11.0: 4 files, 11288 bytes\n\nFiles: claw.json (998b), skill-card.md (3008b), SKILL.md (20732b), _meta.json (126b)\n\nFile v0.11.0:SKILL.md\n\n---\nname: rustok-wallet-tui\ndescription: Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is refused outright, in every mode. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\nversion: 0.11.0\nmetadata:\n  openclaw:\n    emoji: \"🦀\"\n    homepage: https://github.com/rustok-org/mcp\n---\n\n# rustok-wallet-tui\n\n> **License note:** this OpenClaw skill package (`skills/rustok-wallet-tui/`) is MIT-0\n> per ClawHub requirements. The Rustok wallet core itself is proprietary; only the\n> compiled binary image is distributed.\n\nYou are connected to a **self-custody** Ethereum agent wallet that runs entirely\non the user's machine as a single Docker image (`ghcr.io/rustok-org/rustok-wallet-tui`).\nThe container runs the wallet core + gateway and speaks MCP over **stdio**; the\nprivate keys live only in the user's local Docker volume and never leave it.\n\n> ⚠️ **Self-custody, real funds, your risk.** This wallet has **no hard-coded\n> spending limits or budgets** — the user consciously accepts that funds sent to\n> the agent wallet are at risk. txguard still flags risky transactions, but it\n> does not block them. All supported chains the user enables are live (incl.\n> Ethereum mainnet). Always preview before executing and show the user the details.\n\n## What's protected — and what isn't (be honest with the user)\n\nThe wallet's guarantee is narrow and specific. State it plainly; do not oversell it.\n\nThe full list of boundaries — password delivery, updates, what we do not verify at\nall — lives in [docs/CAVEATS.md](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md).\n\n| | |\n|---|---|\n| **Protected** | Private keys stay in the user's **local Docker volume** and never leave the machine. **Sending funds on-chain** (`execute_transaction`) is gated in a **separate console window** (`rustok console`, opened by the user — see below): parked for the user's approval, with a PIN for high-risk items — unless the user has confirmed **autonomous mode** there, a confirmation only they can give, once per wallet. |\n| **Refused, not gated** | `sign_message` (EIP-191) is **refused outright** — in every mode, autonomous included. The console never sees a signature request, because signing does not happen at all: parking a signature for approval (`kind:sign`) is planned and not built. A tool that is listed and always refuses is neither a capability to rely on nor a hole to fear. Tell the user that rather than letting them plan around a signature. |\n| **Outside the model** | An agent with **shell / `docker exec` access to the container** can read the gateway key and reach the full signing surface (including EIP-712 permits — a classic drain). That is why the console is a **separate window, not an agent command**. Trusting your own agent is the user's call, the same as never pasting a seed phrase into an untrusted tool. |\n\n**Never claim** the agent (or a prompt-injected agent) \"cannot move funds.\" What is\ntrue: keys stay local, and **on-chain sends** are human-gated in the console.\n\n### The mode switch, and why a send may still park\n\nThe user switches the wallet's mode **in the console**: press **`c`** on the\nDashboard, pick `read_only` / `supervised` / `autonomous`, enter the PIN. That\nis how autonomy is turned ON — and OFF: switching back to `supervised` parks\nevery future send again, and `read_only` refuses every write outright. The\nagent cannot flip that switch, and neither can an environment variable or a\nlaunch flag. Until a human has confirmed autonomy there, an autonomous-looking\nwallet **parks every send** exactly like a supervised one.\n\n**Turning autonomy on does not release what already waits.** A payment parked\nbefore the switch stays parked — it goes out when the user releases it in the\nconsole, or expires. Do not retry it: a retry adds a second parked copy that\nwill be paid separately if released, and switching the mode releases neither\nof them.\n\n**Your session reads the wallet's mode once, when it connects.** If the user\nswitches the mode mid-session, your tool list does not change until the next\nconnect — a tool you still see may now be refused by the core. The refusal is\nthe wallet enforcing the new mode; tell the user what it said, do not retry\naround it.\n\nConfirmation from a messenger does not exist yet — the console is the only\nplace the switch can be thrown.\n\n## What changed in 0.9.8\n\n- **`sign_message` is refused outright, and these texts finally say so.** Every\n  earlier release described it as an ungated hole you had to guard against. It is\n  not a hole and not a protection: signing is an unfinished capability, and\n  parking a signature for approval is planned and not built. Live acceptance of\n  0.9.7 asked the wallet and got a refusal; nine texts had said otherwise.\n\n## What changed in 0.9.7\n\n- **The wallet states what it does not promise.** A `## Legal` section below, and\n  a full [DISCLAIMER](https://github.com/rustok-org/mcp/blob/main/DISCLAIMER.md)\n  that names the limit of every safeguard — starting with the one easiest to read\n  as absolute: autonomous mode sends without asking once confirmed.\n\n## What changed in 0.9.5\n\n- **Gas limits now carry headroom.** A limit set to exactly the estimate turned\n  any drift between estimating and executing into a burnt fee — a contract call\n  could pay its gas and do nothing. Plain transfers were never affected.\n- **ERC-20 tokens are documented at last** (see below). The wallet has been able\n  to report registered tokens since 0.9.4, but nothing here said so, and an\n  unregistered token reads exactly like an absent one.\n- **`rustok connect --force` names what it is about to drop** instead of quietly\n  rebuilding the registration from the current shell.\n\n## Prerequisites\n\n- **Podman** (recommended) or **Docker**. **cosign is optional** — the installer\n  pulls the image **by digest** (you get exactly those bytes or nothing), and\n  uses cosign, when it is present and runnable, to verify *who built* it\n  (provenance). A missing or broken cosign is reported and skipped, not treated\n  as a failure; a working cosign that disagrees still stops the install. Use\n  cosign 3+ if you install it — 2.x cannot read our signatures.\n- An Ethereum RPC URL (an Alchemy key URL is best; a public RPC works for testing).\n\n## One-time onboarding (the user does this in their own terminal, once)\n\nThree commands, in a **terminal the agent cannot see** — the full guide is\n[docs/INSTALL.md](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md).\n\n**1. Install the `rustok` command.** Fetch the installer to a file, read that\nfile, then run **that same file** — what you read is exactly what runs. This is a\nwallet: fetching a script straight into a shell means running code you never saw,\nand one look costs less than that trade.\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.11.0/scripts/install.sh -o install.sh\nless install.sh      # ~321 lines of POSIX sh\nsh install.sh\n```\n\nIt pulls the wallet image **by digest** (those bytes or nothing) and verifies who\nbuilt it with cosign when cosign is available.\n\n<details>\n<summary>The one-liner, if you have already read the script</summary>\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.11.0/scripts/install.sh | sh\n```\n\nPiping to a shell runs whatever the URL serves at that moment, unreviewed. The\ntag pins a *version*, not the bytes — the identities bound to exact bytes live\n**inside** the script (the image digest and the shim's commit SHA). Fine once you\nhave read it; not the way to meet it.\n</details>\n\n**2. Create the wallet** — the user chooses a 6-digit approval PIN; it prints the\n12-word phrase ONCE:\n\n```bash\nrustok init\n```\n\n**3. Register this wallet with the agent client:**\n\n```bash\nrustok connect claude\n```\n\n`rustok init` asks the user to choose a **6-digit approval PIN** (typed twice) —\nthe one code they will ever enter: it unlocks the console session and confirms\npayments. The keyring password that encrypts the keystore is generated by `init`\nitself and kept in the engine's secret store; the user never sees or types it,\nand it never reaches shell history, `inspect` or any config file. `init` prints\nexactly one thing, once: the **12-word recovery phrase**.\n\nThe 12 words are the only backup — write them down offline; the wallet does not\nstore them. Recovery is `rustok restore` (or importing the words into any standard\nBIP-39 wallet — same address). A copy of the wallet volume by itself is **not** a\nbackup: the password that opens it lives outside the volume and is not something\nthe user knows. If the PIN is forgotten, `rustok set-pin` lets them choose a new\none — the old PIN is not needed.\n\n> **Rule of two windows:** never run `rustok init`, `rustok restore`,\n> `rustok set-pin` or the approval console through an agent shell/command — the\n> seed and PIN would leak into the agent's context. These belong only in the\n> user's own terminal (window 2). Do not ask the user for their PIN or their\n> phrase in this chat, ever.\n\n## Where the balance you show comes from\n\nThe wallet reads chains through an RPC node. Since 0.11.0 it carries two public\nendpoints for each chain it shows (Ethereum, Base, Arbitrum by default), so a\nfresh install reports balances without the user configuring anything, and USDC\nappears beside the native coin without being registered.\n\n**Tell the user this when it matters, and never as a footnote to a payment:** any\nnode that reads a balance learns the address and the IP that asked — the\ncarried ones, one they name themselves, and their own provider's alike. They\nreplace the carried list with `RUSTOK_RPC_URLS_<chain>`; naming one replaces the\nlist rather than adding to it.\n\nOn Arbitrum two USDC rows are normal: the native token and the bridged one, which\nthe wallet labels `USDC.e`. On chain both call themselves `USDC` — only the\ncontract address separates them, which is why balance rows carry it. Never treat\nthem as one balance, and never sum them without saying you did.\n\n## How the agent runs the wallet\n\n`rustok connect claude` writes this registration for the user, so normally none of\nit is typed by hand. It is reproduced here as the reference for what a correct\nsetup looks like — and for setups built without the shim.\n\nThe MCP client launches the image over stdio (keys stay local). **Never put the\nkeyring password in the MCP config or shell history.** On podman, store it once in\nthe secret store; on docker, keep it in a private `0600` file and pass its *path*:\n\n```bash\n# One-time (podman): the value never touches history, inspect or configs.\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" | podman secret create rustok-keyring-claude -\nunset pw\n\npodman run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  --secret rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000 \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453,42161\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.11.0\n```\n\n```bash\n# Docker variant: a 0600 file + RUSTOK_KEYRING_PASSWORD_FILE (path, not value).\numask 077\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" > ~/.rustok-keyring-pass\nunset pw\n\ndocker run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  -v ~/.rustok-keyring-pass:/run/keyring-pass:ro \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/keyring-pass \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453,42161\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.11.0\n```\n\n> Legacy `--env-file` delivery still works but is deprecated: the value lands in\n> `inspect`, and quotes inside an env-file become part of the password (a silent\n> unlock failure). Migrate to the secret / `_FILE` delivery above.\n\n> **Labels, not `--name`:** the agent launches this itself, and a fixed name\n> collides with health probes / a second `mcp list`. The `rustok.agent` sub-label\n> also lets a second agent run its **own** wallet (own volume) alongside.\n\n> The container automatically mints an ephemeral `RUSTOK_MCP_API_KEY` for the\n> loopback gateway↔mcp hop, so no API key configuration is needed for stdio use.\n> Set `RUSTOK_MCP_API_KEY` yourself **only** when exposing the gateway over a\n> network (not the default stdio setup).\n\nWhen the agent asks the user to approve a transaction, the user opens the\nconsole in a **second terminal** (window 2), never through the agent session:\n\n```bash\nrustok console\n```\n\nWithout the shim, the container runs under an auto-generated name (labels, not\n`--name`), so it is found by label:\n\n```bash\ndocker exec -it \"$(docker ps -q --filter label=rustok=wallet --filter label=rustok.agent=claude)\" rustok-console\n```\n\nThe console shows the decoded transaction from the wallet core and waits for\n`y/N` (high-risk items also ask for the per-transaction PIN).\n\nFor **Claude Desktop / Cursor** (stdio MCP), this is the entry `rustok connect`\nwrites — or that the user adds by hand to the MCP config. The keyring\npassword is delivered by the podman secret (or the docker `_FILE` mount) above,\n**never in this config file** — only the non-secret RPC URL lives here:\n\n```json\n{\n  \"mcpServers\": {\n    \"rustok\": {\n      \"command\": \"podman\",\n      \"args\": [\"run\", \"-i\", \"--rm\",\n               \"--label\", \"rustok=wallet\", \"--label\", \"rustok.agent=claude\",\n               \"-v\", \"rustok-wallet-tui:/data\",\n               \"--secret\", \"rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000\",\n               \"-e\", \"RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude\",\n               \"-e\", \"RUSTOK_ALLOWED_CHAINS=1,8453,42161\",\n               \"-e\", \"RUSTOK_RPC_URLS_1\",\n               \"ghcr.io/rustok-org/rustok-wallet-tui:v0.11.0\"],\n      \"env\": {\n        \"RUSTOK_RPC_URLS_1\": \"https://your-rpc\"\n      }\n    }\n  }\n}\n```\n\n## Why Rustok exists\n\nRustok gives an AI agent a wallet of its own — self-custody, no middleman — so agents can begin\nto take part in the economy directly: weighing what's worth paying for, covering the compute,\ndata, and tools they rely on, and in time commissioning and paying the people who help them.\n\n## Tools\n\nThe stdio wallet image is process-trusted and exposes **all** tools by default.\nTo run a restricted agent, set `RUSTOK_MCP_CAPABILITIES` to a subset\n(`read_wallet` / `preview_tx` / `execute_tx`) — e.g. `read_wallet` for read-only.\nThe ceiling is enforced by the gateway, on the path every request takes: it\ncovers the MCP tools below **and** the HTTP routes behind them, so a session\ncannot reach past its capabilities by calling the gateway directly. In releases\nbefore 0.9.0 the ceiling was checked in the MCP layer only, which left every\nroute reachable beside it: the core refused signing for its own unrelated\nreasons, but a session narrowed away from `read_wallet` still read the wallet\naddress and every balance. A client may narrow its own session further in\n`initialize`, and can never widen it.\n\n| Tool | Capability | What it does |\n|------|-----------|--------------|\n| `get_wallet_context` | read_wallet | Active wallet address, the assets it holds (native coin + registered tokens), the assets it could not read, allowed chains |\n| `get_balances` | read_wallet | Balances of the active wallet — one row per asset, with `balance_formatted` to show and `token_address` to tell two same-named tokens apart — or the native balance of `{address, chain_id}` |\n| `get_positions` | read_wallet | DeFi positions — Aave v3 (collateral/debt/health factor/LTV) + ERC-4626 vaults; optional `{address}` |\n| `preview_transaction` | preview_tx | Preview any transaction `{to, value, chain_id, data?}` → decoded call (who/what is authorized), pre-sign simulation (revert check), gas, risk level |\n| `execute_transaction` | execute_tx | Submit a previewed transaction `{preview_id}` — parked for human approval on a supervised wallet, released by the core on one whose owner confirmed autonomous mode; a `pending` result carries `next_step` for the human |\n| `get_execution_status` | execute_tx | Poll a parked execution `{preview_id}` → `pending` / `executed` (+`tx_hash`) / `denied` / `expired` / `failed` (+`error_reason`), with the `not_after_unix` deadline. **`executed` means broadcast, not on-chain success** — see below |\n\n### ERC-20 tokens are opt-in — an empty list is not an empty wallet\n\nThe wallet reports the tokens the **user registered**, and never goes looking for\nothers. A wallet holding USDC shows no USDC until USDC is registered on that\nchain:\n\n```bash\n-e RUSTOK_TOKENS_1=\"USDC:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48:6\"\n-e RUSTOK_TOKENS_8453=\"USDC:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913:6\"\n```\n\n`SYMBOL:ADDRESS:DECIMALS`, comma-separated, one variable per chain, and the chain\nmust be listed in `RUSTOK_ALLOWED_CHAINS`. A malformed entry, a duplicate address\non one chain, or an unknown chain **fails startup** naming the chain — a\nhalf-loaded registry is worse than none. Symbol and decimals are taken from the\nuser, not read from the contract: get the decimals wrong and the wallet will show\na wrong amount confidently.\n\n**What this means for you, the agent:** before telling the user they hold none of\na token, say that it may simply not be registered. Reading an empty list as an\nempty wallet is the likeliest way to be wrong here — and it has already happened.\n\n## Behavioral guidelines\n\n1. **Always `preview_transaction` first** and show its decoded call + simulation (revert check) + risk level so the user gives informed approval.\n2. **The money path is preview → summary card → `execute_transaction` → human.**\n   `execute_transaction` only parks the transaction (`state: \"pending\"`) — the user\n   releases it in a separate terminal window by running `rustok console` (see\n   the onboarding above). Never offer to run the console command yourself\n   and never ask the user to paste the approval PIN into this chat.\n3. **`executed` means the transaction was broadcast, not that it succeeded.**\n   The wallet reports the hash the moment the network accepted the transaction\n   for inclusion; a transaction that reverts on-chain still costs its gas and\n   still reads as `executed` here. Verify the receipt independently before\n   telling the user their swap or approval went through — an explorer, or\n   `eth_getTransactionReceipt` where `status` must be `0x1`.\n4. **Poll `get_execution_status` reasonably**: when the user asks, or every ~15–30\n   seconds until the `not_after_unix` deadline (if it is `null` — only on request).\n   Stop on any terminal state: `executed`, `denied`, `expired`, `failed`. A\n   `denied` outcome is the human's answer — do not re-submit the same transaction;\n   a not-found error means the id is no longer retained — stop polling.\n5. **Surface what the preview decoded** (who/what is authorized, amount, revert check, estimated cost, risk level) before the user acts on it.\n6. **Use `get_wallet_context` first** so you don't hallucinate balances or chains.\n7. If a tool needs a capability the session lacks, it returns an authorization\n   error — explain that to the user rather than retrying.\n8. If the wallet is unreachable, tell the user the wallet container/onboarding may\n   not be set up (see onboarding above).\n\n## Legal\n\nProvided **as is**, without warranty of any kind, under the MIT-0 license.\n**What an agent does with this wallet is not an act of the authors:** the agent\ndriving it is third-party software whose output is unpredictable and may be\ninaccurate, incorrect, or undesirable, and evaluating each proposed transaction\nbefore approving it is the user's exclusive responsibility. Nothing this wallet\nor the agent driving it produces is investment, accounting, legal, or tax advice.\nSending funds is gated at the console **unless autonomous mode was confirmed**;\n**`sign_message` is refused outright** in every mode. The risk of loss is\nsubstantial and the user assumes all of it.\n\nFull terms, and every safeguard's limit named:\n<https://github.com/rustok-org/mcp/blob/main/DISCLAIMER.md>\n\nFile v0.11.0:_meta.json\n\n{\n  \"ownerId\": \"kn783xqj8cgxz5m78mszfj7x9d81x8f3\",\n  \"slug\": \"wallet\",\n  \"version\": \"0.11.0\",\n  \"publishedAt\": 1787202059882\n}\n\nFile v0.11.0:skill-card.md\n\n## Description:\n\nRustok Agentic Wallet gives an agent access to a local self-custody Ethereum wallet for reading balances and DeFi positions, previewing transactions, and submitting transactions through supervised or user-confirmed autonomous wallet modes.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[rustok](https://clawhub.ai/user/rustok)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to let an agent inspect Ethereum wallet state, review DeFi positions, preview on-chain transactions, and coordinate transaction execution from a local self-custody wallet. It is intended for users who accept live-funds risk and understand the separate approval console and autonomous mode behavior.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles a real self-custody wallet with live-funds transaction authority and no hard-coded spending limits.\n\nMitigation: Use read-only capabilities unless transaction execution is specifically needed, keep only limited funds in the wallet, preview every transaction, and rely on the separate approval console unless the user intentionally confirms autonomous mode.\n\nRisk: The installer can be run through a remote shell pipeline, which makes it easy to execute installer code without review.\n\nMitigation: Fetch the installer to a file, inspect it before running it, and verify installer or container provenance where possible.\n\nRisk: Broad default execution capabilities increase the blast radius if an agent session is misconfigured or over-trusted.\n\nMitigation: Configure the narrowest required wallet capability set, such as read-only access for balance and position inspection.\n\nRisk: Local wallet secrets and wallet volumes require lifecycle management by the user.\n\nMitigation: Understand how to remove or rotate the local secret and wallet volume before using the skill with meaningful funds.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/rustok/skills/wallet)\n- [Rustok MCP homepage](https://github.com/rustok-org/mcp)\n- [Install guide](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md)\n- [Caveats](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with inline shell commands and JSON configuration snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include wallet-state summaries, transaction-preview guidance, approval-console instructions, and status-polling guidance.]\n\n## Skill Version(s):\n\n0.11.0 (source: server release metadata, SKILL.md frontmatter, claw.json)\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.11.0:claw.json\n\n{\n  \"name\": \"rustok-wallet-tui\",\n  \"version\": \"0.11.0\",\n  \"description\": \"Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is refused outright, in every mode. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\",\n  \"author\": \"rustok-org\",\n  \"license\": \"MIT-0\",\n  \"permissions\": [\n    \"network\"\n  ],\n  \"entry\": \"SKILL.md\",\n  \"tags\": [\n    \"crypto\",\n    \"ethereum\",\n    \"wallet\",\n    \"defi\",\n    \"agent-wallet\",\n    \"mcp\",\n    \"self-custody\"\n  ],\n  \"minOpenClawVersion\": \"0.8.0\",\n  \"homepage\": \"https://github.com/rustok-org/mcp\"\n}\n\nArchive v0.10.0: 4 files, 10650 bytes\n\nFiles: claw.json (1016b), skill-card.md (2409b), SKILL.md (19651b), _meta.json (126b)\n\nFile v0.10.0:SKILL.md\n\n---\nname: rustok-wallet-tui\ndescription: Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions and sign messages. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is refused outright, in every mode. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\nversion: 0.10.0\nmetadata:\n  openclaw:\n    emoji: \"🦀\"\n    homepage: https://github.com/rustok-org/mcp\n---\n\n# rustok-wallet-tui\n\n> **License note:** this OpenClaw skill package (`skills/rustok-wallet-tui/`) is MIT-0\n> per ClawHub requirements. The Rustok wallet core itself is proprietary; only the\n> compiled binary image is distributed.\n\nYou are connected to a **self-custody** Ethereum agent wallet that runs entirely\non the user's machine as a single Docker image (`ghcr.io/rustok-org/rustok-wallet-tui`).\nThe container runs the wallet core + gateway and speaks MCP over **stdio**; the\nprivate keys live only in the user's local Docker volume and never leave it.\n\n> ⚠️ **Self-custody, real funds, your risk.** This wallet has **no hard-coded\n> spending limits or budgets** — the user consciously accepts that funds sent to\n> the agent wallet are at risk. txguard still flags risky transactions, but it\n> does not block them. All supported chains the user enables are live (incl.\n> Ethereum mainnet). Always preview before executing and show the user the details.\n\n## What's protected — and what isn't (be honest with the user)\n\nThe wallet's guarantee is narrow and specific. State it plainly; do not oversell it.\n\nThe full list of boundaries — password delivery, updates, what we do not verify at\nall — lives in [docs/CAVEATS.md](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md).\n\n| | |\n|---|---|\n| **Protected** | Private keys stay in the user's **local Docker volume** and never leave the machine. **Sending funds on-chain** (`execute_transaction`) is gated in a **separate console window** (`rustok console`, opened by the user — see below): parked for the user's approval, with a PIN for high-risk items — unless the user has confirmed **autonomous mode** there, a confirmation only they can give, once per wallet. |\n| **Refused, not gated** | `sign_message` (EIP-191) is **refused outright** — in every mode, autonomous included. The console never sees a signature request, because signing does not happen at all: parking a signature for approval (`kind:sign`) is planned and not built. A tool that is listed and always refuses is neither a capability to rely on nor a hole to fear. Tell the user that rather than letting them plan around a signature. |\n| **Outside the model** | An agent with **shell / `docker exec` access to the container** can read the gateway key and reach the full signing surface (including EIP-712 permits — a classic drain). That is why the console is a **separate window, not an agent command**. Trusting your own agent is the user's call, the same as never pasting a seed phrase into an untrusted tool. |\n\n**Never claim** the agent (or a prompt-injected agent) \"cannot move funds.\" What is\ntrue: keys stay local, and **on-chain sends** are human-gated in the console.\n\n### Autonomous mode, and why a send may park once\n\nA wallet can be in **autonomous** mode, in which it sends without asking each\ntime. That only happens after a human has confirmed the mode **in the console**:\npress **`c`**, enter the PIN, once per wallet. The agent cannot give that\nconfirmation, and neither can an environment variable or a launch flag.\n\nUntil it is confirmed, an autonomous wallet **parks every send** exactly like a\nsupervised one. The console shows this on every screen and offers the\nconfirmation on the Dashboard.\n\n**If a send parks unexpectedly, this is the first thing to check, and the honest\nthing to tell the user:** the wallet is autonomous but unconfirmed, and one\nconfirmation in the console clears it for good. Do not describe it as an error\nand do not retry the payment — a retry adds a second parked copy under a\ndifferent nonce, and confirming the mode does not release either of them.\n\nConfirmation from a messenger does not exist yet — the console is the only\nplace that acknowledgment can be given.\n\n## What changed in 0.9.8\n\n- **`sign_message` is refused outright, and these texts finally say so.** Every\n  earlier release described it as an ungated hole you had to guard against. It is\n  not a hole and not a protection: signing is an unfinished capability, and\n  parking a signature for approval is planned and not built. Live acceptance of\n  0.9.7 asked the wallet and got a refusal; nine texts had said otherwise.\n\n## What changed in 0.9.7\n\n- **The wallet states what it does not promise.** A `## Legal` section below, and\n  a full [DISCLAIMER](https://github.com/rustok-org/mcp/blob/main/DISCLAIMER.md)\n  that names the limit of every safeguard — starting with the one easiest to read\n  as absolute: autonomous mode sends without asking once confirmed.\n\n## What changed in 0.9.5\n\n- **Gas limits now carry headroom.** A limit set to exactly the estimate turned\n  any drift between estimating and executing into a burnt fee — a contract call\n  could pay its gas and do nothing. Plain transfers were never affected.\n- **ERC-20 tokens are documented at last** (see below). The wallet has been able\n  to report registered tokens since 0.9.4, but nothing here said so, and an\n  unregistered token reads exactly like an absent one.\n- **`rustok connect --force` names what it is about to drop** instead of quietly\n  rebuilding the registration from the current shell.\n\n## Prerequisites\n\n- **Podman** (recommended) or **Docker**. **cosign is optional** — the installer\n  pulls the image **by digest** (you get exactly those bytes or nothing), and\n  uses cosign, when it is present and runnable, to verify *who built* it\n  (provenance). A missing or broken cosign is reported and skipped, not treated\n  as a failure; a working cosign that disagrees still stops the install. Use\n  cosign 3+ if you install it — 2.x cannot read our signatures.\n- An Ethereum RPC URL (an Alchemy key URL is best; a public RPC works for testing).\n\n## One-time onboarding (the user does this in their own terminal, once)\n\nThree commands, in a **terminal the agent cannot see** — the full guide is\n[docs/INSTALL.md](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md).\n\n**1. Install the `rustok` command.** Fetch the installer to a file, read that\nfile, then run **that same file** — what you read is exactly what runs. This is a\nwallet: fetching a script straight into a shell means running code you never saw,\nand one look costs less than that trade.\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.10.0/scripts/install.sh -o install.sh\nless install.sh      # ~321 lines of POSIX sh\nsh install.sh\n```\n\nIt pulls the wallet image **by digest** (those bytes or nothing) and verifies who\nbuilt it with cosign when cosign is available.\n\n<details>\n<summary>The one-liner, if you have already read the script</summary>\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.10.0/scripts/install.sh | sh\n```\n\nPiping to a shell runs whatever the URL serves at that moment, unreviewed. The\ntag pins a *version*, not the bytes — the identities bound to exact bytes live\n**inside** the script (the image digest and the shim's commit SHA). Fine once you\nhave read it; not the way to meet it.\n</details>\n\n**2. Create the wallet** — the user chooses a 6-digit approval PIN; it prints the\n12-word phrase ONCE:\n\n```bash\nrustok init\n```\n\n**3. Register this wallet with the agent client:**\n\n```bash\nrustok connect claude\n```\n\n`rustok init` asks the user to choose a **6-digit approval PIN** (typed twice) —\nthe one code they will ever enter: it unlocks the console session and confirms\npayments. The keyring password that encrypts the keystore is generated by `init`\nitself and kept in the engine's secret store; the user never sees or types it,\nand it never reaches shell history, `inspect` or any config file. `init` prints\nexactly one thing, once: the **12-word recovery phrase**.\n\nThe 12 words are the only backup — write them down offline; the wallet does not\nstore them. Recovery is `rustok restore` (or importing the words into any standard\nBIP-39 wallet — same address). A copy of the wallet volume by itself is **not** a\nbackup: the password that opens it lives outside the volume and is not something\nthe user knows. If the PIN is forgotten, `rustok set-pin` lets them choose a new\none — the old PIN is not needed.\n\n> **Rule of two windows:** never run `rustok init`, `rustok restore`,\n> `rustok set-pin` or the approval console through an agent shell/command — the\n> seed and PIN would leak into the agent's context. These belong only in the\n> user's own terminal (window 2). Do not ask the user for their PIN or their\n> phrase in this chat, ever.\n\n## How the agent runs the wallet\n\n`rustok connect claude` writes this registration for the user, so normally none of\nit is typed by hand. It is reproduced here as the reference for what a correct\nsetup looks like — and for setups built without the shim.\n\nThe MCP client launches the image over stdio (keys stay local). **Never put the\nkeyring password in the MCP config or shell history.** On podman, store it once in\nthe secret store; on docker, keep it in a private `0600` file and pass its *path*:\n\n```bash\n# One-time (podman): the value never touches history, inspect or configs.\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" | podman secret create rustok-keyring-claude -\nunset pw\n\npodman run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  --secret rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000 \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.10.0\n```\n\n```bash\n# Docker variant: a 0600 file + RUSTOK_KEYRING_PASSWORD_FILE (path, not value).\numask 077\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" > ~/.rustok-keyring-pass\nunset pw\n\ndocker run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  -v ~/.rustok-keyring-pass:/run/keyring-pass:ro \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/keyring-pass \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.10.0\n```\n\n> Legacy `--env-file` delivery still works but is deprecated: the value lands in\n> `inspect`, and quotes inside an env-file become part of the password (a silent\n> unlock failure). Migrate to the secret / `_FILE` delivery above.\n\n> **Labels, not `--name`:** the agent launches this itself, and a fixed name\n> collides with health probes / a second `mcp list`. The `rustok.agent` sub-label\n> also lets a second agent run its **own** wallet (own volume) alongside.\n\n> The container automatically mints an ephemeral `RUSTOK_MCP_API_KEY` for the\n> loopback gateway↔mcp hop, so no API key configuration is needed for stdio use.\n> Set `RUSTOK_MCP_API_KEY` yourself **only** when exposing the gateway over a\n> network (not the default stdio setup).\n\nWhen the agent asks the user to approve a transaction, the user opens the\nconsole in a **second terminal** (window 2), never through the agent session:\n\n```bash\nrustok console\n```\n\nWithout the shim, the container runs under an auto-generated name (labels, not\n`--name`), so it is found by label:\n\n```bash\ndocker exec -it \"$(docker ps -q --filter label=rustok=wallet --filter label=rustok.agent=claude)\" rustok-console\n```\n\nThe console shows the decoded transaction from the wallet core and waits for\n`y/N` (high-risk items also ask for the per-transaction PIN).\n\nFor **Claude Desktop / Cursor** (stdio MCP), this is the entry `rustok connect`\nwrites — or that the user adds by hand to the MCP config. The keyring\npassword is delivered by the podman secret (or the docker `_FILE` mount) above,\n**never in this config file** — only the non-secret RPC URL lives here:\n\n```json\n{\n  \"mcpServers\": {\n    \"rustok\": {\n      \"command\": \"podman\",\n      \"args\": [\"run\", \"-i\", \"--rm\",\n               \"--label\", \"rustok=wallet\", \"--label\", \"rustok.agent=claude\",\n               \"-v\", \"rustok-wallet-tui:/data\",\n               \"--secret\", \"rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000\",\n               \"-e\", \"RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude\",\n               \"-e\", \"RUSTOK_ALLOWED_CHAINS=1,8453\",\n               \"-e\", \"RUSTOK_RPC_URLS_1\",\n               \"ghcr.io/rustok-org/rustok-wallet-tui:v0.10.0\"],\n      \"env\": {\n        \"RUSTOK_RPC_URLS_1\": \"https://your-rpc\"\n      }\n    }\n  }\n}\n```\n\n## Why Rustok exists\n\nRustok gives an AI agent a wallet of its own — self-custody, no middleman — so agents can begin\nto take part in the economy directly: weighing what's worth paying for, covering the compute,\ndata, and tools they rely on, and in time commissioning and paying the people who help them.\n\n## Tools\n\nThe stdio wallet image is process-trusted and exposes **all** tools by default.\nTo run a restricted agent, set `RUSTOK_MCP_CAPABILITIES` to a subset\n(`read_wallet` / `preview_tx` / `execute_tx`) — e.g. `read_wallet` for read-only.\nThe ceiling is enforced by the gateway, on the path every request takes: it\ncovers the MCP tools below **and** the HTTP routes behind them, so a session\ncannot reach past its capabilities by calling the gateway directly. In releases\nbefore 0.9.0 the ceiling was checked in the MCP layer only, which left every\nroute reachable beside it: the core refused signing for its own unrelated\nreasons, but a session narrowed away from `read_wallet` still read the wallet\naddress and every balance. A client may narrow its own session further in\n`initialize`, and can never widen it.\n\n| Tool | Capability | What it does |\n|------|-----------|--------------|\n| `get_wallet_context` | read_wallet | Active wallet address, the assets it holds (native coin + registered tokens), the assets it could not read, allowed chains |\n| `get_balances` | read_wallet | Balances of the active wallet — one row per asset, with `balance_formatted` to show and `token_address` to tell two same-named tokens apart — or the native balance of `{address, chain_id}` |\n| `get_positions` | read_wallet | DeFi positions — Aave v3 (collateral/debt/health factor/LTV) + ERC-4626 vaults; optional `{address}` |\n| `preview_transaction` | preview_tx | Preview any transaction `{to, value, chain_id, data?}` → decoded call (who/what is authorized), pre-sign simulation (revert check), gas, risk level |\n| `execute_transaction` | execute_tx | Submit a previewed transaction `{preview_id}` — parked for human approval on a supervised wallet, released by the core on one whose owner confirmed autonomous mode; a `pending` result carries `next_step` for the human |\n| `get_execution_status` | execute_tx | Poll a parked execution `{preview_id}` → `pending` / `executed` (+`tx_hash`) / `denied` / `expired` / `failed` (+`error_reason`), with the `not_after_unix` deadline. **`executed` means broadcast, not on-chain success** — see below |\n| `sign_message` | execute_tx | **Refused outright** in every mode — signature parking is planned, not built. The tool exists and always answers with a policy refusal (see \"What's protected\"). |\n\n### ERC-20 tokens are opt-in — an empty list is not an empty wallet\n\nThe wallet reports the tokens the **user registered**, and never goes looking for\nothers. A wallet holding USDC shows no USDC until USDC is registered on that\nchain:\n\n```bash\n-e RUSTOK_TOKENS_1=\"USDC:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48:6\"\n-e RUSTOK_TOKENS_8453=\"USDC:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913:6\"\n```\n\n`SYMBOL:ADDRESS:DECIMALS`, comma-separated, one variable per chain, and the chain\nmust be listed in `RUSTOK_ALLOWED_CHAINS`. A malformed entry, a duplicate address\non one chain, or an unknown chain **fails startup** naming the chain — a\nhalf-loaded registry is worse than none. Symbol and decimals are taken from the\nuser, not read from the contract: get the decimals wrong and the wallet will show\na wrong amount confidently.\n\n**What this means for you, the agent:** before telling the user they hold none of\na token, say that it may simply not be registered. Reading an empty list as an\nempty wallet is the likeliest way to be wrong here — and it has already happened.\n\n## Behavioral guidelines\n\n1. **Always `preview_transaction` first** and show its decoded call + simulation (revert check) + risk level so the user gives informed approval.\n2. **The money path is preview → summary card → `execute_transaction` → human.**\n   `execute_transaction` only parks the transaction (`state: \"pending\"`) — the user\n   releases it in a separate terminal window by running `rustok console` (see\n   the onboarding above). Never offer to run the console command yourself\n   and never ask the user to paste the approval PIN into this chat.\n3. **`executed` means the transaction was broadcast, not that it succeeded.**\n   The wallet reports the hash the moment the network accepted the transaction\n   for inclusion; a transaction that reverts on-chain still costs its gas and\n   still reads as `executed` here. Verify the receipt independently before\n   telling the user their swap or approval went through — an explorer, or\n   `eth_getTransactionReceipt` where `status` must be `0x1`.\n4. **Poll `get_execution_status` reasonably**: when the user asks, or every ~15–30\n   seconds until the `not_after_unix` deadline (if it is `null` — only on request).\n   Stop on any terminal state: `executed`, `denied`, `expired`, `failed`. A\n   `denied` outcome is the human's answer — do not re-submit the same transaction;\n   a not-found error means the id is no longer retained — stop polling.\n5. **Surface what the preview decoded** (who/what is authorized, amount, revert check, estimated cost, risk level) before the user acts on it.\n6. **Use `get_wallet_context` first** so you don't hallucinate balances or chains.\n7. If a tool needs a capability the session lacks, it returns an authorization\n   error — explain that to the user rather than retrying.\n8. If the wallet is unreachable, tell the user the wallet container/onboarding may\n   not be set up (see onboarding above).\n\n## Legal\n\nProvided **as is**, without warranty of any kind, under the MIT-0 license.\n**What an agent does with this wallet is not an act of the authors:** the agent\ndriving it is third-party software whose output is unpredictable and may be\ninaccurate, incorrect, or undesirable, and evaluating each proposed transaction\nbefore approving it is the user's exclusive responsibility. Nothing this wallet\nor the agent driving it produces is investment, accounting, legal, or tax advice.\nSending funds is gated at the console **unless autonomous mode was confirmed**;\n**`sign_message` is refused outright** in every mode. The risk of loss is\nsubstantial and the user assumes all of it.\n\nFull terms, and every safeguard's limit named:\n<https://github.com/rustok-org/mcp/blob/main/DISCLAIMER.md>\n\nFile v0.10.0:_meta.json\n\n{\n  \"ownerId\": \"kn783xqj8cgxz5m78mszfj7x9d81x8f3\",\n  \"slug\": \"wallet\",\n  \"version\": \"0.10.0\",\n  \"publishedAt\": 1786883494796\n}\n\nFile v0.10.0:skill-card.md\n\n## Description:\n\nRustok Agentic Wallet is a self-custody Ethereum wallet skill that lets an agent read wallet state, preview transactions, and request console-gated on-chain sends while keys stay local.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[rustok](https://clawhub.ai/user/rustok)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and external users use this skill to connect an agent to a local Ethereum wallet for balance and DeFi position awareness, transaction previews, and payment workflows. It is suited to users who understand self-custody and want wallet operations mediated through local container tooling and a separate approval console.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can be configured so an agent moves real funds without per-transaction approval and without built-in spending limits.\n\nMitigation: Use supervised or read-only capability settings unless autonomous payments are intentional, and keep only funds the user is prepared to risk in the wallet.\n\nRisk: Agent-controlled shell access or exposed gateway access can undermine the intended wallet approval boundary.\n\nMitigation: Do not expose the gateway over a network, restrict allowed chains and tokens, and never run the approval console, seed phrase, or PIN through an agent-controlled shell.\n\n## Reference(s):\n\n- [Rustok MCP repository](https://github.com/rustok-org/mcp)\n- [Installation guide](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md)\n- [Wallet caveats](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md)\n- [ClawHub skill page](https://clawhub.ai/rustok/skills/wallet)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with inline shell commands and JSON configuration examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include wallet status summaries, transaction preview details, approval guidance, and container setup commands.]\n\n## Skill Version(s):\n\n0.10.0 (source: frontmatter, claw.json, 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.10.0:claw.json\n\n{\n  \"name\": \"rustok-wallet-tui\",\n  \"version\": \"0.10.0\",\n  \"description\": \"Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions and sign messages. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is refused outright, in every mode. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\",\n  \"author\": \"rustok-org\",\n  \"license\": \"MIT-0\",\n  \"permissions\": [\n    \"network\"\n  ],\n  \"entry\": \"SKILL.md\",\n  \"tags\": [\n    \"crypto\",\n    \"ethereum\",\n    \"wallet\",\n    \"defi\",\n    \"agent-wallet\",\n    \"mcp\",\n    \"self-custody\"\n  ],\n  \"minOpenClawVersion\": \"0.8.0\",\n  \"homepage\": \"https://github.com/rustok-org/mcp\"\n}\n\nArchive v0.9.8: 4 files, 10634 bytes\n\nFiles: claw.json (1015b), skill-card.md (2952b), SKILL.md (19190b), _meta.json (125b)\n\nFile v0.9.8:SKILL.md\n\n---\nname: rustok-wallet-tui\ndescription: Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions and sign messages. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is refused outright, in every mode. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\nversion: 0.9.8\nmetadata:\n  openclaw:\n    emoji: \"🦀\"\n    homepage: https://github.com/rustok-org/mcp\n---\n\n# rustok-wallet-tui\n\n> **License note:** this OpenClaw skill package (`skills/rustok-wallet-tui/`) is MIT-0\n> per ClawHub requirements. The Rustok wallet core itself is proprietary; only the\n> compiled binary image is distributed.\n\nYou are connected to a **self-custody** Ethereum agent wallet that runs entirely\non the user's machine as a single Docker image (`ghcr.io/rustok-org/rustok-wallet-tui`).\nThe container runs the wallet core + gateway and speaks MCP over **stdio**; the\nprivate keys live only in the user's local Docker volume and never leave it.\n\n> ⚠️ **Self-custody, real funds, your risk.** This wallet has **no hard-coded\n> spending limits or budgets** — the user consciously accepts that funds sent to\n> the agent wallet are at risk. txguard still flags risky transactions, but it\n> does not block them. All supported chains the user enables are live (incl.\n> Ethereum mainnet). Always preview before executing and show the user the details.\n\n## What's protected — and what isn't (be honest with the user)\n\nThe wallet's guarantee is narrow and specific. State it plainly; do not oversell it.\n\nThe full list of boundaries — password delivery, updates, what we do not verify at\nall — lives in [docs/CAVEATS.md](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md).\n\n| | |\n|---|---|\n| **Protected** | Private keys stay in the user's **local Docker volume** and never leave the machine. **Sending funds on-chain** (`execute_transaction`) is gated in a **separate console window** (`rustok console`, opened by the user — see below): parked for the user's approval, with a PIN for high-risk items — unless the user has confirmed **autonomous mode** there, a confirmation only they can give, once per wallet. |\n| **Refused, not gated** | `sign_message` (EIP-191) is **refused outright** — in every mode, autonomous included. The console never sees a signature request, because signing does not happen at all: parking a signature for approval (`kind:sign`) is planned and not built. A tool that is listed and always refuses is neither a capability to rely on nor a hole to fear. Tell the user that rather than letting them plan around a signature. |\n| **Outside the model** | An agent with **shell / `docker exec` access to the container** can read the gateway key and reach the full signing surface (including EIP-712 permits — a classic drain). That is why the console is a **separate window, not an agent command**. Trusting your own agent is the user's call, the same as never pasting a seed phrase into an untrusted tool. |\n\n**Never claim** the agent (or a prompt-injected agent) \"cannot move funds.\" What is\ntrue: keys stay local, and **on-chain sends** are human-gated in the console.\n\n### Autonomous mode, and why a send may park once\n\nA wallet can be in **autonomous** mode, in which it sends without asking each\ntime. That only happens after a human has confirmed the mode **in the console**:\npress **`c`**, enter the PIN, once per wallet. The agent cannot give that\nconfirmation, and neither can an environment variable or a launch flag.\n\nUntil it is confirmed, an autonomous wallet **parks every send** exactly like a\nsupervised one. The console shows this on every screen and offers the\nconfirmation on the Dashboard.\n\n**If a send parks unexpectedly, this is the first thing to check, and the honest\nthing to tell the user:** the wallet is autonomous but unconfirmed, and one\nconfirmation in the console clears it for good. Do not describe it as an error\nand do not retry the payment — a retry adds a second parked copy under a\ndifferent nonce, and confirming the mode does not release either of them.\n\nConfirmation from a messenger does not exist yet — the console is the only\nplace that acknowledgment can be given.\n\n## What changed in 0.9.8\n\n- **`sign_message` is refused outright, and these texts finally say so.** Every\n  earlier release described it as an ungated hole you had to guard against. It is\n  not a hole and not a protection: signing is an unfinished capability, and\n  parking a signature for approval is planned and not built. Live acceptance of\n  0.9.7 asked the wallet and got a refusal; nine texts had said otherwise.\n\n## What changed in 0.9.7\n\n- **The wallet states what it does not promise.** A `## Legal` section below, and\n  a full [DISCLAIMER](https://github.com/rustok-org/mcp/blob/main/DISCLAIMER.md)\n  that names the limit of every safeguard — starting with the one easiest to read\n  as absolute: autonomous mode sends without asking once confirmed.\n\n## What changed in 0.9.5\n\n- **Gas limits now carry headroom.** A limit set to exactly the estimate turned\n  any drift between estimating and executing into a burnt fee — a contract call\n  could pay its gas and do nothing. Plain transfers were never affected.\n- **ERC-20 tokens are documented at last** (see below). The wallet has been able\n  to report registered tokens since 0.9.4, but nothing here said so, and an\n  unregistered token reads exactly like an absent one.\n- **`rustok connect --force` names what it is about to drop** instead of quietly\n  rebuilding the registration from the current shell.\n\n## Prerequisites\n\n- **Podman** (recommended) or **Docker**. **cosign is optional** — the installer\n  pulls the image **by digest** (you get exactly those bytes or nothing), and\n  uses cosign, when it is present and runnable, to verify *who built* it\n  (provenance). A missing or broken cosign is reported and skipped, not treated\n  as a failure; a working cosign that disagrees still stops the install. Use\n  cosign 3+ if you install it — 2.x cannot read our signatures.\n- An Ethereum RPC URL (an Alchemy key URL is best; a public RPC works for testing).\n\n## One-time onboarding (the user does this in their own terminal, once)\n\nThree commands, in a **terminal the agent cannot see** — the full guide is\n[docs/INSTALL.md](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md).\n\n**1. Install the `rustok` command.** Fetch the installer to a file, read that\nfile, then run **that same file** — what you read is exactly what runs. This is a\nwallet: fetching a script straight into a shell means running code you never saw,\nand one look costs less than that trade.\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.9.8/scripts/install.sh -o install.sh\nless install.sh      # ~321 lines of POSIX sh\nsh install.sh\n```\n\nIt pulls the wallet image **by digest** (those bytes or nothing) and verifies who\nbuilt it with cosign when cosign is available.\n\n<details>\n<summary>The one-liner, if you have already read the script</summary>\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.9.8/scripts/install.sh | sh\n```\n\nPiping to a shell runs whatever the URL serves at that moment, unreviewed. The\ntag pins a *version*, not the bytes — the identities bound to exact bytes live\n**inside** the script (the image digest and the shim's commit SHA). Fine once you\nhave read it; not the way to meet it.\n</details>\n\n**2. Create the wallet** — prints the 12-word phrase and the approval PIN ONCE:\n\n```bash\nrustok init\n```\n\n**3. Register this wallet with the agent client:**\n\n```bash\nrustok connect claude\n```\n\n`rustok init` asks for a keyring password and stores it in the engine's secret\nstore, so it never reaches shell history, `inspect` or any config file. It prints\ntwo things exactly once:\n\n- the **12-word recovery phrase**;\n- the **6-digit approval PIN** — required for every high-risk approval and for\n  unlocking the console session.\n\nWrite both down offline. Recovery = the 12 words (importable into any standard\nwallet) or the wallet volume + password. If the PIN is lost, reset it in the\nrunning wallet with `core-server set-pin` (needs the keyring password and a real\nterminal).\n\n> **Rule of two windows:** never run `rustok init` or the approval console\n> through an agent shell/command — the seed and PIN would leak into the agent's\n> context. These belong only in the user's own terminal (window 2).\n\n## How the agent runs the wallet\n\n`rustok connect claude` writes this registration for the user, so normally none of\nit is typed by hand. It is reproduced here as the reference for what a correct\nsetup looks like — and for setups built without the shim.\n\nThe MCP client launches the image over stdio (keys stay local). **Never put the\nkeyring password in the MCP config or shell history.** On podman, store it once in\nthe secret store; on docker, keep it in a private `0600` file and pass its *path*:\n\n```bash\n# One-time (podman): the value never touches history, inspect or configs.\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" | podman secret create rustok-keyring-claude -\nunset pw\n\npodman run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  --secret rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000 \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.9.8\n```\n\n```bash\n# Docker variant: a 0600 file + RUSTOK_KEYRING_PASSWORD_FILE (path, not value).\numask 077\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" > ~/.rustok-keyring-pass\nunset pw\n\ndocker run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  -v ~/.rustok-keyring-pass:/run/keyring-pass:ro \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/keyring-pass \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.9.8\n```\n\n> Legacy `--env-file` delivery still works but is deprecated: the value lands in\n> `inspect`, and quotes inside an env-file become part of the password (a silent\n> unlock failure). Migrate to the secret / `_FILE` delivery above.\n\n> **Labels, not `--name`:** the agent launches this itself, and a fixed name\n> collides with health probes / a second `mcp list`. The `rustok.agent` sub-label\n> also lets a second agent run its **own** wallet (own volume) alongside.\n\n> The container automatically mints an ephemeral `RUSTOK_MCP_API_KEY` for the\n> loopback gateway↔mcp hop, so no API key configuration is needed for stdio use.\n> Set `RUSTOK_MCP_API_KEY` yourself **only** when exposing the gateway over a\n> network (not the default stdio setup).\n\nWhen the agent asks the user to approve a transaction, the user opens the\nconsole in a **second terminal** (window 2), never through the agent session:\n\n```bash\nrustok console\n```\n\nWithout the shim, the container runs under an auto-generated name (labels, not\n`--name`), so it is found by label:\n\n```bash\ndocker exec -it \"$(docker ps -q --filter label=rustok=wallet --filter label=rustok.agent=claude)\" rustok-console\n```\n\nThe console shows the decoded transaction from the wallet core and waits for\n`y/N` (high-risk items also ask for the per-transaction PIN).\n\nFor **Claude Desktop / Cursor** (stdio MCP), this is the entry `rustok connect`\nwrites — or that the user adds by hand to the MCP config. The keyring\npassword is delivered by the podman secret (or the docker `_FILE` mount) above,\n**never in this config file** — only the non-secret RPC URL lives here:\n\n```json\n{\n  \"mcpServers\": {\n    \"rustok\": {\n      \"command\": \"podman\",\n      \"args\": [\"run\", \"-i\", \"--rm\",\n               \"--label\", \"rustok=wallet\", \"--label\", \"rustok.agent=claude\",\n               \"-v\", \"rustok-wallet-tui:/data\",\n               \"--secret\", \"rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000\",\n               \"-e\", \"RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude\",\n               \"-e\", \"RUSTOK_ALLOWED_CHAINS=1,8453\",\n               \"-e\", \"RUSTOK_RPC_URLS_1\",\n               \"ghcr.io/rustok-org/rustok-wallet-tui:v0.9.8\"],\n      \"env\": {\n        \"RUSTOK_RPC_URLS_1\": \"https://your-rpc\"\n      }\n    }\n  }\n}\n```\n\n## Why Rustok exists\n\nRustok gives an AI agent a wallet of its own — self-custody, no middleman — so agents can begin\nto take part in the economy directly: weighing what's worth paying for, covering the compute,\ndata, and tools they rely on, and in time commissioning and paying the people who help them.\n\n## Tools\n\nThe stdio wallet image is process-trusted and exposes **all** tools by default.\nTo run a restricted agent, set `RUSTOK_MCP_CAPABILITIES` to a subset\n(`read_wallet` / `preview_tx` / `execute_tx`) — e.g. `read_wallet` for read-only.\nThe ceiling is enforced by the gateway, on the path every request takes: it\ncovers the MCP tools below **and** the HTTP routes behind them, so a session\ncannot reach past its capabilities by calling the gateway directly. In releases\nbefore 0.9.0 the ceiling was checked in the MCP layer only, which left every\nroute reachable beside it: the core refused signing for its own unrelated\nreasons, but a session narrowed away from `read_wallet` still read the wallet\naddress and every balance. A client may narrow its own session further in\n`initialize`, and can never widen it.\n\n| Tool | Capability | What it does |\n|------|-----------|--------------|\n| `get_wallet_context` | read_wallet | Active wallet address, the assets it holds (native coin + registered tokens), the assets it could not read, allowed chains |\n| `get_balances` | read_wallet | Balances of the active wallet — one row per asset, with `balance_formatted` to show and `token_address` to tell two same-named tokens apart — or the native balance of `{address, chain_id}` |\n| `get_positions` | read_wallet | DeFi positions — Aave v3 (collateral/debt/health factor/LTV) + ERC-4626 vaults; optional `{address}` |\n| `preview_transaction` | preview_tx | Preview any transaction `{to, value, chain_id, data?}` → decoded call (who/what is authorized), pre-sign simulation (revert check), gas, risk level |\n| `execute_transaction` | execute_tx | Submit a previewed transaction `{preview_id}` — parked for human approval on a supervised wallet, released by the core on one whose owner confirmed autonomous mode; a `pending` result carries `next_step` for the human |\n| `get_execution_status` | execute_tx | Poll a parked execution `{preview_id}` → `pending` / `executed` (+`tx_hash`) / `denied` / `expired` / `failed` (+`error_reason`), with the `not_after_unix` deadline. **`executed` means broadcast, not on-chain success** — see below |\n| `sign_message` | execute_tx | **Refused outright** in every mode — signature parking is planned, not built. The tool exists and always answers with a policy refusal (see \"What's protected\"). |\n\n### ERC-20 tokens are opt-in — an empty list is not an empty wallet\n\nThe wallet reports the tokens the **user registered**, and never goes looking for\nothers. A wallet holding USDC shows no USDC until USDC is registered on that\nchain:\n\n```bash\n-e RUSTOK_TOKENS_1=\"USDC:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48:6\"\n-e RUSTOK_TOKENS_8453=\"USDC:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913:6\"\n```\n\n`SYMBOL:ADDRESS:DECIMALS`, comma-separated, one variable per chain, and the chain\nmust be listed in `RUSTOK_ALLOWED_CHAINS`. A malformed entry, a duplicate address\non one chain, or an unknown chain **fails startup** naming the chain — a\nhalf-loaded registry is worse than none. Symbol and decimals are taken from the\nuser, not read from the contract: get the decimals wrong and the wallet will show\na wrong amount confidently.\n\n**What this means for you, the agent:** before telling the user they hold none of\na token, say that it may simply not be registered. Reading an empty list as an\nempty wallet is the likeliest way to be wrong here — and it has already happened.\n\n## Behavioral guidelines\n\n1. **Always `preview_transaction` first** and show its decoded call + simulation (revert check) + risk level so the user gives informed approval.\n2. **The money path is preview → summary card → `execute_transaction` → human.**\n   `execute_transaction` only parks the transaction (`state: \"pending\"`) — the user\n   releases it in a separate terminal window by running `rustok console` (see\n   the onboarding above). Never offer to run the console command yourself\n   and never ask the user to paste the approval PIN into this chat.\n3. **`executed` means the transaction was broadcast, not that it succeeded.**\n   The wallet reports the hash the moment the network accepted the transaction\n   for inclusion; a transaction that reverts on-chain still costs its gas and\n   still reads as `executed` here. Verify the receipt independently before\n   telling the user their swap or approval went through — an explorer, or\n   `eth_getTransactionReceipt` where `status` must be `0x1`.\n4. **Poll `get_execution_status` reasonably**: when the user asks, or every ~15–30\n   seconds until the `not_after_unix` deadline (if it is `null` — only on request).\n   Stop on any terminal state: `executed`, `denied`, `expired`, `failed`. A\n   `denied` outcome is the human's answer — do not re-submit the same transaction;\n   a not-found error means the id is no longer retained — stop polling.\n5. **Surface what the preview decoded** (who/what is authorized, amount, revert check, estimated cost, risk level) before the user acts on it.\n6. **Use `get_wallet_context` first** so you don't hallucinate balances or chains.\n7. If a tool needs a capability the session lacks, it returns an authorization\n   error — explain that to the user rather than retrying.\n8. If the wallet is unreachable, tell the user the wallet container/onboarding may\n   not be set up (see onboarding above).\n\n## Legal\n\nProvided **as is**, without warranty of any kind, under the MIT-0 license.\n**What an agent does with this wallet is not an act of the authors:** the agent\ndriving it is third-party software whose output is unpredictable and may be\ninaccurate, incorrect, or undesirable, and evaluating each proposed transaction\nbefore approving it is the user's exclusive responsibility. Nothing this wallet\nor the agent driving it produces is investment, accounting, legal, or tax advice.\nSending funds is gated at the console **unless autonomous mode was confirmed**;\n**`sign_message` is refused outright** in every mode. The risk of loss is\nsubstantial and the user assumes all of it.\n\nFull terms, and every safeguard's limit named:\n<https://github.com/rustok-org/mcp/blob/main/DISCLAIMER.md>\n\nFile v0.9.8:_meta.json\n\n{\n  \"ownerId\": \"kn783xqj8cgxz5m78mszfj7x9d81x8f3\",\n  \"slug\": \"wallet\",\n  \"version\": \"0.9.8\",\n  \"publishedAt\": 1786558342804\n}\n\nFile v0.9.8:skill-card.md\n\n## Description:\n\nSelf-custody Ethereum agent wallet that runs locally as an MCP container, keeps private keys on the user's machine, reads wallet and DeFi context, previews transactions, and gates on-chain sends through a separate approval console.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[rustok](https://clawhub.ai/user/rustok)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to let an agent inspect a local Ethereum wallet, review balances and DeFi positions, preview transactions, and submit on-chain transactions that require explicit approval unless autonomous mode has been confirmed.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill connects an agent to a real-money self-custody Ethereum wallet, and transactions can send funds after execution is enabled or autonomous mode is confirmed.\n\nMitigation: Install only for wallets funded within the user's risk tolerance, prefer read-only or preview-only capabilities until execution is needed, preview every transaction, and avoid autonomous mode unless the wallet holds only funds the user is willing to risk.\n\nRisk: Wallet secrets, seed phrases, keyring passwords, and approval PINs are sensitive local credentials that can be exposed if handled inside the agent session.\n\nMitigation: Keep seed phrases and PINs out of agent chats, use Podman secrets where possible, and deliver passwords through secret or file-based mechanisms rather than shell history or agent-visible configuration.\n\nRisk: An agent with shell or docker exec access to the wallet container can bypass the intended separation between chat guidance and the wallet approval surface.\n\nMitigation: Do not give the agent shell or docker exec access to the wallet container, and require approval through the separate console controlled by the user.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/rustok/skills/wallet)\n- [Rustok MCP repository](https://github.com/rustok-org/mcp)\n- [Rustok installation guide](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md)\n- [Rustok caveats](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md)\n\n## Skill Output:\n\n**Output Type(s):** [Guidance, Markdown, Shell commands, Configuration]\n\n**Output Format:** [Markdown with inline shell commands and JSON configuration examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May propose wallet tool calls and transaction review steps; users must keep secrets and approval flows outside the agent session.]\n\n## Skill Version(s):\n\n0.9.8 (source: server release metadata, SKILL.md frontmatter, claw.json)\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.9.8:claw.json\n\n{\n  \"name\": \"rustok-wallet-tui\",\n  \"version\": \"0.9.8\",\n  \"description\": \"Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions and sign messages. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is refused outright, in every mode. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\",\n  \"author\": \"rustok-org\",\n  \"license\": \"MIT-0\",\n  \"permissions\": [\n    \"network\"\n  ],\n  \"entry\": \"SKILL.md\",\n  \"tags\": [\n    \"crypto\",\n    \"ethereum\",\n    \"wallet\",\n    \"defi\",\n    \"agent-wallet\",\n    \"mcp\",\n    \"self-custody\"\n  ],\n  \"minOpenClawVersion\": \"0.8.0\",\n  \"homepage\": \"https://github.com/rustok-org/mcp\"\n}\n\nArchive v0.9.5: 4 files, 10066 bytes\n\nFiles: claw.json (1001b), skill-card.md (2984b), SKILL.md (17631b), _meta.json (125b)\n\nFile v0.9.5:SKILL.md\n\n---\nname: rustok-wallet-tui\ndescription: Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions and sign messages. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is not console-gated. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\nversion: 0.9.5\nmetadata:\n  openclaw:\n    emoji: \"🦀\"\n    homepage: https://github.com/rustok-org/mcp\n---\n\n# rustok-wallet-tui\n\n> **License note:** this OpenClaw skill package (`skills/rustok-wallet-tui/`) is MIT-0\n> per ClawHub requirements. The Rustok wallet core itself is proprietary; only the\n> compiled binary image is distributed.\n\nYou are connected to a **self-custody** Ethereum agent wallet that runs entirely\non the user's machine as a single Docker image (`ghcr.io/rustok-org/rustok-wallet-tui`).\nThe container runs the wallet core + gateway and speaks MCP over **stdio**; the\nprivate keys live only in the user's local Docker volume and never leave it.\n\n> ⚠️ **Self-custody, real funds, your risk.** This wallet has **no hard-coded\n> spending limits or budgets** — the user consciously accepts that funds sent to\n> the agent wallet are at risk. txguard still flags risky transactions, but it\n> does not block them. All supported chains the user enables are live (incl.\n> Ethereum mainnet). Always preview before executing and show the user the details.\n\n## What's protected — and what isn't (be honest with the user)\n\nThe wallet's guarantee is narrow and specific. State it plainly; do not oversell it.\n\nThe full list of boundaries — password delivery, updates, what we do not verify at\nall — lives in [docs/CAVEATS.md](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md).\n\n| | |\n|---|---|\n| **Protected** | Private keys stay in the user's **local Docker volume** and never leave the machine. **Sending funds on-chain** (`execute_transaction`) is gated in a **separate console window** (`rustok console`, opened by the user — see below): parked for the user's approval, with a PIN for high-risk items — unless the user has confirmed **autonomous mode** there, a confirmation only they can give, once per wallet. |\n| **Not gated by the console** | `sign_message` (EIP-191) returns a signature **without** console approval. The wallet refuses to sign a **raw hex blob** (which could hide a transaction, an approval, or typed data), but it **will** sign an ordinary plaintext message (e.g. a sign-in or an off-chain order). Treat message signing as unprotected: don't connect this wallet to an agent you wouldn't trust to sign a message. |\n| **Outside the model** | An agent with **shell / `docker exec` access to the container** can read the gateway key and reach the full signing surface (including EIP-712 permits — a classic drain). That is why the console is a **separate window, not an agent command**. Trusting your own agent is the user's call, the same as never pasting a seed phrase into an untrusted tool. |\n\n**Never claim** the agent (or a prompt-injected agent) \"cannot move funds.\" What is\ntrue: keys stay local, and **on-chain sends** are human-gated in the console.\n\n### Autonomous mode, and why a send may park once\n\nA wallet can be in **autonomous** mode, in which it sends without asking each\ntime. That only happens after a human has confirmed the mode **in the console**:\npress **`c`**, enter the PIN, once per wallet. The agent cannot give that\nconfirmation, and neither can an environment variable or a launch flag.\n\nUntil it is confirmed, an autonomous wallet **parks every send** exactly like a\nsupervised one. The console shows this on every screen and offers the\nconfirmation on the Dashboard.\n\n**If a send parks unexpectedly, this is the first thing to check, and the honest\nthing to tell the user:** the wallet is autonomous but unconfirmed, and one\nconfirmation in the console clears it for good. Do not describe it as an error\nand do not retry the payment — a retry adds a second parked copy under a\ndifferent nonce, and confirming the mode does not release either of them.\n\nConfirmation from a messenger does not exist yet — the console is the only\nplace that acknowledgment can be given.\n\n## What changed in 0.9.5\n\n- **Gas limits now carry headroom.** A limit set to exactly the estimate turned\n  any drift between estimating and executing into a burnt fee — a contract call\n  could pay its gas and do nothing. Plain transfers were never affected.\n- **ERC-20 tokens are documented at last** (see below). The wallet has been able\n  to report registered tokens since 0.9.4, but nothing here said so, and an\n  unregistered token reads exactly like an absent one.\n- **`rustok connect --force` names what it is about to drop** instead of quietly\n  rebuilding the registration from the current shell.\n\n## Prerequisites\n\n- **Podman** (recommended) or **Docker**. **cosign is optional** — the installer\n  pulls the image **by digest** (you get exactly those bytes or nothing), and\n  uses cosign, when it is present and runnable, to verify *who built* it\n  (provenance). A missing or broken cosign is reported and skipped, not treated\n  as a failure; a working cosign that disagrees still stops the install. Use\n  cosign 3+ if you install it — 2.x cannot read our signatures.\n- An Ethereum RPC URL (an Alchemy key URL is best; a public RPC works for testing).\n\n## One-time onboarding (the user does this in their own terminal, once)\n\nThree commands, in a **terminal the agent cannot see** — the full guide is\n[docs/INSTALL.md](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md).\n\n**1. Install the `rustok` command.** Fetch the installer to a file, read that\nfile, then run **that same file** — what you read is exactly what runs. This is a\nwallet: fetching a script straight into a shell means running code you never saw,\nand one look costs less than that trade.\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.9.5/scripts/install.sh -o install.sh\nless install.sh      # ~321 lines of POSIX sh\nsh install.sh\n```\n\nIt pulls the wallet image **by digest** (those bytes or nothing) and verifies who\nbuilt it with cosign when cosign is available.\n\n<details>\n<summary>The one-liner, if you have already read the script</summary>\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.9.5/scripts/install.sh | sh\n```\n\nPiping to a shell runs whatever the URL serves at that moment, unreviewed. The\ntag pins a *version*, not the bytes — the identities bound to exact bytes live\n**inside** the script (the image digest and the shim's commit SHA). Fine once you\nhave read it; not the way to meet it.\n</details>\n\n**2. Create the wallet** — prints the 12-word phrase and the approval PIN ONCE:\n\n```bash\nrustok init\n```\n\n**3. Register this wallet with the agent client:**\n\n```bash\nrustok connect claude\n```\n\n`rustok init` asks for a keyring password and stores it in the engine's secret\nstore, so it never reaches shell history, `inspect` or any config file. It prints\ntwo things exactly once:\n\n- the **12-word recovery phrase**;\n- the **6-digit approval PIN** — required for every high-risk approval and for\n  unlocking the console session.\n\nWrite both down offline. Recovery = the 12 words (importable into any standard\nwallet) or the wallet volume + password. If the PIN is lost, reset it in the\nrunning wallet with `core-server set-pin` (needs the keyring password and a real\nterminal).\n\n> **Rule of two windows:** never run `rustok init` or the approval console\n> through an agent shell/command — the seed and PIN would leak into the agent's\n> context. These belong only in the user's own terminal (window 2).\n\n## How the agent runs the wallet\n\n`rustok connect claude` writes this registration for the user, so normally none of\nit is typed by hand. It is reproduced here as the reference for what a correct\nsetup looks like — and for setups built without the shim.\n\nThe MCP client launches the image over stdio (keys stay local). **Never put the\nkeyring password in the MCP config or shell history.** On podman, store it once in\nthe secret store; on docker, keep it in a private `0600` file and pass its *path*:\n\n```bash\n# One-time (podman): the value never touches history, inspect or configs.\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" | podman secret create rustok-keyring-claude -\nunset pw\n\npodman run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  --secret rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000 \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.9.5\n```\n\n```bash\n# Docker variant: a 0600 file + RUSTOK_KEYRING_PASSWORD_FILE (path, not value).\numask 077\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" > ~/.rustok-keyring-pass\nunset pw\n\ndocker run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  -v ~/.rustok-keyring-pass:/run/keyring-pass:ro \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/keyring-pass \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.9.5\n```\n\n> Legacy `--env-file` delivery still works but is deprecated: the value lands in\n> `inspect`, and quotes inside an env-file become part of the password (a silent\n> unlock failure). Migrate to the secret / `_FILE` delivery above.\n\n> **Labels, not `--name`:** the agent launches this itself, and a fixed name\n> collides with health probes / a second `mcp list`. The `rustok.agent` sub-label\n> also lets a second agent run its **own** wallet (own volume) alongside.\n\n> The container automatically mints an ephemeral `RUSTOK_MCP_API_KEY` for the\n> loopback gateway↔mcp hop, so no API key configuration is needed for stdio use.\n> Set `RUSTOK_MCP_API_KEY` yourself **only** when exposing the gateway over a\n> network (not the default stdio setup).\n\nWhen the agent asks the user to approve a transaction, the user opens the\nconsole in a **second terminal** (window 2), never through the agent session:\n\n```bash\nrustok console\n```\n\nWithout the shim, the container runs under an auto-generated name (labels, not\n`--name`), so it is found by label:\n\n```bash\ndocker exec -it \"$(docker ps -q --filter label=rustok=wallet --filter label=rustok.agent=claude)\" rustok-console\n```\n\nThe console shows the decoded transaction from the wallet core and waits for\n`y/N` (high-risk items also ask for the per-transaction PIN).\n\nFor **Claude Desktop / Cursor** (stdio MCP), this is the entry `rustok connect`\nwrites — or that the user adds by hand to the MCP config. The keyring\npassword is delivered by the podman secret (or the docker `_FILE` mount) above,\n**never in this config file** — only the non-secret RPC URL lives here:\n\n```json\n{\n  \"mcpServers\": {\n    \"rustok\": {\n      \"command\": \"podman\",\n      \"args\": [\"run\", \"-i\", \"--rm\",\n               \"--label\", \"rustok=wallet\", \"--label\", \"rustok.agent=claude\",\n               \"-v\", \"rustok-wallet-tui:/data\",\n               \"--secret\", \"rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000\",\n               \"-e\", \"RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude\",\n               \"-e\", \"RUSTOK_ALLOWED_CHAINS=1,8453\",\n               \"-e\", \"RUSTOK_RPC_URLS_1\",\n               \"ghcr.io/rustok-org/rustok-wallet-tui:v0.9.5\"],\n      \"env\": {\n        \"RUSTOK_RPC_URLS_1\": \"https://your-rpc\"\n      }\n    }\n  }\n}\n```\n\n## Why Rustok exists\n\nRustok gives an AI agent a wallet of its own — self-custody, no middleman — so agents can begin\nto take part in the economy directly: weighing what's worth paying for, covering the compute,\ndata, and tools they rely on, and in time commissioning and paying the people who help them.\n\n## Tools\n\nThe stdio wallet image is process-trusted and exposes **all** tools by default.\nTo run a restricted agent, set `RUSTOK_MCP_CAPABILITIES` to a subset\n(`read_wallet` / `preview_tx` / `execute_tx`) — e.g. `read_wallet` for read-only.\nThe ceiling is enforced by the gateway, on the path every request takes: it\ncovers the MCP tools below **and** the HTTP routes behind them, so a session\ncannot reach past its capabilities by calling the gateway directly. In releases\nbefore 0.9.0 the ceiling was checked in the MCP layer only, which left every\nroute reachable beside it: the core refused signing for its own unrelated\nreasons, but a session narrowed away from `read_wallet` still read the wallet\naddress and every balance. A client may narrow its own session further in\n`initialize`, and can never widen it.\n\n| Tool | Capability | What it does |\n|------|-----------|--------------|\n| `get_wallet_context` | read_wallet | Active wallet address, the assets it holds (native coin + registered tokens), the assets it could not read, allowed chains |\n| `get_balances` | read_wallet | Balances of the active wallet — one row per asset, with `balance_formatted` to show and `token_address` to tell two same-named tokens apart — or the native balance of `{address, chain_id}` |\n| `get_positions` | read_wallet | DeFi positions — Aave v3 (collateral/debt/health factor/LTV) + ERC-4626 vaults; optional `{address}` |\n| `preview_transaction` | preview_tx | Preview any transaction `{to, value, chain_id, data?}` → decoded call (who/what is authorized), pre-sign simulation (revert check), gas, risk level |\n| `execute_transaction` | execute_tx | Submit a previewed transaction `{preview_id}` — parked for human approval on a supervised wallet, released by the core on one whose owner confirmed autonomous mode; a `pending` result carries `next_step` for the human |\n| `get_execution_status` | execute_tx | Poll a parked execution `{preview_id}` → `pending` / `executed` (+`tx_hash`) / `denied` / `expired` / `failed` (+`error_reason`), with the `not_after_unix` deadline. **`executed` means broadcast, not on-chain success** — see below |\n| `sign_message` | execute_tx | Sign a plaintext message (EIP-191). **Not console-gated** — returns a signature without the approval window; refuses raw hex blobs but signs ordinary messages (see \"What's protected\"). |\n\n### ERC-20 tokens are opt-in — an empty list is not an empty wallet\n\nThe wallet reports the tokens the **user registered**, and never goes looking for\nothers. A wallet holding USDC shows no USDC until USDC is registered on that\nchain:\n\n```bash\n-e RUSTOK_TOKENS_1=\"USDC:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48:6\"\n-e RUSTOK_TOKENS_8453=\"USDC:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913:6\"\n```\n\n`SYMBOL:ADDRESS:DECIMALS`, comma-separated, one variable per chain, and the chain\nmust be listed in `RUSTOK_ALLOWED_CHAINS`. A malformed entry, a duplicate address\non one chain, or an unknown chain **fails startup** naming the chain — a\nhalf-loaded registry is worse than none. Symbol and decimals are taken from the\nuser, not read from the contract: get the decimals wrong and the wallet will show\na wrong amount confidently.\n\n**What this means for you, the agent:** before telling the user they hold none of\na token, say that it may simply not be registered. Reading an empty list as an\nempty wallet is the likeliest way to be wrong here — and it has already happened.\n\n## Behavioral guidelines\n\n1. **Always `preview_transaction` first** and show its decoded call + simulation (revert check) + risk level so the user gives informed approval.\n2. **The money path is preview → summary card → `execute_transaction` → human.**\n   `execute_transaction` only parks the transaction (`state: \"pending\"`) — the user\n   releases it in a separate terminal window by running `rustok console` (see\n   the onboarding above). Never offer to run the console command yourself\n   and never ask the user to paste the approval PIN into this chat.\n3. **`executed` means the transaction was broadcast, not that it succeeded.**\n   The wallet reports the hash the moment the network accepted the transaction\n   for inclusion; a transaction that reverts on-chain still costs its gas and\n   still reads as `executed` here. Verify the receipt independently before\n   telling the user their swap or approval went through — an explorer, or\n   `eth_getTransactionReceipt` where `status` must be `0x1`.\n4. **Poll `get_execution_status` reasonably**: when the user asks, or every ~15–30\n   seconds until the `not_after_unix` deadline (if it is `null` — only on request).\n   Stop on any terminal state: `executed`, `denied`, `expired`, `failed`. A\n   `denied` outcome is the human's answer — do not re-submit the same transaction;\n   a not-found error means the id is no longer retained — stop polling.\n5. **Surface what the preview decoded** (who/what is authorized, amount, revert check, estimated cost, risk level) before the user acts on it.\n6. **Use `get_wallet_context` first** so you don't hallucinate balances or chains.\n7. If a tool needs a capability the session lacks, it returns an authorization\n   error — explain that to the user rather than retrying.\n8. If the wallet is unreachable, tell the user the wallet container/onboarding may\n   not be set up (see onboarding above).\n\nFile v0.9.5:_meta.json\n\n{\n  \"ownerId\": \"kn783xqj8cgxz5m78mszfj7x9d81x8f3\",\n  \"slug\": \"wallet\",\n  \"version\": \"0.9.5\",\n  \"publishedAt\": 1786534302148\n}\n\nFile v0.9.5:skill-card.md\n\n## Description:\n\nRustok Agentic Wallet is a self-custody Ethereum agent wallet that runs locally over MCP, reads wallet and DeFi context, previews transactions, executes approved transactions, and signs messages.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[rustok](https://clawhub.ai/user/rustok)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and external users use this skill to connect an AI agent to a local Ethereum wallet for balance checks, DeFi position reads, transaction previews, approved on-chain execution, and message signing.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can give an agent high-impact authority over real funds without hard spending limits.\n\nMitigation: Prefer supervised mode, keep only limited funds in the wallet, restrict capabilities to read_wallet or preview_tx unless execution is needed, and preview transactions before execution.\n\nRisk: Message signing is not gated by the separate approval console.\n\nMitigation: Use execution capability only with agents trusted to sign messages, and review signing requests as sensitive wallet actions.\n\nRisk: An agent session with Docker or shell access to the wallet container can reach sensitive wallet surfaces.\n\nMitigation: Avoid using the wallet from an agent session that also has Docker or shell access to the wallet container, and keep approval through the separate user console.\n\nRisk: Wallet setup can expose seed phrases, PINs, or keyring passwords if run through the agent session.\n\nMitigation: Run wallet initialization and the approval console only in the user's own terminal, and use Podman secrets or password-file delivery rather than chat, shell history, or config values.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/rustok/skills/wallet)\n- [Rustok repository](https://github.com/rustok-org/mcp)\n- [Install guide](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md)\n- [Caveats and security boundaries](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md)\n\n## Skill Output:\n\n**Output Type(s):** [Text, JSON, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown guidance with inline shell and JSON examples; MCP wallet tool calls return structured data such as balances, previews, execution status, transaction hashes, and signatures.]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Outputs may describe real-funds actions; transaction execution can be pending, executed, denied, expired, or failed, and executed means broadcast rather than confirmed on-chain success.]\n\n## Skill Version(s):\n\n0.9.5 (source: evidence release, SKILL.md frontmatter, claw.json)\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.9.5:claw.json\n\n{\n  \"name\": \"rustok-wallet-tui\",\n  \"version\": \"0.9.5\",\n  \"description\": \"Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions and sign messages. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is not console-gated. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\",\n  \"author\": \"rustok-org\",\n  \"license\": \"MIT-0\",\n  \"permissions\": [\n    \"network\"\n  ],\n  \"entry\": \"SKILL.md\",\n  \"tags\": [\n    \"crypto\",\n    \"ethereum\",\n    \"wallet\",\n    \"defi\",\n    \"agent-wallet\",\n    \"mcp\",\n    \"self-custody\"\n  ],\n  \"minOpenClawVersion\": \"0.8.0\",\n  \"homepage\": \"https://github.com/rustok-org/mcp\"\n}\n\nArchive v0.9.4: 4 files, 8923 bytes\n\nFiles: claw.json (1001b), skill-card.md (2691b), SKILL.md (15376b), _meta.json (125b)\n\nFile v0.9.4:SKILL.md\n\n---\nname: rustok-wallet-tui\ndescription: Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions and sign messages. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is not console-gated. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\nversion: 0.9.4\nmetadata:\n  openclaw:\n    emoji: \"🦀\"\n    homepage: https://github.com/rustok-org/mcp\n---\n\n# rustok-wallet-tui\n\n> **License note:** this OpenClaw skill package (`skills/rustok-wallet-tui/`) is MIT-0\n> per ClawHub requirements. The Rustok wallet core itself is proprietary; only the\n> compiled binary image is distributed.\n\nYou are connected to a **self-custody** Ethereum agent wallet that runs entirely\non the user's machine as a single Docker image (`ghcr.io/rustok-org/rustok-wallet-tui`).\nThe container runs the wallet core + gateway and speaks MCP over **stdio**; the\nprivate keys live only in the user's local Docker volume and never leave it.\n\n> ⚠️ **Self-custody, real funds, your risk.** This wallet has **no hard-coded\n> spending limits or budgets** — the user consciously accepts that funds sent to\n> the agent wallet are at risk. txguard still flags risky transactions, but it\n> does not block them. All supported chains the user enables are live (incl.\n> Ethereum mainnet). Always preview before executing and show the user the details.\n\n## What's protected — and what isn't (be honest with the user)\n\nThe wallet's guarantee is narrow and specific. State it plainly; do not oversell it.\n\nThe full list of boundaries — password delivery, updates, what we do not verify at\nall — lives in [docs/CAVEATS.md](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md).\n\n| | |\n|---|---|\n| **Protected** | Private keys stay in the user's **local Docker volume** and never leave the machine. **Sending funds on-chain** (`execute_transaction`) is gated in a **separate console window** (`rustok console`, opened by the user — see below): parked for the user's approval, with a PIN for high-risk items — unless the user has confirmed **autonomous mode** there, a confirmation only they can give, once per wallet. |\n| **Not gated by the console** | `sign_message` (EIP-191) returns a signature **without** console approval. The wallet refuses to sign a **raw hex blob** (which could hide a transaction, an approval, or typed data), but it **will** sign an ordinary plaintext message (e.g. a sign-in or an off-chain order). Treat message signing as unprotected: don't connect this wallet to an agent you wouldn't trust to sign a message. |\n| **Outside the model** | An agent with **shell / `docker exec` access to the container** can read the gateway key and reach the full signing surface (including EIP-712 permits — a classic drain). That is why the console is a **separate window, not an agent command**. Trusting your own agent is the user's call, the same as never pasting a seed phrase into an untrusted tool. |\n\n**Never claim** the agent (or a prompt-injected agent) \"cannot move funds.\" What is\ntrue: keys stay local, and **on-chain sends** are human-gated in the console.\n\n### Autonomous mode, and why a send may park once\n\nA wallet can be in **autonomous** mode, in which it sends without asking each\ntime. That only happens after a human has confirmed the mode **in the console**:\npress **`c`**, enter the PIN, once per wallet. The agent cannot give that\nconfirmation, and neither can an environment variable or a launch flag.\n\nUntil it is confirmed, an autonomous wallet **parks every send** exactly like a\nsupervised one. The console shows this on every screen and offers the\nconfirmation on the Dashboard.\n\n**If a send parks unexpectedly, this is the first thing to check, and the honest\nthing to tell the user:** the wallet is autonomous but unconfirmed, and one\nconfirmation in the console clears it for good. Do not describe it as an error\nand do not retry the payment — a retry adds a second parked copy under a\ndifferent nonce, and confirming the mode does not release either of them.\n\nConfirmation from a messenger is not in this release.\n\n## Prerequisites\n\n- **Podman** (recommended) or **Docker**. **cosign is optional** — the installer\n  pulls the image **by digest** (you get exactly those bytes or nothing), and\n  uses cosign, when it is present and runnable, to verify *who built* it\n  (provenance). A missing or broken cosign is reported and skipped, not treated\n  as a failure; a working cosign that disagrees still stops the install. Use\n  cosign 3+ if you install it — 2.x cannot read our signatures.\n- An Ethereum RPC URL (an Alchemy key URL is best; a public RPC works for testing).\n\n## One-time onboarding (the user does this in their own terminal, once)\n\nThree commands, in a **terminal the agent cannot see** — the full guide is\n[docs/INSTALL.md](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md).\n\n**1. Install the `rustok` command.** Fetch the installer to a file, read that\nfile, then run **that same file** — what you read is exactly what runs. This is a\nwallet: fetching a script straight into a shell means running code you never saw,\nand one look costs less than that trade.\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.9.4/scripts/install.sh -o install.sh\nless install.sh      # ~150 lines of POSIX sh\nsh install.sh\n```\n\nIt pulls the wallet image **by digest** (those bytes or nothing) and verifies who\nbuilt it with cosign when cosign is available.\n\n<details>\n<summary>The one-liner, if you have already read the script</summary>\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.9.4/scripts/install.sh | sh\n```\n\nPiping to a shell runs whatever the URL serves at that moment, unreviewed. The\ntag pins a *version*, not the bytes — the identities bound to exact bytes live\n**inside** the script (the image digest and the shim's commit SHA). Fine once you\nhave read it; not the way to meet it.\n</details>\n\n**2. Create the wallet** — prints the 12-word phrase and the approval PIN ONCE:\n\n```bash\nrustok init\n```\n\n**3. Register this wallet with the agent client:**\n\n```bash\nrustok connect claude\n```\n\n`rustok init` asks for a keyring password and stores it in the engine's secret\nstore, so it never reaches shell history, `inspect` or any config file. It prints\ntwo things exactly once:\n\n- the **12-word recovery phrase**;\n- the **6-digit approval PIN** — required for every high-risk approval and for\n  unlocking the console session.\n\nWrite both down offline. Recovery = the 12 words (importable into any standard\nwallet) or the wallet volume + password. If the PIN is lost, reset it in the\nrunning wallet with `core-server set-pin` (needs the keyring password and a real\nterminal).\n\n> **Rule of two windows:** never run `rustok init` or the approval console\n> through an agent shell/command — the seed and PIN would leak into the agent's\n> context. These belong only in the user's own terminal (window 2).\n\n## How the agent runs the wallet\n\n`rustok connect claude` writes this registration for the user, so normally none of\nit is typed by hand. It is reproduced here as the reference for what a correct\nsetup looks like — and for setups built without the shim.\n\nThe MCP client launches the image over stdio (keys stay local). **Never put the\nkeyring password in the MCP config or shell history.** On podman, store it once in\nthe secret store; on docker, keep it in a private `0600` file and pass its *path*:\n\n```bash\n# One-time (podman): the value never touches history, inspect or configs.\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" | podman secret create rustok-keyring-claude -\nunset pw\n\npodman run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  --secret rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000 \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.9.4\n```\n\n```bash\n# Docker variant: a 0600 file + RUSTOK_KEYRING_PASSWORD_FILE (path, not value).\numask 077\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" > ~/.rustok-keyring-pass\nunset pw\n\ndocker run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  -v ~/.rustok-keyring-pass:/run/keyring-pass:ro \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/keyring-pass \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.9.4\n```\n\n> Legacy `--env-file` delivery still works but is deprecated: the value lands in\n> `inspect`, and quotes inside an env-file become part of the password (a silent\n> unlock failure). Migrate to the secret / `_FILE` delivery above.\n\n> **Labels, not `--name`:** the agent launches this itself, and a fixed name\n> collides with health probes / a second `mcp list`. The `rustok.agent` sub-label\n> also lets a second agent run its **own** wallet (own volume) alongside.\n\n> The container automatically mints an ephemeral `RUSTOK_MCP_API_KEY` for the\n> loopback gateway↔mcp hop, so no API key configuration is needed for stdio use.\n> Set `RUSTOK_MCP_API_KEY` yourself **only** when exposing the gateway over a\n> network (not the default stdio setup).\n\nWhen the agent asks the user to approve a transaction, the user opens the\nconsole in a **second terminal** (window 2), never through the agent session:\n\n```bash\nrustok console\n```\n\nWithout the shim, the container runs under an auto-generated name (labels, not\n`--name`), so it is found by label:\n\n```bash\ndocker exec -it \"$(docker ps -q --filter label=rustok=wallet --filter label=rustok.agent=claude)\" rustok-console\n```\n\nThe console shows the decoded transaction from the wallet core and waits for\n`y/N` (high-risk items also ask for the per-transaction PIN).\n\nFor **Claude Desktop / Cursor** (stdio MCP), this is the entry `rustok connect`\nwrites — or that the user adds by hand to the MCP config. The keyring\npassword is delivered by the podman secret (or the docker `_FILE` mount) above,\n**never in this config file** — only the non-secret RPC URL lives here:\n\n```json\n{\n  \"mcpServers\": {\n    \"rustok\": {\n      \"command\": \"podman\",\n      \"args\": [\"run\", \"-i\", \"--rm\",\n               \"--label\", \"rustok=wallet\", \"--label\", \"rustok.agent=claude\",\n               \"-v\", \"rustok-wallet-tui:/data\",\n               \"--secret\", \"rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000\",\n               \"-e\", \"RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude\",\n               \"-e\", \"RUSTOK_ALLOWED_CHAINS=1,8453\",\n               \"-e\", \"RUSTOK_RPC_URLS_1\",\n               \"ghcr.io/rustok-org/rustok-wallet-tui:v0.9.4\"],\n      \"env\": {\n        \"RUSTOK_RPC_URLS_1\": \"https://your-rpc\"\n      }\n    }\n  }\n}\n```\n\n## Why Rustok exists\n\nRustok gives an AI agent a wallet of its own — self-custody, no middleman — so agents can begin\nto take part in the economy directly: weighing what's worth paying for, covering the compute,\ndata, and tools they rely on, and in time commissioning and paying the people who help them.\n\n## Tools\n\nThe stdio wallet image is process-trusted and exposes **all** tools by default.\nTo run a restricted agent, set `RUSTOK_MCP_CAPABILITIES` to a subset\n(`read_wallet` / `preview_tx` / `execute_tx`) — e.g. `read_wallet` for read-only.\nThe ceiling is enforced by the gateway, on the path every request takes: it\ncovers the MCP tools below **and** the HTTP routes behind them, so a session\ncannot reach past its capabilities by calling the gateway directly. Until this\nrelease it was checked in the MCP layer only, which left every route reachable\nbeside it — on this edition the core refused signing for its own unrelated\nreasons, but a session narrowed away from `read_wallet` still read the wallet\naddress and every balance. A client may narrow its own session further in\n`initialize`, and can never widen it.\n\n| Tool | Capability | What it does |\n|------|-----------|--------------|\n| `get_wallet_context` | read_wallet | Active wallet address, the assets it holds (native coin + registered tokens), the assets it could not read, allowed chains |\n| `get_balances` | read_wallet | Balances of the active wallet — one row per asset, with `balance_formatted` to show and `token_address` to tell two same-named tokens apart — or the native balance of `{address, chain_id}` |\n| `get_positions` | read_wallet | DeFi positions — Aave v3 (collateral/debt/health factor/LTV) + ERC-4626 vaults; optional `{address}` |\n| `preview_transaction` | preview_tx | Preview any transaction `{to, value, chain_id, data?}` → decoded call (who/what is authorized), pre-sign simulation (revert check), gas, risk level |\n| `execute_transaction` | execute_tx | Submit a previewed transaction `{preview_id}` — parked for human approval on a supervised wallet, released by the core on one whose owner confirmed autonomous mode; a `pending` result carries `next_step` for the human |\n| `get_execution_status` | execute_tx | Poll a parked execution `{preview_id}` → `pending` / `executed` (+`tx_hash`) / `denied` / `expired` / `failed` (+`error_reason`), with the `not_after_unix` deadline |\n| `sign_message` | execute_tx | Sign a plaintext message (EIP-191). **Not console-gated** — returns a signature without the approval window; refuses raw hex blobs but signs ordinary messages (see \"What's protected\"). |\n\n## Behavioral guidelines\n\n1. **Always `preview_transaction` first** and show its decoded call + simulation (revert check) + risk level so the user gives informed approval.\n2. **The money path is preview → summary card → `execute_transaction` → human.**\n   `execute_transaction` only parks the transaction (`state: \"pending\"`) — the user\n   releases it in a separate terminal window by running `rustok console` (see\n   the onboarding above). Never offer to run the console command yourself\n   and never ask the user to paste the approval PIN into this chat.\n3. **Poll `get_execution_status` reasonably**: when the user asks, or every ~15–30\n   seconds until the `not_after_unix` deadline (if it is `null` — only on request).\n   Stop on any terminal state: `executed`, `denied`, `expired`, `failed`. A\n   `denied` outcome is the human's answer — do not re-submit the same transaction;\n   a not-found error means the id is no longer retained — stop polling.\n4. **Surface what the preview decoded** (who/what is authorized, amount, revert check, estimated cost, risk level) before the user acts on it.\n5. **Use `get_wallet_context` first** so you don't hallucinate balances or chains.\n6. If a tool needs a capability the session lacks, it returns an authorization\n   error — explain that to the user rather than retrying.\n7. If the wallet is unreachable, tell the user the wallet container/onboarding may\n   not be set up (see onboarding above).\n\nFile v0.9.4:_meta.json\n\n{\n  \"ownerId\": \"kn783xqj8cgxz5m78mszfj7x9d81x8f3\",\n  \"slug\": \"wallet\",\n  \"version\": \"0.9.4\",\n  \"publishedAt\": 1786364313821\n}\n\nFile v0.9.4:skill-card.md\n\n## Description:\n\nRustok Agentic Wallet lets agents use a local self-custody Ethereum wallet to read wallet context, balances, and DeFi positions, preview transactions, execute approved on-chain sends, and sign messages.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[rustok](https://clawhub.ai/user/rustok)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal developers and agent users use this skill to connect an agent to a local Ethereum wallet for wallet reads, transaction previews, approved sends, and message signing while keeping custody on the user's machine.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The wallet can move real funds without per-transaction approval after autonomous mode is enabled and has no built-in spending cap.\n\nMitigation: Use supervised or read-only capabilities for normal agent use, and enable autonomous mode only when unattended transfers are an intentional, accepted risk.\n\nRisk: Secrets or approval authority can leak if the seed phrase, PIN, keyring password, or approval console are exposed through an agent chat or shell.\n\nMitigation: Enter wallet secrets and use the approval console only in a separate user-controlled terminal; prefer Podman secrets for password delivery.\n\nRisk: Message signing is not console-gated, so a trusted session can return signatures without the separate approval flow.\n\nMitigation: Use message signing only with agents the user trusts for signatures, and restrict wallet capabilities when read-only or preview-only access is sufficient.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/rustok/skills/wallet)\n- [Rustok MCP homepage](https://github.com/rustok-org/mcp)\n- [Rustok caveats](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md)\n- [Rustok install guide](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with inline shell commands and JSON configuration examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Outputs include wallet operation guidance, transaction preview summaries, status polling instructions, and setup commands; live wallet data depends on the connected wallet tools.]\n\n## Skill Version(s):\n\n0.9.4 (source: frontmatter, claw.json, server release evidence)\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.9.4:claw.json\n\n{\n  \"name\": \"rustok-wallet-tui\",\n  \"version\": \"0.9.4\",\n  \"description\": \"Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions and sign messages. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is not console-gated. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\",\n  \"author\": \"rustok-org\",\n  \"license\": \"MIT-0\",\n  \"permissions\": [\n    \"network\"\n  ],\n  \"entry\": \"SKILL.md\",\n  \"tags\": [\n    \"crypto\",\n    \"ethereum\",\n    \"wallet\",\n    \"defi\",\n    \"agent-wallet\",\n    \"mcp\",\n    \"self-custody\"\n  ],\n  \"minOpenClawVersion\": \"0.8.0\",\n  \"homepage\": \"https://github.com/rustok-org/mcp\"\n}\n\nArchive v0.9.3: 4 files, 9052 bytes\n\nFiles: claw.json (1001b), skill-card.md (3244b), SKILL.md (15294b), _meta.json (125b)\n\nFile v0.9.3:SKILL.md\n\n---\nname: rustok-wallet-tui\ndescription: Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions and sign messages. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is not console-gated. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\nversion: 0.9.3\nmetadata:\n  openclaw:\n    emoji: \"🦀\"\n    homepage: https://github.com/rustok-org/mcp\n---\n\n# rustok-wallet-tui\n\n> **License note:** this OpenClaw skill package (`skills/rustok-wallet-tui/`) is MIT-0\n> per ClawHub requirements. The Rustok wallet core itself is proprietary; only the\n> compiled binary image is distributed.\n\nYou are connected to a **self-custody** Ethereum agent wallet that runs entirely\non the user's machine as a single Docker image (`ghcr.io/rustok-org/rustok-wallet-tui`).\nThe container runs the wallet core + gateway and speaks MCP over **stdio**; the\nprivate keys live only in the user's local Docker volume and never leave it.\n\n> ⚠️ **Self-custody, real funds, your risk.** This wallet has **no hard-coded\n> spending limits or budgets** — the user consciously accepts that funds sent to\n> the agent wallet are at risk. txguard still flags risky transactions, but it\n> does not block them. All supported chains the user enables are live (incl.\n> Ethereum mainnet). Always preview before executing and show the user the details.\n\n## What's protected — and what isn't (be honest with the user)\n\nThe wallet's guarantee is narrow and specific. State it plainly; do not oversell it.\n\nThe full list of boundaries — password delivery, updates, what we do not verify at\nall — lives in [docs/CAVEATS.md](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md).\n\n| | |\n|---|---|\n| **Protected** | Private keys stay in the user's **local Docker volume** and never leave the machine. **Sending funds on-chain** (`execute_transaction`) is gated in a **separate console window** (`rustok console`, opened by the user — see below): parked for the user's approval, with a PIN for high-risk items — unless the user has confirmed **autonomous mode** there, a confirmation only they can give, once per wallet. |\n| **Not gated by the console** | `sign_message` (EIP-191) returns a signature **without** console approval. The wallet refuses to sign a **raw hex blob** (which could hide a transaction, an approval, or typed data), but it **will** sign an ordinary plaintext message (e.g. a sign-in or an off-chain order). Treat message signing as unprotected: don't connect this wallet to an agent you wouldn't trust to sign a message. |\n| **Outside the model** | An agent with **shell / `docker exec` access to the container** can read the gateway key and reach the full signing surface (including EIP-712 permits — a classic drain). That is why the console is a **separate window, not an agent command**. Trusting your own agent is the user's call, the same as never pasting a seed phrase into an untrusted tool. |\n\n**Never claim** the agent (or a prompt-injected agent) \"cannot move funds.\" What is\ntrue: keys stay local, and **on-chain sends** are human-gated in the console.\n\n### Autonomous mode, and why a send may park once\n\nA wallet can be in **autonomous** mode, in which it sends without asking each\ntime. That only happens after a human has confirmed the mode **in the console**:\npress **`c`**, enter the PIN, once per wallet. The agent cannot give that\nconfirmation, and neither can an environment variable or a launch flag.\n\nUntil it is confirmed, an autonomous wallet **parks every send** exactly like a\nsupervised one. The console shows this on every screen and offers the\nconfirmation on the Dashboard.\n\n**If a send parks unexpectedly, this is the first thing to check, and the honest\nthing to tell the user:** the wallet is autonomous but unconfirmed, and one\nconfirmation in the console clears it for good. Do not describe it as an error\nand do not retry the payment — a retry adds a second parked copy under a\ndifferent nonce, and confirming the mode does not release either of them.\n\nConfirmation from a messenger is not in this release.\n\n## Prerequisites\n\n- **Podman** (recommended) or **Docker**. **cosign is optional** — the installer\n  pulls the image **by digest** (you get exactly those bytes or nothing), and\n  uses cosign, when it is present and runnable, to verify *who built* it\n  (provenance). A missing or broken cosign is reported and skipped, not treated\n  as a failure; a working cosign that disagrees still stops the install. Use\n  cosign 3+ if you install it — 2.x cannot read our signatures.\n- An Ethereum RPC URL (an Alchemy key URL is best; a public RPC works for testing).\n\n## One-time onboarding (the user does this in their own terminal, once)\n\nThree commands, in a **terminal the agent cannot see** — the full guide is\n[docs/INSTALL.md](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md).\n\n**1. Install the `rustok` command.** Fetch the installer to a file, read that\nfile, then run **that same file** — what you read is exactly what runs. This is a\nwallet: fetching a script straight into a shell means running code you never saw,\nand one look costs less than that trade.\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.9.3/scripts/install.sh -o install.sh\nless install.sh      # ~150 lines of POSIX sh\nsh install.sh\n```\n\nIt pulls the wallet image **by digest** (those bytes or nothing) and verifies who\nbuilt it with cosign when cosign is available. The release notes for that tag\npublish the script's `sha256` if you would rather check the bytes than read them.\n\n<details>\n<summary>The one-liner, if you have already read the script</summary>\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.9.3/scripts/install.sh | sh\n```\n\nPiping to a shell runs whatever the URL serves at that moment, unreviewed. The\ntag pins a *version*, not the bytes — the identities bound to exact bytes live\n**inside** the script (the image digest and the shim's commit SHA). Fine once you\nhave read it; not the way to meet it.\n</details>\n\n**2. Create the wallet** — prints the 12-word phrase and the approval PIN ONCE:\n\n```bash\nrustok init\n```\n\n**3. Register this wallet with the agent client:**\n\n```bash\nrustok connect claude\n```\n\n`rustok init` asks for a keyring password and stores it in the engine's secret\nstore, so it never reaches shell history, `inspect` or any config file. It prints\ntwo things exactly once:\n\n- the **12-word recovery phrase**;\n- the **6-digit approval PIN** — required for every high-risk approval and for\n  unlocking the console session.\n\nWrite both down offline. Recovery = the 12 words (importable into any standard\nwallet) or the wallet volume + password. If the PIN is lost, reset it in the\nrunning wallet with `core-server set-pin` (needs the keyring password and a real\nterminal).\n\n> **Rule of two windows:** never run `rustok init` or the approval console\n> through an agent shell/command — the seed and PIN would leak into the agent's\n> context. These belong only in the user's own terminal (window 2).\n\n## How the agent runs the wallet\n\n`rustok connect claude` writes this registration for the user, so normally none of\nit is typed by hand. It is reproduced here as the reference for what a correct\nsetup looks like — and for setups built without the shim.\n\nThe MCP client launches the image over stdio (keys stay local). **Never put the\nkeyring password in the MCP config or shell history.** On podman, store it once in\nthe secret store; on docker, keep it in a private `0600` file and pass its *path*:\n\n```bash\n# One-time (podman): the value never touches history, inspect or configs.\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" | podman secret create rustok-keyring-claude -\nunset pw\n\npodman run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  --secret rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000 \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.9.3\n```\n\n```bash\n# Docker variant: a 0600 file + RUSTOK_KEYRING_PASSWORD_FILE (path, not value).\numask 077\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" > ~/.rustok-keyring-pass\nunset pw\n\ndocker run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  -v ~/.rustok-keyring-pass:/run/keyring-pass:ro \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/keyring-pass \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.9.3\n```\n\n> Legacy `--env-file` delivery still works but is deprecated: the value lands in\n> `inspect`, and quotes inside an env-file become part of the password (a silent\n> unlock failure). Migrate to the secret / `_FILE` delivery above.\n\n> **Labels, not `--name`:** the agent launches this itself, and a fixed name\n> collides with health probes / a second `mcp list`. The `rustok.agent` sub-label\n> also lets a second agent run its **own** wallet (own volume) alongside.\n\n> The container automatically mints an ephemeral `RUSTOK_MCP_API_KEY` for the\n> loopback gateway↔mcp hop, so no API key configuration is needed for stdio use.\n> Set `RUSTOK_MCP_API_KEY` yourself **only** when exposing the gateway over a\n> network (not the default stdio setup).\n\nWhen the agent asks the user to approve a transaction, the user opens the\nconsole in a **second terminal** (window 2), never through the agent session:\n\n```bash\nrustok console\n```\n\nWithout the shim, the container runs under an auto-generated name (labels, not\n`--name`), so it is found by label:\n\n```bash\ndocker exec -it \"$(docker ps -q --filter label=rustok=wallet --filter label=rustok.agent=claude)\" rustok-console\n```\n\nThe console shows the decoded transaction from the wallet core and waits for\n`y/N` (high-risk items also ask for the per-transaction PIN).\n\nFor **Claude Desktop / Cursor** (stdio MCP), this is the entry `rustok connect`\nwrites — or that the user adds by hand to the MCP config. The keyring\npassword is delivered by the podman secret (or the docker `_FILE` mount) above,\n**never in this config file** — only the non-secret RPC URL lives here:\n\n```json\n{\n  \"mcpServers\": {\n    \"rustok\": {\n      \"command\": \"podman\",\n      \"args\": [\"run\", \"-i\", \"--rm\",\n               \"--label\", \"rustok=wallet\", \"--label\", \"rustok.agent=claude\",\n               \"-v\", \"rustok-wallet-tui:/data\",\n               \"--secret\", \"rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000\",\n               \"-e\", \"RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude\",\n               \"-e\", \"RUSTOK_ALLOWED_CHAINS=1,8453\",\n               \"-e\", \"RUSTOK_RPC_URLS_1\",\n               \"ghcr.io/rustok-org/rustok-wallet-tui:v0.9.3\"],\n      \"env\": {\n        \"RUSTOK_RPC_URLS_1\": \"https://your-rpc\"\n      }\n    }\n  }\n}\n```\n\n## Why Rustok exists\n\nRustok gives an AI agent a wallet of its own — self-custody, no middleman — so agents can begin\nto take part in the economy directly: weighing what's worth paying for, covering the compute,\ndata, and tools they rely on, and in time commissioning and paying the people who help them.\n\n## Tools\n\nThe stdio wallet image is process-trusted and exposes **all** tools by default.\nTo run a restricted agent, set `RUSTOK_MCP_CAPABILITIES` to a subset\n(`read_wallet` / `preview_tx` / `execute_tx`) — e.g. `read_wallet` for read-only.\nThe ceiling is enforced by the gateway, on the path every request takes: it\ncovers the MCP tools below **and** the HTTP routes behind them, so a session\ncannot reach past its capabilities by calling the gateway directly. Until this\nrelease it was checked in the MCP layer only, which left every route reachable\nbeside it — on this edition the core refused signing for its own unrelated\nreasons, but a session narrowed away from `read_wallet` still read the wallet\naddress and every balance. A client may narrow its own session further in\n`initialize`, and can never widen it.\n\n| Tool | Capability | What it does |\n|------|-----------|--------------|\n| `get_wallet_context` | read_wallet | Active wallet address, per-chain balances, allowed chains |\n| `get_balances` | read_wallet | Token balances for the active wallet, or `{address, chain_id}` |\n| `get_positions` | read_wallet | DeFi positions — Aave v3 (collateral/debt/health factor/LTV) + ERC-4626 vaults; optional `{address}` |\n| `preview_transaction` | preview_tx | Preview any transaction `{to, value, chain_id, data?}` → decoded call (who/what is authorized), pre-sign simulation (revert check), gas, risk level |\n| `execute_transaction` | execute_tx | Submit a previewed transaction `{preview_id}` — parked for human approval on a supervised wallet, released by the core on one whose owner confirmed autonomous mode; a `pending` result carries `next_step` for the human |\n| `get_execution_status` | execute_tx | Poll a parked execution `{preview_id}` → `pending` / `executed` (+`tx_hash`) / `denied` / `expired` / `failed` (+`error_reason`), with the `not_after_unix` deadline |\n| `sign_message` | execute_tx | Sign a plaintext message (EIP-191). **Not console-gated** — returns a signature without the approval window; refuses raw hex blobs but signs ordinary messages (see \"What's protected\"). |\n\n## Behavioral guidelines\n\n1. **Always `preview_transaction` first** and show its decoded call + simulation (revert check) + risk level so the user gives informed approval.\n2. **The money path is preview → summary card → `execute_transaction` → human.**\n   `execute_transaction` only parks the transaction (`state: \"pending\"`) — the user\n   releases it in a separate terminal window by running `rustok console` (see\n   the onboarding above). Never offer to run the console command yourself\n   and never ask the user to paste the approval PIN into this chat.\n3. **Poll `get_execution_status` reasonably**: when the user asks, or every ~15–30\n   seconds until the `not_after_unix` deadline (if it is `null` — only on request).\n   Stop on any terminal state: `executed`, `denied`, `expired`, `failed`. A\n   `denied` outcome is the human's answer — do not re-submit the same transaction;\n   a not-found error means the id is no longer retained — stop polling.\n4. **Surface what the preview decoded** (who/what is authorized, amount, revert check, estimated cost, risk level) before the user acts on it.\n5. **Use `get_wallet_context` first** so you don't hallucinate balances or chains.\n6. If a tool needs a capability the session lacks, it returns an authorization\n   error — explain that to the user rather than retrying.\n7. If the wallet is unreachable, tell the user the wallet container/onboarding may\n   not be set up (see onboarding above).\n\nFile v0.9.3:_meta.json\n\n{\n  \"ownerId\": \"kn783xqj8cgxz5m78mszfj7x9d81x8f3\",\n  \"slug\": \"wallet\",\n  \"version\": \"0.9.3\",\n  \"publishedAt\": 1786272240461\n}\n\nFile v0.9.3:skill-card.md\n\n## Description:\n\nSelf-custody Ethereum agent wallet that runs locally over MCP, keeps private keys in a local container volume, reads wallet balances and DeFi positions, previews transactions, signs messages, and can submit on-chain transactions with human console gating or user-confirmed autonomous mode.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[rustok](https://clawhub.ai/user/rustok)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and external users use this skill to give an agent a local self-custody Ethereum wallet for wallet context, balances, DeFi positions, transaction previews, gated on-chain sends, execution status checks, and message signing.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill can let an agent operate a real self-custody Ethereum wallet with funds at risk and no hard-coded spending limits.\n\nMitigation: Use it only for funds you can afford to risk, prefer supervised mode, and restrict capabilities and allowed chains where possible.\n\nRisk: Autonomous mode can send transactions without per-transaction approval after the user confirms that mode in the separate console.\n\nMitigation: Use supervised mode unless autonomous sending is intentional, and review transaction previews before execution.\n\nRisk: Message signing is not console-gated and can return signatures without the separate approval window.\n\nMitigation: Connect the wallet only to agents trusted to sign messages, and treat sign-in or off-chain order messages as sensitive.\n\nRisk: Wallet initialization, approval PIN entry, or keyring password handling through an agent shell can expose secrets to the agent context or shell history.\n\nMitigation: Run wallet initialization and the approval console only in the user's own terminal, never paste seed phrases or PINs into chat, and prefer Podman secrets for password delivery.\n\nRisk: An agent with shell or container exec access can reach sensitive wallet surfaces outside the intended approval flow.\n\nMitigation: Do not give the agent shell or docker exec access to the wallet container, and keep approval operations in a separate user-controlled terminal.\n\n## Reference(s):\n\n- [Rustok ClawHub skill page](https://clawhub.ai/rustok/skills/wallet)\n- [Rustok MCP homepage](https://github.com/rustok-org/mcp)\n- [Rustok caveats](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md)\n- [Rustok install guide](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with shell command and JSON configuration examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include transaction preview summaries, approval instructions, execution status guidance, and MCP configuration snippets.]\n\n## Skill Version(s):\n\n0.9.3 (source: server release, SKILL.md frontmatter, claw.json)\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.9.3:claw.json\n\n{\n  \"name\": \"rustok-wallet-tui\",\n  \"version\": \"0.9.3\",\n  \"description\": \"Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions and sign messages. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is not console-gated. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\",\n  \"author\": \"rustok-org\",\n  \"license\": \"MIT-0\",\n  \"permissions\": [\n    \"network\"\n  ],\n  \"entry\": \"SKILL.md\",\n  \"tags\": [\n    \"crypto\",\n    \"ethereum\",\n    \"wallet\",\n    \"defi\",\n    \"agent-wallet\",\n    \"mcp\",\n    \"self-custody\"\n  ],\n  \"minOpenClawVersion\": \"0.8.0\",\n  \"homepage\": \"https://github.com/rustok-org/mcp\"\n}\n\nArchive v0.9.2: 4 files, 8966 bytes\n\nFiles: claw.json (1001b), skill-card.md (2935b), SKILL.md (15294b), _meta.json (125b)\n\nFile v0.9.2:SKILL.md\n\n---\nname: rustok-wallet-tui\ndescription: Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions and sign messages. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is not console-gated. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\nversion: 0.9.2\nmetadata:\n  openclaw:\n    emoji: \"🦀\"\n    homepage: https://github.com/rustok-org/mcp\n---\n\n# rustok-wallet-tui\n\n> **License note:** this OpenClaw skill package (`skills/rustok-wallet-tui/`) is MIT-0\n> per ClawHub requirements. The Rustok wallet core itself is proprietary; only the\n> compiled binary image is distributed.\n\nYou are connected to a **self-custody** Ethereum agent wallet that runs entirely\non the user's machine as a single Docker image (`ghcr.io/rustok-org/rustok-wallet-tui`).\nThe container runs the wallet core + gateway and speaks MCP over **stdio**; the\nprivate keys live only in the user's local Docker volume and never leave it.\n\n> ⚠️ **Self-custody, real funds, your risk.** This wallet has **no hard-coded\n> spending limits or budgets** — the user consciously accepts that funds sent to\n> the agent wallet are at risk. txguard still flags risky transactions, but it\n> does not block them. All supported chains the user enables are live (incl.\n> Ethereum mainnet). Always preview before executing and show the user the details.\n\n## What's protected — and what isn't (be honest with the user)\n\nThe wallet's guarantee is narrow and specific. State it plainly; do not oversell it.\n\nThe full list of boundaries — password delivery, updates, what we do not verify at\nall — lives in [docs/CAVEATS.md](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md).\n\n| | |\n|---|---|\n| **Protected** | Private keys stay in the user's **local Docker volume** and never leave the machine. **Sending funds on-chain** (`execute_transaction`) is gated in a **separate console window** (`rustok console`, opened by the user — see below): parked for the user's approval, with a PIN for high-risk items — unless the user has confirmed **autonomous mode** there, a confirmation only they can give, once per wallet. |\n| **Not gated by the console** | `sign_message` (EIP-191) returns a signature **without** console approval. The wallet refuses to sign a **raw hex blob** (which could hide a transaction, an approval, or typed data), but it **will** sign an ordinary plaintext message (e.g. a sign-in or an off-chain order). Treat message signing as unprotected: don't connect this wallet to an agent you wouldn't trust to sign a message. |\n| **Outside the model** | An agent with **shell / `docker exec` access to the container** can read the gateway key and reach the full signing surface (including EIP-712 permits — a classic drain). That is why the console is a **separate window, not an agent command**. Trusting your own agent is the user's call, the same as never pasting a seed phrase into an untrusted tool. |\n\n**Never claim** the agent (or a prompt-injected agent) \"cannot move funds.\" What is\ntrue: keys stay local, and **on-chain sends** are human-gated in the console.\n\n### Autonomous mode, and why a send may park once\n\nA wallet can be in **autonomous** mode, in which it sends without asking each\ntime. That only happens after a human has confirmed the mode **in the console**:\npress **`c`**, enter the PIN, once per wallet. The agent cannot give that\nconfirmation, and neither can an environment variable or a launch flag.\n\nUntil it is confirmed, an autonomous wallet **parks every send** exactly like a\nsupervised one. The console shows this on every screen and offers the\nconfirmation on the Dashboard.\n\n**If a send parks unexpectedly, this is the first thing to check, and the honest\nthing to tell the user:** the wallet is autonomous but unconfirmed, and one\nconfirmation in the console clears it for good. Do not describe it as an error\nand do not retry the payment — a retry adds a second parked copy under a\ndifferent nonce, and confirming the mode does not release either of them.\n\nConfirmation from a messenger is not in this release.\n\n## Prerequisites\n\n- **Podman** (recommended) or **Docker**. **cosign is optional** — the installer\n  pulls the image **by digest** (you get exactly those bytes or nothing), and\n  uses cosign, when it is present and runnable, to verify *who built* it\n  (provenance). A missing or broken cosign is reported and skipped, not treated\n  as a failure; a working cosign that disagrees still stops the install. Use\n  cosign 3+ if you install it — 2.x cannot read our signatures.\n- An Ethereum RPC URL (an Alchemy key URL is best; a public RPC works for testing).\n\n## One-time onboarding (the user does this in their own terminal, once)\n\nThree commands, in a **terminal the agent cannot see** — the full guide is\n[docs/INSTALL.md](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md).\n\n**1. Install the `rustok` command.** Fetch the installer to a file, read that\nfile, then run **that same file** — what you read is exactly what runs. This is a\nwallet: fetching a script straight into a shell means running code you never saw,\nand one look costs less than that trade.\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.9.2/scripts/install.sh -o install.sh\nless install.sh      # ~150 lines of POSIX sh\nsh install.sh\n```\n\nIt pulls the wallet image **by digest** (those bytes or nothing) and verifies who\nbuilt it with cosign when cosign is available. The release notes for that tag\npublish the script's `sha256` if you would rather check the bytes than read them.\n\n<details>\n<summary>The one-liner, if you have already read the script</summary>\n\n```bash\ncurl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.9.2/scripts/install.sh | sh\n```\n\nPiping to a shell runs whatever the URL serves at that moment, unreviewed. The\ntag pins a *version*, not the bytes — the identities bound to exact bytes live\n**inside** the script (the image digest and the shim's commit SHA). Fine once you\nhave read it; not the way to meet it.\n</details>\n\n**2. Create the wallet** — prints the 12-word phrase and the approval PIN ONCE:\n\n```bash\nrustok init\n```\n\n**3. Register this wallet with the agent client:**\n\n```bash\nrustok connect claude\n```\n\n`rustok init` asks for a keyring password and stores it in the engine's secret\nstore, so it never reaches shell history, `inspect` or any config file. It prints\ntwo things exactly once:\n\n- the **12-word recovery phrase**;\n- the **6-digit approval PIN** — required for every high-risk approval and for\n  unlocking the console session.\n\nWrite both down offline. Recovery = the 12 words (importable into any standard\nwallet) or the wallet volume + password. If the PIN is lost, reset it in the\nrunning wallet with `core-server set-pin` (needs the keyring password and a real\nterminal).\n\n> **Rule of two windows:** never run `rustok init` or the approval console\n> through an agent shell/command — the seed and PIN would leak into the agent's\n> context. These belong only in the user's own terminal (window 2).\n\n## How the agent runs the wallet\n\n`rustok connect claude` writes this registration for the user, so normally none of\nit is typed by hand. It is reproduced here as the reference for what a correct\nsetup looks like — and for setups built without the shim.\n\nThe MCP client launches the image over stdio (keys stay local). **Never put the\nkeyring password in the MCP config or shell history.** On podman, store it once in\nthe secret store; on docker, keep it in a private `0600` file and pass its *path*:\n\n```bash\n# One-time (podman): the value never touches history, inspect or configs.\nread -r -s -p \"Keyring password: \" pw &&\n  printf '%s' \"$pw\" | podman secret create rustok-keyring-claude -\nunset pw\n\npodman run -i --rm \\\n  --label rustok=wallet --label rustok.agent=claude \\\n  -v rustok-wallet-tui:/data \\\n  --secret rustok-keyring-claude,type=mount,mode=0400,uid=1000,gid=1000 \\\n  -e RUSTOK_KEYRING_PASSWORD_FILE=/run/secrets/rustok-keyring-claude \\\n  -e RUSTOK_ALLOWED_CHAINS=\"1,8453\" \\\n  -e RUSTOK_RPC_URLS_1=\"https://your-rpc\" \\\n  ghcr.io/rustok-org/rustok-wallet-tui:v0.9.2\n```\n\n```bash\n# Docker variant: a 0600 file + RUSTOK_KEYRING_PASSWORD_FILE (path, not value).\numask 077\nread -r -s -p \"Keyring passwor\n\nArchive v0.9.1: 4 files, 8951 bytes\n\nFiles: claw.json (1001b), skill-card.md (3076b), SKILL.md (15294b), _meta.json (125b)\n\nArchive v0.9.0: 4 files, 8749 bytes\n\nFiles: claw.json (916b), skill-card.md (2951b), SKILL.md (15036b), _meta.json (125b)\n\nArchive v0.8.5: 4 files, 8327 bytes\n\nFiles: claw.json (916b), skill-card.md (2803b), SKILL.md (14056b), _meta.json (125b)","readmeExcerpt":"Skill: Rustok Agentic Wallet Owner: rustok Summary: Self-custody Ethereum agent wallet - one container image, keys never leave your machine. Reads balances and DeFi positions. Sending is gated in a separate console, never the agent chat: approve each payment, or confirm autonomous mode once and it pays alone. No spending limits, you assume all risk. Tags: latest:0.11.0 Version history: v0.11.0 | 2026-08-20T05:00:59.8","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"curl --proto '=https' --tlsv1.2 -fsSL \\"},{"language":"bash","snippet":"curl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.11.0/scripts/install.sh -o install.sh\nless install.sh      # ~321 lines of POSIX sh\nsh install.sh"},{"language":"bash","snippet":"curl --proto '=https' --tlsv1.2 -fsSL \\"},{"language":"bash","snippet":"curl --proto '=https' --tlsv1.2 -fsSL \\\n  https://raw.githubusercontent.com/rustok-org/mcp/wallet-tui-v0.11.0/scripts/install.sh | sh"},{"language":"bash","snippet":"rustok init"},{"language":"bash","snippet":"rustok connect claude"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: rustok-wallet-tui\ndescription: Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is refused outright, in every mode. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\nversion: 0.11.0\nmetadata:\n  openclaw:\n    emoji: \"🦀\"\n    homepage: https://github.com/rustok-org/mcp\n---\n\n# rustok-wallet-tui\n\n> **License note:** this OpenClaw skill package (`skills/rustok-wallet-tui/`) is MIT-0\n> per ClawHub requirements. The Rustok wallet core itself is proprietary; only the\n> compiled binary image is distributed.\n\nYou are connected to a **self-custody** Ethereum agent wallet that runs entirely\non the user's machine as a single Docker image (`ghcr.io/rustok-org/rustok-wallet-tui`).\nThe container runs the wallet core + gateway and speaks MCP over **stdio**; the\nprivate keys live only in the user's local Docker volume and never leave it.\n\n> ⚠️ **Self-custody, real funds, your risk.** This wallet has **no hard-coded\n> spending limits or budgets** — the user consciously accepts that funds sent to\n> the agent wallet are at risk. txguard still flags risky transactions, but it\n> does not block them. All supported chains the user enables are live (incl.\n> Ethereum mainnet). Always preview before executing and show the user the details.\n\n## What's protected — and what isn't (be honest with the user)\n\nThe wallet's guarantee is narrow and specific. State it plainly; do not oversell it.\n\nThe full list of boundaries — password delivery, updates, what we do not verify at\nall — lives in [docs/CAVEATS.md](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md).\n\n| | |\n|---|---|\n| **Protected** | Private keys stay in the user's **local Docker volume** and never leave the machine. **Sending funds on-chain** (`execute_transaction`) is gated in a **separate console window** (`rustok console`, opened by the user — see below): parked for the user's approval, with a PIN for high-risk items — unless the user has confirmed **autonomous mode** there, a confirmation only they can give, once per wallet. |\n| **Refused, not gated** | `sign_message` (EIP-191) is **refused outright** — in every mode, autonomous included. The console never sees a signature request, because signing does not happen at all: parking a signature for approval (`kind:sign`) is planned and not built. A tool that is listed and always refuses is neither a capability to rely on nor a hole to fear. Tell the user that rather than letting them plan around a signature. |\n| **Outside the model** | An agent with **shell / `docker exec` access to the cont"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn783xqj8cgxz5m78mszfj7x9d81x8f3\",\n  \"slug\": \"wallet\",\n  \"version\": \"0.11.0\",\n  \"publishedAt\": 1787202059882\n}"},{"path":"skill-card.md","content":"## Description:\n\nRustok Agentic Wallet gives an agent access to a local self-custody Ethereum wallet for reading balances and DeFi positions, previewing transactions, and submitting transactions through supervised or user-confirmed autonomous wallet modes.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[rustok](https://clawhub.ai/user/rustok)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nExternal users and developers use this skill to let an agent inspect Ethereum wallet state, review DeFi positions, preview on-chain transactions, and coordinate transaction execution from a local self-custody wallet. It is intended for users who accept live-funds risk and understand the separate approval console and autonomous mode behavior.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The skill handles a real self-custody wallet with live-funds transaction authority and no hard-coded spending limits.\n\nMitigation: Use read-only capabilities unless transaction execution is specifically needed, keep only limited funds in the wallet, preview every transaction, and rely on the separate approval console unless the user intentionally confirms autonomous mode.\n\nRisk: The installer can be run through a remote shell pipeline, which makes it easy to execute installer code without review.\n\nMitigation: Fetch the installer to a file, inspect it before running it, and verify installer or container provenance where possible.\n\nRisk: Broad default execution capabilities increase the blast radius if an agent session is misconfigured or over-trusted.\n\nMitigation: Configure the narrowest required wallet capability set, such as read-only access for balance and position inspection.\n\nRisk: Local wallet secrets and wallet volumes require lifecycle management by the user.\n\nMitigation: Understand how to remove or rotate the local secret and wallet volume before using the skill with meaningful funds.\n\n## Reference(s):\n\n- [ClawHub skill page](https://clawhub.ai/rustok/skills/wallet)\n- [Rustok MCP homepage](https://github.com/rustok-org/mcp)\n- [Install guide](https://github.com/rustok-org/mcp/blob/main/docs/INSTALL.md)\n- [Caveats](https://github.com/rustok-org/mcp/blob/main/docs/CAVEATS.md)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with inline shell commands and JSON configuration snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include wallet-state summaries, transaction-preview guidance, approval-console instructions, and status-polling guidance.]\n\n## Skill Version(s):\n\n0.11.0 (source: server release metadata, SKILL.md frontmatter, claw.json)\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 depl"},{"path":"claw.json","content":"{\n  \"name\": \"rustok-wallet-tui\",\n  \"version\": \"0.11.0\",\n  \"description\": \"Self-custody Ethereum agent wallet. Installs with one command and runs entirely on your machine as a single container image (MCP over stdio); private keys never leave it. Read wallet context, balances and DeFi positions (Aave v3, ERC-4626); preview transactions. Sending funds on-chain is gated in a separate terminal console, never inside the agent chat: you approve each payment, or confirm autonomous mode once and the wallet sends on its own after that; message signing is refused outright, in every mode. You assume all risk for funds on the agent wallet — there are no hard-coded spending limits.\",\n  \"author\": \"rustok-org\",\n  \"license\": \"MIT-0\",\n  \"permissions\": [\n    \"network\"\n  ],\n  \"entry\": \"SKILL.md\",\n  \"tags\": [\n    \"crypto\",\n    \"ethereum\",\n    \"wallet\",\n    \"defi\",\n    \"agent-wallet\",\n    \"mcp\",\n    \"self-custody\"\n  ],\n  \"minOpenClawVersion\": \"0.8.0\",\n  \"homepage\": \"https://github.com/rustok-org/mcp\"\n}"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1789,"uniquenessScore":40,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T23:52:08.372Z","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-09T23:52:08.372Z","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-10T06:43:39.765Z","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"}]}}}