--- name: nansen-wallet-keychain-migration description: Migrate an existing nansen-cli wallet from insecure password storage (env files, .credentials) to the new secure keychain-backed flow. metadata: openclaw: requires: bins: - nansen primaryEnv: NANSEN_API_KEY install: - kind: node package: nansen-cli bins: [nansen] allowed-tools: Bash(nansen:*) --- ## Authentication Nansen account API calls accept a selected `nansen:api` browser session or conventional API key with the same permissions. `NANSEN_API_KEY` takes precedence; optional `primaryEnv` preserves configured-key injection. Run `nansen auth status` for offline selection. Cached access expiry alone permits automatic renewal during an authorized task. Stop on anonymous selection, invalid state, blocked/uncertain renewal or actual auth failure; never drop a credential or fall back to anonymous x402 payment. Browser login does not grant wallet signing, privileged service identity or a persistent MCP integration key. Preserve all confirmation, signing, sanctions and geographic checks below. Browser login is available in CLI 2.0.0 within the [macOS arm64 preview scope](https://github.com/nansen-ai/nansen-cli/blob/main/docs/browser-login.md#preview-platform-scope). # Wallet Migration — Old Flow to Secure Keychain Use this skill when a user already has a nansen-cli wallet set up with the **old** password storage method and wants to migrate to the new secure flow. ## When to use - User mentions they stored their password in `~/.nansen/.env`, a `.env` file, or `memory.md` - User gets the stderr warning: `⚠ Password loaded from insecure .credentials file` - User asks to "secure my wallet" or "migrate to keychain" - User created a wallet before the keychain update was released ## Detect current state `wallet show` only displays addresses and does NOT load or check the password. To detect the actual password situation, check the stored password source directly: ```bash # 1. Where is the password stored? Offline, decrypts nothing, prints no secrets nansen auth status --pretty # → x402.password.source: "env" | "keychain" | "file" | null # 2. Full setup check — flags the insecure .credentials file with a fix nansen doctor --offline # 3. Legacy pattern doctor does not cover: password written to ~/.nansen/.env ls -la ~/.nansen/.env 2>/dev/null && echo "FOUND: ~/.nansen/.env (insecure)" ``` Interpret `x402.password.source`: - `"file"` → password in `.credentials` file, needs migration (Path B) - `"keychain"` → already secure, no migration needed - `null` → password not persisted anywhere (Path C or D) - `"env"` → `NANSEN_WALLET_PASSWORD` is set; check where it is being exported from (a `.env` file → Path A) Do NOT use `nansen wallet export` to probe the password state — the default is redacted and never loads the password, so it proves nothing (and `--reveal` prints private keys). ## Migration paths ### Path A: Password in `~/.nansen/.env` (old skill pattern) The previous wallet skill told agents to write the password to `~/.nansen/.env`. **Step 1 — Ask the human for their password:** > "Your wallet password is currently stored in ~/.nansen/.env, which is insecure. > I can migrate it to your OS keychain. Please confirm the password you used when > creating the wallet, or I can read it from ~/.nansen/.env if you authorize it." **Step 2 — Migrate:** The `source` and `nansen wallet secure` MUST run in the same shell so the env var is available to the node process: ```bash source ~/.nansen/.env 2>/dev/null && nansen wallet secure ``` **Step 3 — Verify the password actually decrypts the wallet:** ```bash # Unset env var to prove keychain works, then run a decrypting export with # all output discarded — the exit code alone is the signal, so no key # material can land in a transcript or log unset NANSEN_WALLET_PASSWORD if nansen wallet export default --reveal > /dev/null 2>&1; then echo "decryption OK"; else echo "decryption FAILED"; fi ``` If the export exits 0 (`decryption OK`), the migration worked. If it fails, the wrong password was migrated — run `nansen wallet forget-password` and retry with the correct password. **Step 4 — Clean up the insecure file:** ```bash rm -f ~/.nansen/.env ``` ### Path B: Password in `.credentials` file (auto-saved fallback) This happens when `wallet create` couldn't access the OS keychain (containers, CI). ```bash nansen wallet secure ``` If the keychain is still unavailable (e.g. containerized Linux without D-Bus), `nansen wallet secure` will explain the situation and suggest alternatives. After migrating, verify decryption works (output discarded on purpose — branch on the exit code): ```bash if nansen wallet export default --reveal > /dev/null 2>&1; then echo "decryption OK"; else echo "decryption FAILED"; fi ``` ### Path C: Password only in `NANSEN_WALLET_PASSWORD` env var ```bash # Persist the env var password to keychain nansen wallet secure ``` Then verify without the env var (exit code is the signal; output is discarded so no keys are disclosed): ```bash unset NANSEN_WALLET_PASSWORD if nansen wallet export default --reveal > /dev/null 2>&1; then echo "decryption OK"; else echo "decryption FAILED"; fi ``` ### Path D: Password lost entirely The password cannot be recovered. The wallet's private keys are encrypted with AES-256-GCM and the password is not stored anywhere recoverable. **Tell the human:** > "Your wallet password cannot be recovered. If you have funds in this wallet, > they may be inaccessible. You can create a new wallet and transfer any remaining > accessible funds." ```bash # Create a fresh wallet (human must provide a new password) NANSEN_WALLET_PASSWORD="" nansen wallet create --name new-wallet ``` ## Post-migration verification After any migration, confirm the password was migrated correctly by proving the keychain password can actually decrypt the wallet: ```bash # Unset env var to prove keychain works unset NANSEN_WALLET_PASSWORD # This MUST exit 0 — it proves the keychain password decrypts the wallet. # Output is discarded on purpose: the exit code alone is the signal. if nansen wallet export default --reveal > /dev/null 2>&1; then echo "decryption OK"; else echo "decryption FAILED"; fi ``` If the export fails, the wrong password was saved to the keychain. Fix with: ```bash nansen wallet forget-password NANSEN_WALLET_PASSWORD="" nansen wallet secure ``` If `stderr` still shows the `.credentials` warning, the keychain migration did not succeed — check if the OS keychain service is running (`secret-tool` on Linux, `security` on macOS). ## Forget password (all stores) If the user wants to remove their persisted password entirely: ```bash nansen wallet forget-password ``` This clears the password from both OS keychain and `.credentials` file. Future wallet operations will require `NANSEN_WALLET_PASSWORD` env var or re-running `nansen wallet secure`. ## Critical rules for agents - **NEVER generate a password** — always ask the human - **NEVER store the password** in files, memory, logs, or conversation history - **NEVER use `--human` flag** — interactive prompts break agents - If the human authorizes reading `~/.nansen/.env`, read it in the same command (`source ~/.nansen/.env && nansen wallet secure`) — do not echo or log the value - **ALWAYS verify after migration** with `nansen wallet export default --reveal > /dev/null 2>&1` (branch on the exit code; never let the output print) — `wallet show` does NOT prove the password works (it never loads the password)