Loading...
Loading...
Official Ledger wallet-cli - USB-based CLI for Ledger hardware wallet flows (account discover, receive, balances, operations, send, swap quote/execute/status, genuine-check, assets token / token-by-id) and the Ledger Key Ring (ring init/encrypt/decrypt/keys/destroy — LKRP-backed encryption of files and text). Use for any wallet-cli command execution and for mapping informal requests to the right command.
npx skill4agent add ledgerhq/agent-skills wallet-cli-usagenpm i -g @ledgerhq/wallet-clipnpm add -g @ledgerhq/wallet-cliyarn global add @ledgerhq/wallet-clibun add -g @ledgerhq/wallet-cliwallet-cli [flags]Concepts & rationale: for why a command behaves the way it does, or to surface a safety rule that this skill states tersely (genuine check, receive-address verification, sessions, sandbox, device contention), read.references/business-logic.md
Session first: When invoked without a specific task, immediately run— do not ask the user what to do first. Show the result, then ask what to do next. If labels exist, skipsession view.account discover
Sandbox:,account discover,receive,send,genuine-check,swap execute,ring encrypt,ring decrypt,ring keysmust usering destroy— the first group is blocked by USB restrictions; the ring commands are blocked by OS keychain access restrictions.dangerouslyDisableSandbox: true
Device contention: Never run two device commands in parallel — they fail withor garbled APDU. Run sequentially.[object Object]
Device readiness: Before running a device command, briefly describe what you're about to do. The CLI prompts for device interaction itself — don't time out or kill the command. Exception:exits immediately (genuine-check, exit code 4) if any currency app is open — unlike the other device commands, it targets the dashboard and has no auto-launch path. Ensure the device is on the dashboard before running; if it exits, ask the user to back out to the dashboard and re-run.[✖] Wrong app. Open Ledger dashboard.
Ambiguous requests — ask, don't guess. If a required parameter is missing or unclear (no recipient for, no network forsend, an amount with no ticker), stop and ask. A wrong guess on a hardware wallet flow can mean irreversible fund loss.account discover
ethereum-1| User says | Command |
|---|---|
| "show me my wallet", "what do I have", "let's get started", no specific task | |
| "find my accounts", "scan my wallet", "import my wallet", "set up Ethereum/Bitcoin" | |
| "where do I send funds to", "give me my address", "deposit address" | |
| "how much do I have", "balance", "what's my ETH balance" | |
| "what did I send", "transaction history", "recent activity" | |
| "send X to Y", "transfer", "pay", "withdraw to an exchange" | |
| "swap A to B", "convert", "trade ETH for BTC", "exchange" | |
| "where can I earn", "staking rates", "yield/APY", "best return on my ETH/SOL" | |
| "what am I staking", "my staking positions", "earn balance" | |
| "stake my SOL", "deposit into a vault", "earn yield on my USDC", "delegate" | |
| "unstake", "withdraw my stake", "redeem from vault", "stop earning" | |
| "is this Ledger real", "verify authenticity", "I bought this off eBay" | |
| "encrypt this file / these env vars / publish tokens", "GPG alternative", "secret manager", "decrypt anywhere with my Ledger" | |
| "what keys do I have on my ring", "list domains/projects I've encrypted under" | |
| "wipe my key ring", "destroy the ring", "tear down LKRP membership" | |
| "start over", "clear my session", "I switched devices" | |
ringsendreceiveoperationsswap executeaccount discover<network>[-derivation][-env]-<n>ethereum-1bitcoin-native-1ethereum-sepolia-1--accountethereum-1account discover| Command | Device | Sandbox | TTY† | Network |
|---|---|---|---|---|
| No | No | No | No |
| No | No | No | No |
| Yes | Required | No | Yes |
| Yes | Required | No | No |
| Yes* | Required | No | Yes |
| Yes | Required | No | Yes |
| No | No | No | Yes |
| No | No | No | Yes |
| No | No | No | Yes |
| Yes | Required | No | Yes |
| No | No | No | Yes |
| No | No | No | No |
| No | No | No | No |
| No | No | No | Yes |
| No | No | No | Yes |
| Yes* | Required | No | Yes |
| Yes* | Required | No | Yes |
| Yes | Required | Required‡ | Yes |
| No | Required | No | Yes |
| No | Required | No | Yes |
| No | Required | No | No |
| No | Required | Required‡‡ | Yes |
sendearn depositearn withdraw--dry-runring initWALLET_PASSring destroy"destroy"echo "destroy" | wallet-cli ring destroyWALLET_PASSwallet-cli session view
wallet-cli session resetwallet-cli account discover ethereum
wallet-cli account discover bitcoin
wallet-cli account discover ethereum:sepoliabitcoinethereumsolanaethereum:sepoliabitcoin:testnetsolana:devnetwallet-cli receive ethereum-1
wallet-cli receive ethereum-1 --no-verify # skip device confirmationgenuine-checkreferences/business-logic.mdwallet-cli genuine-check
wallet-cli genuine-check --output json # only if a downstream caller needs to parse the resultwallet-cli balances ethereum-1
wallet-cli balances ethereum-1 --output jsonwallet-cli operations ethereum-1
wallet-cli operations ethereum-1 --limit 20 --cursor <cursor>nextCursorwallet-cli send ethereum-1 --to 0xDEF... --amount '0.5 ETH'
wallet-cli send ethereum-1 --to 0xDEF... --amount '100 USDT' # ERC-20
wallet-cli send bitcoin-native-1 --to bc1q... --amount '0.001 BTC' --fee-per-byte 15 --rbf
wallet-cli send ethereum-1 --to 0xDEF... --amount '0.5 ETH' --dry-run--amount--token--fee-per-byte <sats>--rbf--mode send|stake.createAccount|stake.delegate|stake.undelegate|stake.withdraw--validator <addr>--stake-account <addr>--memo <text>--from-f--to-tethereumbitcoinsolana--from-account--to-accountswap quoteswap executechangellychangelly_v2ciccic_v2exoduslifinearintentsokxoneinchswapsxyzuniswapvelorauniswaponeinchveloraokx--from-account--to-accountreceivewallet-cli swap quote --from ethereum --to bitcoin --amount 0.1 --from-account ethereum-1 --to-account bitcoin-native-1
wallet-cli swap quote -f ethereum -t bitcoin --amount 0.1 --from-account ethereum-1 --to-account bitcoin-native-1 --output json--from--to--from-account--to-account--amount--from-f--to-tswap quote--account--to-account--providerchangellychangelly_v2ciccic_v2exoduslifinearintentsokxoneinchswapsxyzuniswapvelorachangellychangelly_v21inchoneinchswap quoteuniswaponeinchveloraokxsign-approvalsign-permit2sign-swapOpen <app>ethereum--accountrfq-orderapproval-then-rfq-orderfalling back to legacy Exchange-app pipelinechangellycicexodusnearintentsswapsxyzlifi--fee-strategyslowmediumfastwallet-cli swap execute --from ethereum --to bitcoin --account ethereum-1 --to-account bitcoin-native-1 --provider changelly --amount 0.1
wallet-cli swap execute -f ethereum -t bitcoin --account ethereum-1 --to-account bitcoin-native-1 --provider changelly --amount 0.1 --fee-strategy fast
wallet-cli swap execute --from ethereum --to bitcoin --account ethereum-1 --to-account bitcoin-native-1 --provider changelly --amount 0.1 --output json
# DEX (embedded coin app): EVM-only, source and destination on an EVM chain
wallet-cli swap execute --from ethereum --to ethereum/erc20/usd_tether__erc20_ --account ethereum-1 --to-account ethereum-1 --provider uniswap --amount 0.1--from--to--account--to-account--provider--amount--providerswap quotewallet-cli swap status --swap-id <swapId> --provider changelly
wallet-cli swap status --swap-id <swapId> --provider changelly --output json--swap-id--providerwallet-cli assets token ethereum 0xdac17f958d2ee523a2206206994597c13d831ec7
wallet-cli assets token-by-id ethereum/erc20/usd_tether__erc20_tokentoken-by-id--identifieridswap quote --from--toswap execute --from--toencryptdecryptencryptdecrypt# One-time provisioning (device required). Password comes from WALLET_PASS in the environment (see below); name the machine with --name.
wallet-cli ring init
wallet-cli ring init --name my-laptop
# File round-trip (no device after init):
wallet-cli ring encrypt --key my-oss-project -i .publish-tokens -o .publish-tokens.enc
wallet-cli ring decrypt --key my-oss-project -i .publish-tokens.enc -o .publish-tokens
# Text via stdin/stdout (clipboard pattern):
pbpaste | wallet-cli ring encrypt --key personal-notes | pbcopy
pbpaste | wallet-cli ring decrypt --key personal-notes | pbcopy
# List the keys this machine has used; tear down the ring:
wallet-cli ring keys
wallet-cli ring destroyAlways provision with a password. The ring must be protected by a password. The user provides it viain the environment before runningWALLET_PASS(see Non-TTY password injection) — the agent never provisions a ring without one.ring init
Decrypted output is sensitive.emits secrets — never print them to the terminal,ring decrypta decrypted file, or otherwise surface the decrypted contents, since they land in the agent transcript, logs, and scrollback. Pipecatstraight to its destination (a file viadecrypt, another process, or the clipboard as shown above) or capture it into an env var; avoid-o/logging sinks that could echo it back.--output
--key <name>my-oss-projectopenClaw-prodpersonal-notesringWALLET_PASSWALLET_PASS=hunter2 wallet-cli …psWALLET_PASS=$(security find-generic-password -a default -s ledger-wallet-cli -w) wallet-cli ring encrypt …WALLET_PASS=$(secret-tool lookup service ledger-wallet-cli account default) wallet-cli ring encrypt …$(…)ring initsecurity add-generic-password -a default -s ledger-wallet-cli -wps eww--output json⚠ Ledger Key Ring rotatedring destroyWALLET_PASSyieldspositionsdepositwithdrawOnly ethereum & solana support/deposit. Other networks appear inwithdraw(informational) but cannot be deposited to via the CLI.earn yields
--network-n ethereum-n solana→ --product <id>earn deposit1_0x7daeba3f217614e409f85d3014d33923a6b03630--productwallet-cli earn yields
wallet-cli earn yields -n solana
wallet-cli earn yields -n ethereum --output jsonearn yields -n <network>--productvaultIdvalidatorwallet-cli earn positions solana-1
wallet-cli earn positions solana-1 --fresh # request a background refresh--fresh(stale)→ --stake-account <address>state--stake-accountearn withdrawstakes[]positionsstakeAccountvalidatorstatestakeBalancewithdrawablestakes--productearn yields -n <network>--amount# Solana: --product is a validator vote account
wallet-cli earn deposit solana-1 --product 26pV97Ce83ZQ6Kz9XT4td8tdoUFPTng8Fb8gPyc53dJx --amount '1.5 SOL'
# Ethereum: --product is a vault id
wallet-cli earn deposit ethereum-1 --product 1_0x7daeba3f217614e409f85d3014d33923a6b03630 --amount '100 USDC'
# Validate without signing (no device, no sandbox bypass)
wallet-cli earn deposit solana-1 --product 26pV97… --amount '1.5 SOL' --dry-runstake.createAccountapprovedepositapprovedeposit--dry-runnot-simulated …dry-run: approve validated; deposit needs an on-chain allowance to simulateapprovedeposit--dry-run--product <vault-id>--amount'50 USDC'--amountamount:"max"--stake-account <address>undelegate--finalize--amount# Ethereum vault redeem
wallet-cli earn withdraw ethereum-1 --product 1_0x7daeba3f… --amount '50 USDC'
# Solana phase 1: deactivate
wallet-cli earn withdraw solana-1 --stake-account <stakeAccountAddr>
# Solana phase 2 (after ~2–3 days): withdraw
wallet-cli earn withdraw solana-1 --stake-account <stakeAccountAddr> --finalize--stake-accountearn positions <account>stakes[]→ --stake-accountearn deposit| Error | Cause | Fix |
|---|---|---|
| | Ask the user which asset they mean — do not guess. Then pass the ticker inline, e.g. |
| ticker not in account balances | Run |
| | Ask the user to exit the foreground app on the device (short-press both buttons on the app's main screen until |
| user rejected a sign request on device | The rejection was deliberate. Ask the user whether to retry or abort — do not auto-retry. If they retry, have them review amount, recipient, and fees on the device screen before approving. |
| user rejected the app-open prompt on device | Ask the user to confirm the app-open prompt on the device and re-run the command. |
| sandbox blocking USB, or device busy/locked | Surface to the user that the command needs |
| two device commands running in parallel (contention) | Run device-touching commands sequentially — never in parallel tool calls. |
| device powered off or unplugged | Ask the user to power on the device, unlock it, and connect via USB, then re-run the command. |
| device locked | Keep the command running — the CLI resumes automatically once unlocked. Ask the user to unlock the device with their PIN. |