@palmyr/cli 1.8.2 → 1.8.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -27
- package/dist/cli.js +610 -47
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +13 -1
- package/dist/config.js +15 -1
- package/dist/config.js.map +1 -1
- package/dist/passphrase-prompt.d.ts +4 -1
- package/dist/passphrase-prompt.js +5 -2
- package/dist/passphrase-prompt.js.map +1 -1
- package/dist/sdk.d.ts +1 -0
- package/dist/sdk.js +14 -1
- package/dist/sdk.js.map +1 -1
- package/dist/vault.d.ts +12 -6
- package/dist/vault.js +13 -7
- package/dist/vault.js.map +1 -1
- package/dist/wallet-live-test.js +23 -8
- package/dist/wallet-live-test.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -112,21 +112,26 @@ from a single 12-word mnemonic. Wallets are created locally; the seed never leav
|
|
|
112
112
|
|
|
113
113
|
### Creating a wallet
|
|
114
114
|
|
|
115
|
+
Wallet creation **requires** a recoverable passphrase fallback (the env var keeps the phrase out of shell history) — or an explicit `--session-only` opt-out for ephemeral wallets you're OK losing on reboot / keyring change / host migration.
|
|
116
|
+
|
|
115
117
|
```bash
|
|
116
|
-
#
|
|
117
|
-
palmyr wallet create --name agent-prod
|
|
118
|
+
# Recommended — env-var passphrase fallback (durable across reboots and machines)
|
|
119
|
+
PALMYR_WALLET_PASSPHRASE="your-passphrase" palmyr wallet create --name agent-prod
|
|
118
120
|
|
|
119
|
-
#
|
|
120
|
-
palmyr wallet create --name
|
|
121
|
+
# Equivalent — flag form (less safe, ends up in shell history)
|
|
122
|
+
palmyr wallet create --name agent-prod --passphrase "your-passphrase"
|
|
121
123
|
|
|
122
124
|
# Single-chain: skip the other chain's account
|
|
123
|
-
palmyr wallet create --name sol-only --solana
|
|
124
|
-
palmyr wallet create --name base-only --base
|
|
125
|
+
PALMYR_WALLET_PASSPHRASE="..." palmyr wallet create --name sol-only --solana
|
|
126
|
+
PALMYR_WALLET_PASSPHRASE="..." palmyr wallet create --name base-only --base
|
|
127
|
+
|
|
128
|
+
# OPT OUT — bound to this machine's OS keychain, NOT recoverable from the JSON file alone
|
|
129
|
+
palmyr wallet create --name throwaway --session-only
|
|
125
130
|
```
|
|
126
131
|
|
|
127
|
-
|
|
132
|
+
On a TTY without env or flag, the CLI prompts twice with confirmation; non-TTY callers (CI, agents) must provide one of the three knobs above or get a clear error.
|
|
128
133
|
|
|
129
|
-
|
|
134
|
+
By default a wallet derives both Solana and Base/EVM accounts. Pass `--solana` or `--base` (not both) to materialize only one side. The mnemonic always derives both — `--solana` / `--base` controls *which addresses are surfaced and stored*, not which keys exist cryptographically.
|
|
130
135
|
|
|
131
136
|
### Bulk creation with tags
|
|
132
137
|
|
|
@@ -149,7 +154,7 @@ palmyr wallet tags # all tags + counts + chains
|
|
|
149
154
|
palmyr wallet tag-delete palmyr-demo --confirm
|
|
150
155
|
```
|
|
151
156
|
|
|
152
|
-
Bulk-create
|
|
157
|
+
Bulk-create caps at 500 per call. Names auto-suffix `-001..-N` with zero-padding based on count width.
|
|
153
158
|
|
|
154
159
|
### Importing an existing seed
|
|
155
160
|
|
|
@@ -162,7 +167,9 @@ palmyr wallet import --mnemonic "..." --name from-backup --tag restored --solana
|
|
|
162
167
|
|
|
163
168
|
### Durable recovery — passphrase fallback
|
|
164
169
|
|
|
165
|
-
|
|
170
|
+
Wallets created with a passphrase store **two** decryption blobs: one keyed by the OS-keychain session secret (fast, local), one keyed by scrypt(passphrase, salt) (durable). Decryption tries the keychain first, then falls back to `PALMYR_WALLET_PASSPHRASE`. That second blob is what lets the wallet survive a reboot, OS-keychain password change, fresh OS install, or copy to another machine.
|
|
171
|
+
|
|
172
|
+
Session-only wallets (`--session-only`) **only** have the keychain blob and are NOT recoverable from the JSON file alone. If you have legacy session-only wallets and still have access to the original machine, add a fallback retroactively:
|
|
166
173
|
|
|
167
174
|
```bash
|
|
168
175
|
# At create time — env var preferred (keeps the phrase out of shell history)
|
|
@@ -414,11 +421,11 @@ palmyr compute exec my-vps -- bash -c 'cloud-init clean && cloud-init init --all
|
|
|
414
421
|
| `palmyr domain check --name example.dev` | free | Availability check. |
|
|
415
422
|
| `palmyr domain pricing --name example.dev` | free | TLD pricing. |
|
|
416
423
|
| `palmyr domain buy --name example.dev` | $20.00 | One-year registration. Renewals are charged annually. |
|
|
417
|
-
| `palmyr domain list` | $0.
|
|
418
|
-
| `palmyr domain dns --name example.dev` | $0.
|
|
419
|
-
| `palmyr domain transfer-ownership --name example.dev --to <wallet>` | $0.
|
|
420
|
-
| `palmyr domain share --name example.dev --with <wallet>` | $0.
|
|
421
|
-
| `palmyr domain unshare --name example.dev --from <wallet>` | $0.
|
|
424
|
+
| `palmyr domain list` | $0.01 *(ownership proof)* | List domains your wallet owns plus any shared with you. Each row tagged `access: owner | shared`. |
|
|
425
|
+
| `palmyr domain dns --name example.dev` | $0.01 *(ownership proof)* | View DNS records. Owners and shared wallets allowed. |
|
|
426
|
+
| `palmyr domain transfer-ownership --name example.dev --to <wallet>` | $0.01 *(ownership proof)* | Hand the domain to another wallet. Clears `shared_with` — the prior owner's collaborators don't travel with the domain. |
|
|
427
|
+
| `palmyr domain share --name example.dev --with <wallet>` | $0.01 *(ownership proof)* | Grant another wallet shared access (visible in `domain list`, can edit DNS). Owner-only. |
|
|
428
|
+
| `palmyr domain unshare --name example.dev --from <wallet>` | $0.01 *(ownership proof)* | Revoke a shared wallet's access. Owner-only. |
|
|
422
429
|
|
|
423
430
|
### Wallet
|
|
424
431
|
|
|
@@ -426,8 +433,8 @@ All wallet operations except `addresses`, `api-key`, `config`, and `request-appr
|
|
|
426
433
|
|
|
427
434
|
| Command | Network | Notes |
|
|
428
435
|
|---|---|---|
|
|
429
|
-
| `palmyr wallet create [--name N] [--
|
|
430
|
-
| `palmyr wallet import --mnemonic "..." [--name N] [--
|
|
436
|
+
| `palmyr wallet create [--name N] [--solana\|--base] [--tag T] [--count N] [--name-prefix P] (--passphrase P \| PALMYR_WALLET_PASSPHRASE env \| --session-only)` | local | New wallet. **Requires** either a passphrase (recoverable across reboot / OS-keychain loss / host migration) or explicit `--session-only` opt-out. On TTY without env/flag, prompts twice. Stores keychain secret + (with passphrase) a scrypt-sealed `owner_crypto` blob. `--count > 1` bulk-creates N wallets under a required `--tag` (max 500/call, batched DPAPI seal on Windows). |
|
|
437
|
+
| `palmyr wallet import --mnemonic "..." [--name N] [--solana\|--base] [--tag T] (--passphrase P \| PALMYR_WALLET_PASSPHRASE env \| --session-only)` | local | Restore from BIP-39. Same passphrase rules as `create` — re-importing on a new machine to recover from keychain loss should always set a passphrase so you don't get trapped again. |
|
|
431
438
|
| `palmyr wallet rekey <ID> --passphrase P` | local | Add (or rotate) the scrypt passphrase fallback on an existing wallet. Wallet must be decryptable right now (session secret still works, or `--current-passphrase` provided). Run on the original machine, then `PALMYR_WALLET_PASSPHRASE` decrypts the wallet anywhere. |
|
|
432
439
|
| `palmyr wallet list [--tag T]` | local | Lists wallets in the local vault. `--tag` filters to one folder. |
|
|
433
440
|
| `palmyr wallet info <ID>` | local | Show one wallet (id, name, addresses, mode, tag). |
|
|
@@ -439,7 +446,6 @@ All wallet operations except `addresses`, `api-key`, `config`, and `request-appr
|
|
|
439
446
|
| `palmyr wallet api-key <ID> [--name N]` | API | Mint an agent API key bound to the wallet. |
|
|
440
447
|
| `palmyr wallet config <ID>` | API | Pull the agent's runtime config. |
|
|
441
448
|
| `palmyr wallet use <ID> [--chain solana\|base]` | local | Set default payer and payment chain. |
|
|
442
|
-
| `palmyr wallet request-approval <ID> [--action limits] [--daily N] [--per-tx N]` | API | Managed wallets only — generate an approval URL for a human. |
|
|
443
449
|
| `palmyr wallet export <ID> --confirm` | local | Print mnemonic. Requires explicit `--confirm`. |
|
|
444
450
|
|
|
445
451
|
**Trading.** Thesis-tracked positions on Solana + Base persist at `~/.palmyr/trading/` (overridable via `PALMYR_TRADING_PATH`). Swaps route through Jupiter v6 on Solana and ParaSwap on Base. Positions, sells, journal, and watchlist live as JSON / JSONL.
|
|
@@ -576,7 +582,7 @@ Local credentials are encrypted with AES-256-GCM (per-account session secret in
|
|
|
576
582
|
| `palmyr twitter banner <username> --file path.png` *(or `--url ...`)* | $0.005 | |
|
|
577
583
|
| `palmyr twitter username <username> --to <new-handle>` | $0.005 | Pre-flight validates handle (4–15 chars, `[A-Za-z0-9_]`) before payment. May trigger X's password re-auth modal — handled automatically. |
|
|
578
584
|
| `palmyr twitter transfer <username> --to <wallet> --confirm` | $0.0001 ownership proof + $0.0011 lookup; **adds $0.01 if auto-register runs**; **plus ~$0.001 in poll fees** ($0.0001 × ~10 polls) | Atomically hand the X account to another wallet. End-to-end one-command: looks up the account in both server tables (`x_accounts` + `social_registered_accounts`), auto-registers if only in local vault, then kicks off an async rotation job. Server returns `{ transfer_id }` immediately and the CLI polls `/transfers/:id` every 5s until `completed` or `failed` (rotation takes 30-90s in the background — async so it survives Cloudflare's HTTP timeout). Password is rotated and other sessions revoked before ownership flips, so the local copy of credentials becomes useless. Requires `--confirm`. Local vault entry is removed on success — receiver picks up fresh creds with `palmyr twitter list` (which shows server-only accounts) and/or `palmyr twitter claim`. |
|
|
579
|
-
| `palmyr twitter share <username> --with <wallet>` | $0.
|
|
585
|
+
| `palmyr twitter share <username> --with <wallet>` | $0.01 *(ownership proof)* | Grant another wallet shared access — same login, no credential rotation. Both wallets see the account via `palmyr twitter claim`. Owner-only. Same pool / registered dispatch as transfer. |
|
|
580
586
|
| `palmyr twitter unshare <username> --from <wallet> [--rotate]` | $0.0001 ownership proof + $0.0011 lookup; **with `--rotate`: kicks off async rotation, ~$0.001 in poll fees plus another lookup to sync local vault** | Revoke a wallet's shared access. Without `--rotate`, the wallet is removed from `shared_with` immediately but their previously exported cookies / password remain valid until X-side expiry. With `--rotate`, the unshare is immediate AND the server kicks off an async password rotation (same machinery as transfer — Playwright + polling so it survives Cloudflare's HTTP timeout). On completion, the CLI fetches the new credentials from the appropriate `/mine` endpoint and updates the local vault in place. Owner-only. Same pool / registered dispatch. |
|
|
581
587
|
| `palmyr twitter claim` | $0.0011 *(ownership proof on both `/x/accounts/mine` and `/social/twitter/registered/mine`)* | Pull every X account on the server bound to your wallet (owner or shared) into the local vault, with session cookies pre-warmed. Queries both server tables in parallel. The fast path for a wallet that just received a transferred account. |
|
|
582
588
|
|
|
@@ -803,10 +809,11 @@ Config is stored in `~/.palmyr/config.json`. Environment variables override file
|
|
|
803
809
|
|
|
804
810
|
The payment chain is resolved in this order:
|
|
805
811
|
|
|
806
|
-
1.
|
|
807
|
-
2. `
|
|
808
|
-
3. `
|
|
809
|
-
|
|
812
|
+
1. `--chain` flag on the command itself (e.g. `wallet pay-preflight --chain base`).
|
|
813
|
+
2. `defaultPayChain` in `~/.palmyr/config.json` — set by `palmyr wallet use <ID> --chain <chain>`.
|
|
814
|
+
3. `solana` as the final default.
|
|
815
|
+
|
|
816
|
+
(Earlier versions of this doc listed `PALMYR_PAY_CHAIN` and `defaultChain` as fallbacks — neither is read by the current pay path. `defaultChain` is legacy keyfile-flow state and `saveConfig` strips it from vault-only configs.)
|
|
810
817
|
|
|
811
818
|
If the server doesn't offer the chosen chain for an endpoint, the CLI errors loudly. There is no silent fallback — the assumption is that an agent should know which chain it pays from.
|
|
812
819
|
|
|
@@ -820,7 +827,6 @@ If the server doesn't offer the chosen chain for an endpoint, the CLI errors lou
|
|
|
820
827
|
├── wallet/
|
|
821
828
|
│ ├── wallets/ # Encrypted wallet files (AES-256-GCM)
|
|
822
829
|
│ ├── keys/ # API key metadata
|
|
823
|
-
│ ├── policies/ # Spending policies for managed wallets
|
|
824
830
|
│ └── spends/ # Per-day spend ledgers
|
|
825
831
|
├── secrets/ # Windows DPAPI fallback (macOS/Linux use OS keychain)
|
|
826
832
|
├── data/ # Local cache of phones, inboxes, servers, domains
|
|
@@ -853,10 +859,10 @@ The CLI uses distinct exit codes so scripts and agents can branch on failure mod
|
|
|
853
859
|
|
|
854
860
|
## Security Model
|
|
855
861
|
|
|
856
|
-
- **Keys never leave the machine.** `wallet create` and `wallet import` never transmit seed material to the server.
|
|
862
|
+
- **Keys never leave the machine.** `wallet create` and `wallet import` never transmit seed material to the server.
|
|
857
863
|
- **Encryption at rest.** The wallet file is AES-256-GCM with the session secret as the key. The session secret is generated on wallet creation and never stored on disk in plaintext.
|
|
858
864
|
- **OS credential store.** Session secrets live in DPAPI (Windows), Keychain (macOS), or `secret-tool` (libsecret on Linux). If none is available the CLI errors rather than falling back to plaintext.
|
|
859
|
-
- **
|
|
865
|
+
- **Recoverable by default.** `wallet create` and `wallet import` require a scrypt passphrase fallback (via `--passphrase` or `PALMYR_WALLET_PASSPHRASE`) or an explicit `--session-only` opt-out. The passphrase blob is a second AES-256-GCM ciphertext keyed by scrypt(passphrase, random salt) and lets the wallet decrypt on a different machine / user / headless box where the OS keychain isn't reachable. Decryption tries the OS session secret first, then falls back to the env/flag passphrase. Session-only wallets are bound to this machine's OS keychain — explicit opt-in for ephemeral use only.
|
|
860
866
|
- **Bidirectional vault integrity.** On every load, the CLI checks that every account stored in the wallet file is still derivable from the seed, **and** that every account derivable from the seed is still in the file. Either direction failing returns exit code `7`.
|
|
861
867
|
- **Pre-flight validation.** Endpoints that are easy to fail (bad pubkey for an inbox, malformed E.164 for SMS, unsupported destination country) are validated **before** the x402 paywall, so you don't pay for requests that were never going to succeed.
|
|
862
868
|
- **No `--no-verify`.** Hooks, signatures, and webhooks are always verified.
|
|
@@ -876,7 +882,6 @@ Common issues:
|
|
|
876
882
|
- **`SECURITY` exit code on any wallet command.** The vault file or its derived accounts have drifted. Restore the wallet file from backup, or re-import from the mnemonic.
|
|
877
883
|
- **`Server did not offer <chain> as option`.** Either the endpoint only supports the other chain, or your `defaultPayChain` is misconfigured. Use `palmyr wallet use <ID> --chain <other>` and retry.
|
|
878
884
|
- **`No session secret found`.** The wallet was created on a different machine, or the OS credential store is unavailable. Re-import the wallet and let the CLI store the secret again.
|
|
879
|
-
- **Managed wallet, `REQUIRES_APPROVAL`.** The transaction exceeded a per-tx or daily limit. Run `palmyr wallet request-approval <ID>` and forward the URL to the human reviewer.
|
|
880
885
|
|
|
881
886
|
---
|
|
882
887
|
|