perp-cli 0.15.0 → 0.16.0

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.
Files changed (154) hide show
  1. package/README.ja.md +243 -0
  2. package/README.ko.md +243 -0
  3. package/README.md +129 -535
  4. package/README.zh.md +243 -0
  5. package/dist/api/public/lighter.d.ts +5 -0
  6. package/dist/api/public/lighter.js +5 -0
  7. package/dist/api/public/pacifica.js +2 -2
  8. package/dist/arb/sizing.js +4 -2
  9. package/dist/arb/state.d.ts +6 -0
  10. package/dist/balance-by-address.d.ts +39 -0
  11. package/dist/balance-by-address.js +44 -0
  12. package/dist/bot/quote-rules.js +1 -1
  13. package/dist/bot/strategies/funding-arb-strategy.js +10 -3
  14. package/dist/bot/strategies/funding-arb-utils.d.ts +14 -2
  15. package/dist/bot/strategies/funding-arb-utils.js +48 -15
  16. package/dist/bot/strategies/spot-perp-arb-strategy.d.ts +1 -1
  17. package/dist/bot/strategies/spot-perp-arb-strategy.js +4 -2
  18. package/dist/bot/strategies/spot-perp-executor.js +2 -2
  19. package/dist/cli-program.js +1 -1
  20. package/dist/commands/account.js +168 -24
  21. package/dist/commands/arb/index.js +19 -77
  22. package/dist/commands/arb-auto.d.ts +24 -0
  23. package/dist/commands/arb-auto.js +155 -81
  24. package/dist/commands/arb.d.ts +8 -0
  25. package/dist/commands/arb.js +49 -23
  26. package/dist/commands/backtest.js +23 -21
  27. package/dist/commands/market.d.ts +48 -0
  28. package/dist/commands/market.js +241 -78
  29. package/dist/commands/options.d.ts +5 -0
  30. package/dist/commands/options.js +20 -3
  31. package/dist/commands/pacifica-earn.js +8 -21
  32. package/dist/commands/portfolio.d.ts +16 -0
  33. package/dist/commands/portfolio.js +51 -8
  34. package/dist/commands/trade.js +4 -4
  35. package/dist/cross-chain-margin.d.ts +3 -1
  36. package/dist/cross-chain-margin.js +4 -2
  37. package/dist/dashboard/server.js +2 -2
  38. package/dist/dashboard/ui.js +9 -6
  39. package/dist/errors.d.ts +5 -0
  40. package/dist/errors.js +10 -0
  41. package/dist/exchanges/address.d.ts +8 -0
  42. package/dist/exchanges/address.js +47 -0
  43. package/dist/exchanges/arcus/adapter.d.ts +10 -6
  44. package/dist/exchanges/arcus/adapter.js +33 -6
  45. package/dist/exchanges/arcus/public.js +3 -2
  46. package/dist/exchanges/aster.d.ts +27 -7
  47. package/dist/exchanges/aster.js +124 -42
  48. package/dist/exchanges/canonical-symbols.d.ts +7 -0
  49. package/dist/exchanges/canonical-symbols.js +20 -0
  50. package/dist/exchanges/capabilities.d.ts +2 -0
  51. package/dist/exchanges/capabilities.js +2 -1
  52. package/dist/exchanges/derive/options.d.ts +5 -0
  53. package/dist/exchanges/derive/options.js +20 -1
  54. package/dist/exchanges/extended/adapter.d.ts +16 -2
  55. package/dist/exchanges/extended/adapter.js +96 -34
  56. package/dist/exchanges/extended/public.d.ts +3 -0
  57. package/dist/exchanges/extended/public.js +9 -2
  58. package/dist/exchanges/grvt/adapter.d.ts +16 -2
  59. package/dist/exchanges/grvt/adapter.js +98 -21
  60. package/dist/exchanges/hyperliquid-outcome.d.ts +2 -0
  61. package/dist/exchanges/hyperliquid-outcome.js +29 -1
  62. package/dist/exchanges/hyperliquid-spot.d.ts +8 -0
  63. package/dist/exchanges/hyperliquid-spot.js +20 -12
  64. package/dist/exchanges/hyperliquid.d.ts +180 -13
  65. package/dist/exchanges/hyperliquid.js +487 -185
  66. package/dist/exchanges/interface.d.ts +64 -8
  67. package/dist/exchanges/interface.js +31 -0
  68. package/dist/exchanges/lighter-public.d.ts +66 -11
  69. package/dist/exchanges/lighter-public.js +249 -81
  70. package/dist/exchanges/lighter-spot.d.ts +7 -1
  71. package/dist/exchanges/lighter-spot.js +99 -90
  72. package/dist/exchanges/lighter.d.ts +70 -11
  73. package/dist/exchanges/lighter.js +285 -92
  74. package/dist/exchanges/ondo/adapter.d.ts +34 -8
  75. package/dist/exchanges/ondo/adapter.js +73 -16
  76. package/dist/exchanges/ondo/public.d.ts +27 -2
  77. package/dist/exchanges/ondo/public.js +63 -31
  78. package/dist/exchanges/outcome-interface.d.ts +4 -0
  79. package/dist/exchanges/pacifica-spot.d.ts +6 -0
  80. package/dist/exchanges/pacifica-spot.js +23 -15
  81. package/dist/exchanges/pacifica-vaults.d.ts +9 -0
  82. package/dist/exchanges/pacifica-vaults.js +14 -1
  83. package/dist/exchanges/pacifica.d.ts +77 -6
  84. package/dist/exchanges/pacifica.js +321 -130
  85. package/dist/exchanges/public-balances.d.ts +25 -0
  86. package/dist/exchanges/public-balances.js +158 -0
  87. package/dist/exchanges/public-positions.d.ts +43 -0
  88. package/dist/exchanges/public-positions.js +154 -0
  89. package/dist/exchanges/qfex/adapter.d.ts +52 -9
  90. package/dist/exchanges/qfex/adapter.js +74 -9
  91. package/dist/exchanges/qfex/public.d.ts +62 -9
  92. package/dist/exchanges/qfex/public.js +128 -22
  93. package/dist/exchanges/qfex/ws-transport.d.ts +1 -1
  94. package/dist/exchanges/risex/adapter.d.ts +19 -7
  95. package/dist/exchanges/risex/adapter.js +58 -12
  96. package/dist/exchanges/spot-factory.js +1 -1
  97. package/dist/exchanges/txflow/adapter.d.ts +14 -7
  98. package/dist/exchanges/txflow/adapter.js +51 -19
  99. package/dist/exchanges/txflow/client.js +3 -1
  100. package/dist/exchanges/txflow/public.d.ts +12 -1
  101. package/dist/exchanges/txflow/public.js +82 -11
  102. package/dist/exchanges/unknown-symbol.d.ts +6 -1
  103. package/dist/exchanges/unknown-symbol.js +7 -2
  104. package/dist/exchanges/variational/adapter.d.ts +2 -6
  105. package/dist/exchanges/venue-types.d.ts +46 -3
  106. package/dist/exchanges/venue-types.js +80 -9
  107. package/dist/exchanges/venue.d.ts +99 -3
  108. package/dist/exchanges/venue.js +72 -0
  109. package/dist/exchanges/venues/hyperliquid.js +9 -0
  110. package/dist/exchanges/venues/lighter-rh.js +13 -3
  111. package/dist/exchanges/venues/lighter.js +13 -3
  112. package/dist/exchanges/venues/pacifica.js +9 -0
  113. package/dist/exchanges/venues/risex.js +15 -0
  114. package/dist/funding/legacy-public.d.ts +5 -3
  115. package/dist/funding/legacy-public.js +33 -37
  116. package/dist/funding/rates.d.ts +54 -5
  117. package/dist/funding/rates.js +49 -13
  118. package/dist/liquidity.d.ts +3 -1
  119. package/dist/liquidity.js +8 -4
  120. package/dist/mcp-pacifica-earn.js +11 -5
  121. package/dist/mcp-server.js +104 -15
  122. package/dist/pacifica/client.d.ts +2 -1
  123. package/dist/pacifica/client.js +11 -0
  124. package/dist/positions-by-address.d.ts +34 -0
  125. package/dist/positions-by-address.js +46 -0
  126. package/dist/strategies/funding-arb.js +35 -62
  127. package/dist/utils.d.ts +11 -1
  128. package/dist/venue-health.js +1 -1
  129. package/dist/ws/arcus-market.d.ts +9 -0
  130. package/dist/ws/arcus-market.js +9 -0
  131. package/dist/ws/aster-market.d.ts +33 -0
  132. package/dist/ws/aster-market.js +30 -0
  133. package/dist/ws/index.d.ts +30 -9
  134. package/dist/ws/index.js +180 -15
  135. package/dist/ws/lighter-market.d.ts +14 -0
  136. package/dist/ws/lighter-market.js +13 -0
  137. package/dist/ws/node.d.ts +30 -9
  138. package/dist/ws/node.js +204 -16
  139. package/dist/ws/unclassified.d.ts +16 -0
  140. package/dist/ws/unclassified.js +43 -0
  141. package/package.json +15 -2
  142. package/skills/perp-cli/SKILL.md +97 -33
  143. package/skills/perp-cli/package.json +15 -2
  144. package/skills/perp-cli/references/agent-operations.md +15 -12
  145. package/skills/perp-cli/references/commands.md +67 -12
  146. package/skills/perp-cli/references/strategies.md +38 -3
  147. package/skills/perp-cli/references/ws-library.md +55 -24
  148. package/skills/perp-cli/scripts/arb-monitor.sh +13 -10
  149. package/skills/perp-cli/scripts/funding-analysis.sh +57 -29
  150. package/skills/perp-cli/scripts/preflight.sh +27 -19
  151. package/skills/perp-cli/scripts/spot-perp-scan.sh +58 -38
  152. package/skills/perp-cli/scripts/validate-arb.sh +56 -39
  153. package/dist/cli-spec.d.ts +0 -46
  154. package/dist/cli-spec.js +0 -81
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  name: perp-cli
3
- description: "Multi-DEX perpetual futures trading via the perp-cli command-line tool. Use when user asks to: trade perps, check funding rates, scan/execute arbitrage (perp-perp or spot-perp), run delta-neutral strategies, bridge USDC across chains, manage positions/orders/leverage, deposit/withdraw, hedge spot+perp, trade HIP-3 DEXes, or mentions perp-cli, hypurrquant, Pacifica, Hyperliquid, Lighter, Aster, Lighter RH, Ondo Perps, Arcus, QFEX, RISEx, TxFlow, Variational, GRVT, HyperEVM, funding arb, or U-tokens (UBTC/UETH/USOL). Covers Pacifica (Solana), Hyperliquid (HyperEVM), Lighter (Ethereum), Aster (BNB Chain), Lighter RH and Arcus (Robinhood chain), Ondo Perps and QFEX (off-chain), RISEx (RISE chain), TxFlow (market data only, UNOFFICIAL API) Variational Omni (market data only, official API) and GRVT (market data only for now, official API)."
3
+ description: "Multi-DEX perpetual futures trading via the perp-cli command-line tool. Use when user asks to: trade perps, check funding rates, scan/execute arbitrage (perp-perp or spot-perp), run delta-neutral strategies, bridge USDC across chains, manage positions/orders/leverage, deposit/withdraw, hedge spot+perp, trade HIP-3 DEXes, read Derive options chains, use Pacifica Print or Pacifica vaults, or mentions perp-cli, hypurrquant, Pacifica, Hyperliquid, Lighter, Aster, Lighter RH, Ondo Perps, Arcus, QFEX, RISEx, TxFlow, Variational, GRVT, Extended, Derive, HyperEVM, funding arb, or U-tokens (UBTC/UETH/USOL). Covers Pacifica (Solana), Hyperliquid (HyperEVM), Lighter (Ethereum), Aster (BNB Chain), Lighter RH and Arcus (Robinhood chain), Ondo Perps and QFEX (off-chain), RISEx (RISE chain), TxFlow (market data only, UNOFFICIAL API) Variational Omni (market data only, official API), GRVT and Extended (Starknet) (market data only for now, official API), Derive options (read-only), and Pacifica Print / vaults."
4
4
  license: MIT
5
- allowed-tools: "Bash(perp:*), Bash(npx -y perp-cli:*), Bash(bash scripts/preflight.sh:*), Bash(bash scripts/arb-monitor.sh:*), Bash(bash scripts/funding-analysis.sh:*), Bash(bash scripts/spot-perp-scan.sh:*), Bash(bash scripts/validate-arb.sh:*)"
6
- compatibility: "Requires Node.js 20 or newer and the perp-cli npm package (global install or npx). Network access required for exchange APIs and bridge providers. Mutating commands need a wallet key imported into the OWS vault via 'perp wallet set EXCHANGE' (key on stdin or hidden prompt — never argv). Skill is portable across Claude Code, Claude.ai, Cursor, Codex, and Gemini CLI — no platform-specific features."
5
+ allowed-tools: "Bash(perp:*), Bash(bash scripts/preflight.sh:*), Bash(bash scripts/arb-monitor.sh:*), Bash(bash scripts/funding-analysis.sh:*), Bash(bash scripts/spot-perp-scan.sh:*), Bash(bash scripts/validate-arb.sh:*)"
6
+ compatibility: "Requires Node.js 20 or newer and the perp-cli npm package installed by the user (version must be >= 0.16.0; the user runs `npm install -g perp-cli` — never install it yourself). Network access required for exchange APIs and bridge providers. Mutating commands need a wallet key imported into the OWS vault via 'perp wallet set EXCHANGE' (key on stdin or hidden prompt — never argv). Skill is portable across Claude Code, Claude.ai, Cursor, Codex, and Gemini CLI — no platform-specific features."
7
7
  metadata:
8
8
  author: hypurrquant
9
- version: "0.15.0"
9
+ version: "0.16.0"
10
10
  ---
11
11
 
12
12
  # perp-cli
@@ -28,15 +28,15 @@ This skill uses progressive disclosure. Read these on demand:
28
28
  - `references/commands.md` — full command tree for every group (market, account, trade, outcome, options, print, vault, arb, funds, wallet, risk, history, strategy, background, alerts, settings, backtest)
29
29
  - `references/agent-operations.md` — non-interactive setup flows, idempotency rules, error codes, common mistakes
30
30
  - `references/strategies.md` — funding-arb decision framework + risk-management playbook (read before designing arb strategy)
31
- - `references/ws-library.md` — WebSocket library (0.15.0, @experimental), published standalone as **`@hypurrquant/perp-ws`** (zero dependencies; recommended for integrators — `npm install @hypurrquant/perp-ws`) and inside perp-cli as `perp-cli/ws` (same code, use it when perp-cli is already installed): build a live dashboard / funding comparison / account feed in the browser or Node (streams, events, nullability, comparator, user channels, errors, capability matrix). Cross-venue subscriptions use `canonicals` (e.g. `{ kind: "allMarkets", canonicals: ["BTC"] }`), never `symbols` (those are per-venue directory symbols); always surface `ready` rejections — an `idle` venue is not "fine"
31
+ - `references/ws-library.md` — WebSocket library (shipped since 0.15.0, @experimental), published standalone as **`@hypurrquant/perp-ws`** (zero dependencies; recommended for integrators — `npm install @hypurrquant/perp-ws`) and inside perp-cli as `perp-cli/ws` (same code, use it when perp-cli is already installed): build a live dashboard / funding comparison / account feed in the browser or Node (streams, events, nullability, comparator, user channels, errors, capability matrix). Cross-venue subscriptions use `canonicals` (e.g. `{ kind: "allMarkets", canonicals: ["BTC"] }`), never `symbols` (those are per-venue directory symbols); always surface `ready` rejections — an `idle` venue is not "fine"
32
32
 
33
- Also bundled under `scripts/`: `preflight.sh`, `arb-monitor.sh`, `funding-analysis.sh`, `spot-perp-scan.sh`, `validate-arb.sh`. Use these for repeatable multi-step diagnostics.
33
+ Also bundled under `scripts/`: `preflight.sh`, `arb-monitor.sh`, `funding-analysis.sh`, `spot-perp-scan.sh`, `validate-arb.sh`. Use these for repeatable multi-step diagnostics. They need `perp` on PATH (else they exit 1 with `PERP_NOT_FOUND` — ask the user to install it) and exit non-zero on a failed read; `funding-analysis.sh` / `spot-perp-scan.sh` take `-n mainnet|testnet`, `spot-perp-scan.sh --no-portfolio` scans without a wallet.
34
34
 
35
35
  ### Critical rules
36
36
 
37
37
  1. **Always pass `--json`.** Without it, output is human-formatted and hard to parse. `ok:false` also exits 1.
38
38
  2. **Always pass `-e <venue>`** on venue-scoped commands. The default is `settings.defaultExchange`, else `pacifica` — never rely on it.
39
- 3. **Always run `--dry-run` first** for any mutating command that supports it (`--help` says "supports --dry-run"). Show the result, get user confirmation, then execute without `--dry-run`. Commands without dry-run support refuse `--dry-run` with `INVALID_PARAMS` (see "Safety rules").
39
+ 3. **Always run `--dry-run` first** for any mutating command that supports it, show the result, get user confirmation, then execute without `--dry-run`. `--help` is NOT a reliable indicator — the 0.16.0 list: every `trade` write (market / buy / sell / limit / split / cancel / cancel-all / stop / tpsl / scale-tp / scale-in / edit / atomic / leverage / close / close-all / flatten / reduce / spot-buy / spot-sell / spot-limit / spot-cancel / spot-transfer), `arb exec|close|auto|rebalance`, `funds deposit|withdraw|transfer|faucet|bridge send|bridge exchange|rebalance execute|address-book add`, `outcome buy|sell`, `print deposit|cancel`, `vault deposit|withdraw`, `wallet builder approve|revoke`, `wallet manage referral set`, `strategy run`, `strategy plan execute`. Everything else (read-only commands too; `trade twap|multi|cancel-stop|cancel-twap`; the moved stubs `wallet manage lake deposit|withdraw` → use `vault deposit|withdraw`) refuses `--dry-run` with `INVALID_PARAMS` — that refusal means "unsupported", nothing ran (see "Safety rules").
40
40
  4. **Always use `--fields`** when you only need specific data — saves tokens.
41
41
  5. **Avoid bare `perp setup` / `perp init` / `perp wallet setup`** — they prompt and will hang an agent. Use `printf '%s' "$KEY" | OWS_PASSPHRASE=<pp> perp --json wallet set <exchange>` for key registration (key on stdin; a key on argv or `-k` is rejected), or `perp --json setup --non-interactive --wallet <ows-wallet> --venues <list> [--default-venue <v>] [--slippage-bps <n>] [--slippage <venue>=<bps>]` (new wallet: `--wallet-name <name>` with the passphrase in `OWS_PASSPHRASE`; agent registration only with `--approve-agents --yes`, after user confirmation) (and `OWS_PASSPHRASE=<pp> perp wallet setup --name <n> --max-tx-usd <usd> --max-daily-usd <usd>`) when the wizard is required. The passphrase goes in `OWS_PASSPHRASE` or stdin — the root `--passphrase` flag is deprecated (visible in `ps`).
42
42
  6. **NEVER trade without explicit user confirmation.** A dry-run is not consent.
@@ -44,19 +44,20 @@ Also bundled under `scripts/`: `preflight.sh`, `arb-monitor.sh`, `funding-analys
44
44
  8. **NEVER manually add `-PERP` suffix** to symbols. Use bare names (`BTC`, `SOL`, `ICP`); the CLI resolves exchange-specific naming.
45
45
  9. **NEVER resubmit after `ORDER_PENDING`** (or any unknown outcome). See "Safety rules".
46
46
 
47
- ### Step 1: Verify install + version
47
+ ### Step 1: Verify install, version, venue health
48
48
 
49
49
  ```bash
50
- perp --version 2>/dev/null || npx -y perp-cli@latest --version # must be >= 0.15.0
50
+ perp --version # must be >= 0.16.0
51
+ perp --json health # keyless venue connectivity
51
52
  ```
52
53
 
53
- If it is missing or older, ask the user before installing/upgrading (`npm install -g perp-cli@latest`) — never install on your own. If `perp` is not on PATH, prefix every command with `npx -y perp-cli@latest`.
54
+ If `perp` is missing or older, STOP and ask the user to install / upgrade it (`npm install -g perp-cli`) — never install it yourself and never switch to `npx`. `health`: `data.healthy` = every OFFICIAL-API venue is up (use this); `allHealthy` also counts unofficial APIs (TxFlow, listed under `unofficial[]`); `skipped[]` = venues with no environment on this network (not probed). Don't use a venue whose `exchanges[].status` is not `"ok"`.
54
55
 
55
56
  ### Step 2: Verify wallet + balance
56
57
 
57
58
  ```bash
58
- perp --json wallet show # confirms configured exchanges
59
- perp --json portfolio -e <venue-id> # per-exchange USDC available; full id (hyperliquid, not hl) — portfolio rejects aliases
59
+ perp --json wallet show # with an OWS wallet, `exchanges: []` is normal — owsActiveWallet serves every venue
60
+ perp --json portfolio -e <venue> # per-exchange perp.available (aliases like hl / pac accepted)
60
61
  ```
61
62
 
62
63
  If any required exchange is missing, register it (user supplies the key):
@@ -125,7 +126,7 @@ Imported keys trade; `funds deposit|withdraw|transfer|bridge`, `wallet manage re
125
126
  **Extended** (`-e extended`, aliases `ext` / `x10`; testnet = Sepolia via `-n testnet`): official public API (api.docs.extended.exchange), READ-ONLY in this version — counted as an official venue in `perp health`. Rules an agent must follow:
126
127
  - Works: `market list|prices|info|book|trades|funding|kline -e extended`, and Extended rows in `perp --json arb scan --rates --include-unverified` (display only — funding is UNVERIFIED: never rank or trade on it). `market list` rows carry `assetClass` (crypto / equity / etf / index / commodity / fx / preIpo; human table "Class" column), `venueSymbol` (wire name, e.g. `TSLA_24_5-USD`), `tickSize`, `minSize`, `tradable` (false while `REDUCE_ONLY` or `isOffHours`), `isRfq`, `tradingHours`.
127
128
  - Symbols: `assetName` without the `_24_5` suffix (`TSLA_24_5-USD` → `TSLA`, `SPX500m-USD` → `SPX500M`); `-e extended market book TSLA-USD` and the wire name also resolve. The crypto `SPX` market is SPX6900, not the S&P 500 (index = `SPX500M`). RWA tickers that are also crypto tickers (PURR = Hyperliquid Strategies Inc., QNT, BB, ON, ADI, BOT), XIAOMI and the crypto SPX are never matched across venues.
128
- - Funding: applied hourly; `fundingRate` in market rows = the current hour's ACCRUING rate (fraction per hour, recomputed every minute, rounded to 6 decimals; `fundingRateKind: "accruing"`, `nextFundingTime`), `market funding` = applied hourly prints (`rateKind: "lastSettled"`, `annualizedPct`). `_24_5` equities print 0 while their underlying is closed (weekends / holidays), so an annualized rate overstates them.
129
+ - Funding: applied hourly; `fundingRate` in market rows = the current hour's ACCRUING rate (fraction per hour, recomputed every minute, rounded to 6 decimals by the venue — no public source is more precise; `fundingRateKind: "accruing"`, `nextFundingTime`), `market funding` = applied hourly prints (`rateKind: "lastSettled"`, `annualizedPct`). `_24_5` equities print 0 while their underlying is closed (weekends / holidays), so an annualized rate overstates them.
129
130
  - Refused with `CAPABILITY_UNSUPPORTED` before any request ("Extended is read-only (market data) in this version; trading is planned for a later release"): every trade / account / portfolio / funds / agent / builder / bot command, also under `--dry-run`. RFQ markets' REST order book is the indicative book.
130
131
 
131
132
  Venue rules for these: `trade limit` defaults to `--tif GTC` on every venue (arcus maps it to GTT; ondo offers GTC|IOC|ALO; FOK is never emulated → `CAPABILITY_UNSUPPORTED` where not offered); market orders on every venue are bounded by `--slippage-bps <n>` → `settings.slippageBps.<venue>` → `settings.defaultSlippageBps` (shipped default 50). Ondo (US, PA) and Arcus (US, CA, GB) print a one-time restricted-region notice on stderr when used with credentials (warn only, never blocks).
@@ -140,30 +141,42 @@ perp --json arb scan --rates # raw funding rates
140
141
  perp --json arb scan --basis [<symbol>] # cross-exchange basis
141
142
  perp --json arb scan --gaps # cross-exchange price gaps
142
143
  perp --json arb scan --hip3 # HIP-3 cross-dex spreads
143
- perp --json arb scan --history <symbol> # historical funding
144
+ perp --json arb scan --history <symbol> # LOCAL snapshots only (written by earlier `arb scan --rates` runs; often `rates: {}`)
145
+ perp --json -e <ex> market funding <symbol> -l 24 # real settled history (newest first; rate per `intervalHours`)
144
146
  perp --json arb scan --compare <symbol> # one symbol across all exchanges
145
147
  perp --json arb scan --positions # funding impact on open positions
146
148
  perp --json arb scan --live --interval 60 # continuous monitoring
147
149
  ```
148
150
 
149
- Common knobs: `--min <pct>`, `--top <n>`, `--hold-days <n>`, `--bridge-cost <usd>`, `--size <usd>`.
151
+ Common knobs: `--min <pct>`, `--top <n>`, `--hold-days <n>` (default 7), `--bridge-cost <usd>`, `--size <usd>`.
152
+
153
+ Prices: `perp --json -e <ex> market mid <SYM>` is the canonical price read; cross-venue: `arb scan --compare <SYM>`. `market prices` takes no symbol (every market). There is no spot price / book read (`market *` are perp markets; `HYPE/USDC`, `@107`, `HYPE-SPOT` → `SYMBOL_NOT_FOUND`), and `arb scan --basis` is cross-venue PERP basis, not spot-perp.
154
+
155
+ **Reading scan rows** — act only on these fields (detail: `references/commands.md` → "Arbitrage"):
156
+ - perp-perp rows (`mode: "perp-perp"`): `longExch` / `shortExch`, `netSpread` / `grossSpread` (= `netSpreadPct` / `grossSpreadPct`, annual %), `estFeesPct` (estimated round trip on BOTH legs incl. 0.1 % slippage — e.g. hl+hl 0.24 %; `perp settings fees show` is the per-fill taker rate it is built from).
157
+ - spot-perp rows (`mode: "spot-perp"`): `spotExchanges[]`, `perpExchange`, `direction`, `netSpread`, `estFeesPct`, `breakEvenDays` — no `longExch` / `shortExch`. Executable ONLY when `direction == "long-spot-short-perp"`: `arb exec <SYM> spot:<one of spotExchanges> <perpExchange> <USD>`. `arb exec spot:` does not look at the funding sign — it always buys spot and shorts the perp, so on a `sell-spot-long-perp` row it would PAY the funding. Never act on `sell-spot-long-perp` rows.
158
+ - `--rates` / `--compare` rows: `longExchange` / `shortExchange` / `maxSpreadAnnual` (all null when fewer than two verified rates), `executable`, `readOnlyLegs`, `unverifiedLegs`, `mixedKinds` (the legs' rates are of different kinds — lastSettled / accruing / predicted); `--rates` top level has `minSpread` / `belowMinSpread`. Act only when `executable === true`. `--compare <unknown>` is `ok:true` with `data.available: false`.
159
+ - **Testnet funding rates and spreads are meaningless** (thousands of % / yr). Never report them as opportunities; do yield analysis on mainnet public reads (keyless, `-n mainnet`).
150
160
 
151
161
  #### HIP-3 dexes (part of Hyperliquid, not a separate venue)
152
162
 
153
163
  HIP-3 dexes are selected on the Hyperliquid venue with the root `--dex <name>` flag; every market / account / trade command works the same way. Same account and wallet as native Hyperliquid perps.
154
164
 
155
165
  ```bash
156
- perp --json -e hyperliquid market hip3 # list deployed dexes (name, markets)
166
+ perp --json -e hyperliquid market hip3 # deployed dexes: name, deployer, assets, delistedAssets, delisted
167
+ perp --json -e hyperliquid market list --hip3 # native + every HIP-3 dex market
157
168
  perp --json -e hyperliquid --dex xyz market list # markets on dex "xyz"
158
169
  perp --json -e hyperliquid --dex xyz market info GOLD # symbols WITHOUT the "xyz:" prefix
159
170
  perp --json -e hyperliquid --dex xyz account positions # positions on that dex only
171
+ perp --json -e hyperliquid account positions --hip3 # native + every HIP-3 dex
160
172
  perp --json -e hyperliquid --dex xyz --dry-run trade market GOLD buy 0.01
161
173
  ```
162
174
 
163
175
  - `--dex` with any other `-e` venue → `INVALID_PARAMS` (never ignored).
164
176
  - A dex symbol without `--dex` (e.g. `-e hyperliquid market mid xyz:GOLD`) → `SYMBOL_NOT_FOUND` with remediation `--dex xyz`; it is never read from the native dex.
165
- - `portfolio --dexes xyz,…` adds HIP-3 dex balances; builder fees are never attached on HIP-3.
166
- - MCP tools cover native Hyperliquid perps only — use the CLI for HIP-3.
177
+ - `portfolio --dexes` works only with `--serve` (web dashboard); for HIP-3 positions use `account positions --hip3` / `--dex <name>` or `--address`. Builder fees are never attached on HIP-3.
178
+ - Symbols: input is bare (`BTC`; HIP-3 `TSLA` + `--dex xyz`). Output differs: market rows are plain, keyed HL native position / order rows show `<COIN>-PERP`, HIP-3 rows `xyz:TSLA` — pass the bare name back (`BTC`, `TSLA` + `--dex xyz`).
179
+ - MCP tools cover native Hyperliquid perps only, except `get_positions_by_address` (reads every HIP-3 dex) — use the CLI for the rest of HIP-3.
167
180
 
168
181
  #### Options market data (Derive, read-only)
169
182
 
@@ -182,26 +195,46 @@ perp --json -e derive options quote ETH-20261225-3500-P # one op
182
195
  For arb:
183
196
 
184
197
  ```bash
185
- perp --json portfolio -e <longEx> # check available USDC (long leg)
186
- perp --json portfolio -e <shortEx> # check available USDC (short leg)
198
+ perp --json portfolio -e <longEx> # perp.available (long leg)
199
+ perp --json portfolio -e <shortEx> # perp.available (short leg)
187
200
  perp --json --dry-run arb exec <SYM> <longEx> <shortEx> <USD>
188
201
  ```
189
202
 
203
+ Spot-perp (`spot:<venue>` long leg, only for `direction == "long-spot-short-perp"` rows): the spot leg needs the full spot notional in the spot venue's quote (`perp --json -e <venue> trade spot-balance`; separate-margin venues transfer the shortfall perp→spot) plus perp margin on the perp leg — the dry-run checks both and refuses an empty book or a > 5% spot/perp price gap.
204
+
190
205
  For a single trade:
191
206
 
192
207
  ```bash
208
+ perp --json -e <ex> market info <SYM> # markPrice, stepSize (lot), maxLeverage
193
209
  perp --json -e <ex> trade check <SYM> <SIDE> <SIZE> --leverage <N>
194
- perp --json --dry-run -e <ex> trade buy <SYM> <SIZE> --smart
210
+ perp --json --dry-run -e <ex> trade buy <SYM> <SIZE> # market entry
211
+ perp --json --dry-run -e <ex> trade buy <SYM> <SIZE> --tp <PX> --sl <PX> # entry + TP/SL
212
+ perp --json --dry-run -e <ex> trade buy <SYM> <SIZE> --smart # IOC at best ask + 1 tick (no TP/SL)
195
213
  ```
196
214
 
197
215
  > `trade check` does NOT read exchange-set leverage. Always pass `--leverage` explicitly.
198
216
  >
199
- > `--smart` (IOC at best bid/ask ± 1 tick) exists only on pacifica / hyperliquid / lighter / aster, and is refused (`CAPABILITY_UNSUPPORTED`) together with `--tp`/`--sl` or `--client-id`/`--auto-id`.
217
+ > `--tp` / `--sl` are ABSOLUTE trigger prices (not %). Market entries: every venue (venues that place TP/SL as separate orders need a market / IOC entry); `trade limit --tp/--sl`: ondo / arcus on any entry, elsewhere only with `--tif IOC`. TP/SL on an already open position: `trade tpsl <SYM> long|short --tp <PX> --sl <PX>` (side = the position's side).
218
+ >
219
+ > `--smart` (IOC at best bid/ask ± 1 tick) exists only on pacifica / hyperliquid / lighter / aster, and is refused (`CAPABILITY_UNSUPPORTED`) together with `--tp`/`--sl` or `--client-id`/`--auto-id` — need TP/SL → plain market entry (or `--smart`, then `trade tpsl`).
200
220
  >
201
221
  > Pacifica basket (pair trade): `perp --json --dry-run -e pacifica trade atomic --long BTC:50 --short ETH:50 --usd 1000` — one batch of market orders, NOT all-or-nothing (a leg can fill while another is refused → `ORDER_PARTIAL`; an unconfirmed leg → `ORDER_PENDING` + quarantine). A batch failure other than HTTP 400 / 429 quarantines every leg. Pacifica's Chase / OCO / Trailing Stop / Swarm / Trigger Swarm / Conditional orders have no documented API / SDK path (as of 2026-10-19); nearest here: `trade twap` (≈ Swarm) and `trade tpsl` (≈ OCO bracket exit).
202
222
 
203
223
  Show the dry-run output to the user. Wait for confirmation.
204
224
 
225
+ #### Minimum order size and tick (not in `market info`; `trade check` and `--dry-run` do NOT enforce the minimum)
226
+
227
+ | Venue | Min order value (USD notional) |
228
+ |---|---|
229
+ | hyperliquid | $10 (also spot; HIP-4 outcomes: 10 quote tokens) |
230
+ | pacifica | $10 (per market `min_order_size`) |
231
+ | lighter, lighter-rh | $10 (per market `min_quote_amount`; a few markets 0) |
232
+ | aster | $5 (`MIN_NOTIONAL`) |
233
+ | arcus | $5 (`minOrderNotional`; reduce-only exempt; perp-cli refuses below it, `SIZE_TOO_SMALL`) |
234
+ | ondo, qfex | unknown (not published) |
235
+
236
+ Values read from the venues' public market data on 2026-10-26; keyless MCP `get_markets` (no credentials configured) returns them per market as `minNotional`, with `tickSize` / `minSize`. **Default smallest order = $15 notional** (on every venue, including the $5 ones and the unknown ones): `mark` = `market mid <SYM>`, `step` = `stepSize` from `market info`; `size = ceil(15 / mark / step) × step`, then `trade check` + dry-run. The $15 buffer over the $10 venue minimum absorbs price moves between sizing and the fill, step rounding and fees; below the venue minimum the live order is rejected. Use the bare venue minimum only when the user explicitly asks for it. Anything that splits a position must keep every piece ≥ $15 too: `trade reduce 50` / `scale-tp` / partial `tpsl --size` need a position of ≥ $30 (≥ $15 × number of pieces), and an arb's matched size must clear $15 on both legs. Tick: off-grid limit / trigger prices are refused with `INVALID_TICK` on the live send (never rounded, nothing sent) — Hyperliquid: ≤ 5 significant figures; elsewhere take `tickSize` from keyless MCP `get_markets` or the price steps of `market book <SYM>`.
237
+
205
238
  ### Step 5: Execute
206
239
 
207
240
  After explicit user confirmation:
@@ -213,15 +246,29 @@ After explicit user confirmation:
213
246
  perp --json arb exec <SYM> <longEx> <shortEx> <USD> --smart
214
247
 
215
248
  # Spot+perp arb (spot has 0 funding cost; spot:<venue> = hl, lt, lrh, aster, ondo)
249
+ # ONLY for a spot-perp scan row with direction == "long-spot-short-perp": buys spot, shorts the perp.
216
250
  perp --json arb exec <SYM> spot:hl hl <USD>
217
251
  perp --json arb exec <SYM> spot:lt pac <USD>
218
252
 
219
253
  # Single trade
220
254
  perp --json -e <ex> trade buy <SYM> <SIZE> --smart
221
- perp --json -e <ex> trade sell <SYM> <SIZE> --smart
255
+ perp --json -e <ex> trade sell <SYM> <SIZE> --tp <PX> --sl <PX>
222
256
  perp --json -e <ex> trade split <SYM> buy <USD> --max-slippage 0.5
223
257
  ```
224
258
 
259
+ #### Orders: limit / status / edit / cancel
260
+
261
+ ```bash
262
+ perp --json -e <ex> trade limit <SYM> buy|sell <PRICE> <SIZE> [--tif GTC|IOC|FOK|ALO] [--reduce-only] # default GTC
263
+ perp --json -e <ex> account orders # open orders + ids
264
+ perp --json -e <ex> trade status <ORDER_ID> [--symbol <SYM>] # --symbol required on ondo / arcus / qfex
265
+ perp --json -e <ex> trade edit <SYM> <ORDER_ID> <PRICE> <SIZE> # SIZE = new open (unfilled) size
266
+ perp --json -e <ex> trade cancel <SYM> <ORDER_ID> # one order
267
+ perp --json -e <ex> trade cancel <SYM> # every order on that symbol
268
+ ```
269
+
270
+ All of these writes take `--dry-run`. **`trade edit` may return a NEW `orderId` — always continue with the id it returns**: pacifica (ALO → native edit, GTC / TOB → cancel+replace; new id either way, TIF kept), ondo (cancel+replace), qfex (venue assigns a new id); hyperliquid / lighter / lighter-rh / aster / arcus amend natively — use the returned id anyway. `trade edit --tif` only on ondo / pacifica.
271
+
225
272
  HL spot uses U-tokens (`BTC→UBTC`, `ETH→UETH`, `SOL→USOL`) — auto-resolved.
226
273
 
227
274
  ### Step 6: Monitor
@@ -231,8 +278,14 @@ perp --json arb status # open arb positions, PnL, f
231
278
  perp --json portfolio # cross-exchange equity + risk
232
279
  perp --json risk status # canTrade, level, violations
233
280
  perp --json risk liquidation-distance # % from liq for ALL positions
281
+ perp --json -e <ex> account positions --address <ADDR> [--symbol BTC] [--account-index <n>] # keyless, ANY account
282
+ perp --json -e <ex> account balance --address <ADDR> [--account-index <n>] # keyless balances of ANY account
234
283
  ```
235
284
 
285
+ `arb status` reads every configured venue and fails as a whole (`EXCHANGE_ERROR`) when one venue's read fails — there is no venue filter; check the venues one by one with `perp --json -e <ex> account positions` and report which one failed. Never read the failure as "no positions".
286
+
287
+ `account positions --address` (keyless, nothing signed; without `-e`: every venue that supports it): hyperliquid (0x; native + every HIP-3 dex, rows carry `dex`), lighter / lighter-rh (0x; every account of the address, rows carry `accountIndex`, narrow with `--account-index`), pacifica (Solana address), risex (0x). Other venues → `CAPABILITY_UNSUPPORTED`. MCP `get_positions_by_address` returns the same rows (HIP-3 included). `account balance --address` (same venues and address rules; MCP `get_balance_by_address`): `data = { exchange, address, balance, spot }` — `balance` = `{ equity, available, marginUsed, unrealizedPnl }` (+ Pacifica `usdcBalance` / `borrowedUsdc` / `pendingInterest` / `availableToWithdraw`), `spot` = token rows or null (RISEx). Hyperliquid: `accountMode` decides equity (unified / portfolio → the spot collateral row; standard / default → perp `accountValue`; read `meta.notes`), `dexes` = HIP-3 dexes with a non-zero value, a failed dex → `meta.errors["hip3:<dex>"]` + `meta.warnings` (unknown, not zero). Lighter: top-level `balance` / `spot` null, one row per account in `accounts: [{ accountIndex, balance, spot }]`; no account → `[]` + note. `account balance` WITHOUT `--address` is the renamed-command error — your own balance is `perp portfolio`.
288
+
236
289
  If `risk status.canTrade === false`, do NOT open new positions. If liquidation distance falls below the user's `--min-liq-distance`, recommend reducing position size.
237
290
 
238
291
  For continuous monitoring, run `bash scripts/arb-monitor.sh --json`.
@@ -247,12 +300,14 @@ perp --json arb close <SYM> --smart # IOC limits
247
300
  perp --json arb close <SYM> --force # quarantined symbol — only after the user checked positions
248
301
  perp --json arb close <SYM> --state-only --yes # drop a stale state entry (arb status staleStateEntries); sends no order
249
302
 
250
- # Single trade
303
+ # Single trade (dry-run first, then confirm)
251
304
  perp --json -e <ex> trade close <SYM> # close one symbol
252
305
  perp --json -e <ex> trade close-all # close all positions on this exchange
253
- perp --json -e <ex> trade flatten # close ALL + cancel ALL orders
306
+ perp --json -e <ex> trade flatten # cancel ALL orders, then close ALL positions
254
307
  ```
255
308
 
309
+ `trade close` / `close-all` close positions only — perp-cli does not cancel resting TP/SL / stop / limit orders (QFEX lists the leftovers as a WARNING). After a close, run `account orders` and cancel what is left (`trade cancel <SYM> <id>`), or use `trade flatten`, which cancels every order on the venue first.
310
+
256
311
  ### Pacifica Print and vaults (`perp print`, `perp vault`)
257
312
 
258
313
  Pacifica-only, details in `references/commands.md`. Reads first (`print games`, `print quote`, `print positions`, `vault list|info|positions`); every write is `--dry-run` first and needs the user's confirmation:
@@ -328,7 +383,7 @@ Background jobs inherit the parent's `-n`, `--dry-run`, `-e`, `--ows`, `-w`, `--
328
383
  - Single position notional < **80%** of that exchange's available balance.
329
384
  - Leverage 1–3x for arb; never above 5x for arb positions.
330
385
  - `arb exec` sizes the short to the verified long fill and always reconciles; still check `arb status` (`unconfirmedPairs`, `staleStateEntries`) afterwards.
331
- - ALWAYS follow `longExch`/`shortExch` from `arb scan` — NEVER reverse direction.
386
+ - ALWAYS follow `longExch`/`shortExch` (perp-perp) or `longExchange`/`shortExchange` (`--rates` / `--compare`) — NEVER reverse direction. Spot-perp: only `direction == "long-spot-short-perp"`.
332
387
  - NEVER enter if `netSpread <= 0` or `netSpread < estimated round-trip slippage`.
333
388
  - Capital that's mid-bridge is "at risk" and unhedged — factor it in.
334
389
 
@@ -355,6 +410,7 @@ perp --json arb status
355
410
  ### Example 2: "ETH spot+perp arb, $100"
356
411
 
357
412
  ```bash
413
+ perp --json arb scan --mode spot-perp --min 0 # ETH row must say direction "long-spot-short-perp"
358
414
  perp --json --dry-run arb exec ETH spot:hl hl 100
359
415
  # → show dry-run, ask confirmation
360
416
  perp --json arb exec ETH spot:hl hl 100
@@ -366,11 +422,11 @@ perp --json arb close ETH --spot-exch hl --perp-exch hl
366
422
  ### Example 3: "Long SOL 0.5 on Hyperliquid with 2x leverage"
367
423
 
368
424
  ```bash
369
- perp --json -e hl wallet manage margin SOL isolated # use isolated margin for new trade
370
- perp --json -e hl trade leverage SOL 2 --isolated
371
425
  perp --json -e hl trade check SOL buy 0.5 --leverage 2
426
+ perp --json --dry-run -e hl trade leverage SOL 2 --isolated
372
427
  perp --json --dry-run -e hl trade buy SOL 0.5 --smart
373
- # → show dry-run, ask confirmation
428
+ # → show both dry-runs (isolated 2x + the order), ask confirmation; only then:
429
+ perp --json -e hl trade leverage SOL 2 --isolated
374
430
  perp --json -e hl trade buy SOL 0.5 --smart
375
431
  perp --json -e hl account positions
376
432
  ```
@@ -378,9 +434,10 @@ perp --json -e hl account positions
378
434
  ### Example 4: "Move 500 USDC from Pacifica to Hyperliquid"
379
435
 
380
436
  ```bash
381
- perp --json funds withdraw pacifica 500
437
+ perp --json --dry-run funds withdraw pacifica 500
382
438
  perp --json funds bridge quote --from solana --to arbitrum --amount 500
383
- # → show fee, ETA, ask confirmation
439
+ # → show the withdraw plan + bridge fee / ETA, ask confirmation; only then:
440
+ perp --json funds withdraw pacifica 500
384
441
  perp --json funds bridge send --from solana --to arbitrum --amount 500
385
442
  perp --json funds bridge status <orderId> # poll until completed
386
443
  perp --json funds deposit hyperliquid 500
@@ -423,7 +480,10 @@ Every response is `{ "ok": true, "data": ... }` or `{ "ok": false, "error": { "c
423
480
  | `RATE_LIMITED` / `EXCHANGE_UNREACHABLE` | Throttled / API down (reads) | Wait 5–10s (or `retryAfterMs` when present — Pacifica sets it from its credit headers), retry once; then skip that venue. |
424
481
  | `INSUFFICIENT_BALANCE` | Not enough collateral on that venue | Reduce size or move funds first (user-confirmed). |
425
482
  | `SYMBOL_NOT_FOUND` | Not listed on this venue | `market list`. Don't add `-PERP`. |
426
- | `SIZE_TOO_SMALL` | Below venue minimum (HL TWAP: $100 total) | Compute `size × price`; raise size. |
483
+ | `SIZE_TOO_SMALL` | Below venue minimum (HL TWAP: $100 total) | Compute `size × price`; raise size (minimum table in Step 4). |
484
+ | `UNKNOWN` | Unclassified failure (the message matched no known code) | Read `error.message`. After a write: treat the outcome as unknown — check `account orders` / `account positions` / `portfolio` before anything else, never resubmit blindly; report to the user. |
485
+
486
+ Lighter / Lighter RH "account not found" (venue code `21100`): the address has no account on that venue / network — the user must fund (create) the account first, then `perp wallet agent approve lighter` (or `lighter-rh`).
427
487
 
428
488
  `--client-id` (`trade market/buy/sell/limit`): an id already recorded in `~/.perp/client-ids.jsonl` (and not marked failed) returns `ok:true` with `data.duplicate: true` and sends nothing — local tracking only, not a venue check (it is NOT a `DUPLICATE_ORDER` error). Formats: Pacifica a full UUID, Hyperliquid `0x` + 32 hex; QFEX refuses `--client-id` (use `--auto-id`); `--smart` + client id → `CAPABILITY_UNSUPPORTED`.
429
489
 
@@ -475,7 +535,9 @@ qfex: `builder.qfex <uuid>` is a fee share (no extra fee, no approval; mainnet o
475
535
 
476
536
  ## MCP Server
477
537
 
478
- The package also ships a 29-tool MCP server (no API keys required for read-only market data — `get_markets`, `get_orderbook`, `get_funding_rates`, `get_prices`, `get_outcome_markets`, `get_outcome_view`, `get_outcome_book`, `get_option_expiries`, `get_option_chain`, `get_option_quote` (Derive options), the read-only Pacifica Print / vault tools `pacifica_print_products`, `pacifica_print_quote`, `pacifica_print_positions`, `pacifica_vaults`, plus 15 account/advisor tools):
538
+ The package also ships a 30-tool MCP server (no API keys required for read-only market data — `get_markets`, `get_orderbook`, `get_funding_rates`, `get_prices`, `get_outcome_markets`, `get_outcome_view`, `get_outcome_book`, `get_option_expiries`, `get_option_chain`, `get_option_quote` (Derive options), the read-only Pacifica Print / vault tools `pacifica_print_products`, `pacifica_print_quote`, `pacifica_print_positions`, `pacifica_vaults`, plus 16 account/advisor tools, incl. keyless `get_positions_by_address`):
539
+
540
+ MCP `portfolio` totals (`totalEquity`, `totalAvailable`, `totalMarginUsed`, `totalUnrealizedPnl`, `riskMetrics.marginUtilization`) are `null` when no balance was read — check `accountState` (`"ok"` | `"unread"` = credentials but no balance read | `"noAccount"`) and `totalsCover` (the venues the totals include) before quoting a total. The CLI `portfolio` shape differs: `totals.{equity,marginUsed,marginPct,funding24h,fundingIncomplete}`, `risk.{level,marginPct}`.
479
541
 
480
542
  MCP network: `PERP_NETWORK=mainnet|testnet` (validated; unset = mainnet); every result's `meta.network` says which. The only write tools, `trade_execute` / `trade_close`, run the same local risk gate as `perp trade` (no override over MCP), refuse non-reduce-only orders on quarantined symbols, and log every order.
481
543
 
@@ -490,4 +552,6 @@ MCP network: `PERP_NETWORK=mainnet|testnet` (validated; unset = mainnet); every
490
552
  }
491
553
  ```
492
554
 
555
+ **`perp-guardrail`** (third binary): not run by hand — the OWS Policy Engine spawns it before an agent API key signs anything; it allows / denies by chain + contract whitelist, per-tx and daily USD limits, withdrawal limits and blocked selectors. Set it up through `perp wallet setup` or `perp wallet policy create --perp-defaults`; it is a second line of defence, not a replacement for perp-cli's risk gate.
556
+
493
557
  [![Glama MCP server](https://glama.ai/mcp/servers/hypurrquant/perp-cli/badges/score.svg)](https://glama.ai/mcp/servers/hypurrquant/perp-cli)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypurrquant/perp-cli-skill",
3
- "version": "0.5.3",
3
+ "version": "0.16.0",
4
4
  "description": "AI agent skill for perp-cli — multi-DEX perpetual futures trading via CLI",
5
5
  "keywords": [
6
6
  "ai-skill",
@@ -12,6 +12,19 @@
12
12
  "hyperliquid",
13
13
  "pacifica",
14
14
  "lighter",
15
+ "aster",
16
+ "lighter-rh",
17
+ "ondo",
18
+ "arcus",
19
+ "qfex",
20
+ "risex",
21
+ "grvt",
22
+ "extended",
23
+ "variational",
24
+ "txflow",
25
+ "derive",
26
+ "options",
27
+ "hip-3",
15
28
  "defi",
16
29
  "arbitrage",
17
30
  "funding-rate"
@@ -30,6 +43,6 @@
30
43
  "scripts"
31
44
  ],
32
45
  "peerDependencies": {
33
- "perp-cli": ">=0.5.0"
46
+ "perp-cli": ">=0.16.0"
34
47
  }
35
48
  }
@@ -38,9 +38,9 @@ OWS_PASSPHRASE=<pp> perp --json wallet setup --name <name> --max-tx-usd <usd> --
38
38
  ### ALWAYS use these (non-interactive, agent-safe):
39
39
  ```bash
40
40
  printf '%s' "$KEY" | OWS_PASSPHRASE=<pp> perp --json wallet set <exchange> # import key (stdin) into OWS vault → active wallet
41
- perp --json wallet generate evm # generate EVM wallet
42
- perp --json wallet generate solana # generate Solana wallet
43
- perp --json wallet show # check configured wallets
41
+ OWS_PASSPHRASE=<pp> perp --json wallet generate [name] [--words 12|24] # new multi-chain OWS wallet (EVM + Solana)
42
+ perp --json health # keyless venue connectivity: use data.healthy
43
+ perp --json wallet show # check configured wallets (OWS wallet: exchanges: [] is normal)
44
44
  perp --json wallet list # list named wallets
45
45
  perp --json wallet balance # gas token + USDC/USDT per chain (Arbitrum, Ethereum, Base, BNB, Robinhood USDG, Solana); failed reads → balance null + error
46
46
  perp --json portfolio -e <EX> # per-exchange balance + positions (account balance was renamed in v0.12)
@@ -61,9 +61,8 @@ perp --json risk check --notional <$> --leverage <L> # pre-trade risk check
61
61
 
62
62
  ### Single Exchange Setup
63
63
  ```bash
64
- # 1. Install
65
- npm install -g perp-cli@latest
66
- # or use npx -y perp-cli@latest as the prefix
64
+ # 1. Install — ASK THE USER; they run it (never install perp-cli yourself, never fall back to npx)
65
+ # the user runs: npm install -g perp-cli → then check: perp --version (must be >= 0.16.0)
67
66
 
68
67
  # 2. Register wallet (user provides key — on stdin, never argv)
69
68
  printf '%s' "$USER_PRIVATE_KEY" | OWS_PASSPHRASE=<pp> perp --json wallet set hl
@@ -342,13 +341,17 @@ Orders, cancels, edits, leverage, withdraw / deposit / bridge / transfer: `ORDER
342
341
 
343
342
  ## Symbol Naming Across Exchanges
344
343
 
345
- Symbols are auto-resolved by the CLI. **Always use bare symbols** (e.g., `BTC`, `SOL`, `ICP`) — the CLI handles exchange-specific naming automatically:
344
+ Symbols are auto-resolved by the CLI. **Always INPUT bare symbols** (e.g., `BTC`, `SOL`, `ICP`; HIP-3: `TSLA` with `-e hyperliquid --dex xyz`) — no `-PERP` suffix, no `xyz:` prefix. OUTPUT rows are not uniform:
346
345
 
347
- | Input | Pacifica | Hyperliquid | Lighter | Aster |
348
- |-------|----------|-------------|---------|-------|
349
- | `ICP` | → `ICP` | → `ICP-PERP` | → `ICP` | → `ICP` |
350
- | `BTC` | → `BTC` | → `BTC` | → `BTC` | → `BTC` |
351
- | `SOL` | → `SOL` | → `SOL` | → `SOL` | → `SOL` |
346
+ | Row kind | Example | Notes |
347
+ |----------|---------|-------|
348
+ | `market list` / `info` / `mid`, `arb scan` | `BTC` | plain on every venue (HIP-3 market rows: `xyz:TSLA`, wire coin in `venueSymbol`) |
349
+ | Keyed Hyperliquid native positions / orders / history (`account …` with your key) | `BTC-PERP` | internal display name — strip `-PERP` to compare with market rows |
350
+ | HIP-3 position / order rows | `xyz:TSLA` | dex prefix; also `account positions --address` rows (with `dex: "xyz"`) |
351
+ | `account positions --address` (public) native HL rows | `BTC` | plain, `dex: null` |
352
+ | Pacifica / Lighter / Aster / other venues | `BTC` | plain |
353
+
354
+ Why: the CLI resolves your bare input to each venue's own name, but keyed Hyperliquid rows keep the adapter's internal `<COIN>-PERP` key. When feeding a row back into a command, pass the bare name (`BTC`, `TSLA` + `--dex xyz`).
352
355
 
353
356
  - `arb scan` returns bare symbols — pass them directly to trade/leverage commands on any exchange.
354
357
  - Do NOT manually add `-PERP` suffix — the CLI resolves this automatically.
@@ -4,7 +4,7 @@ All commands support `--json` for structured output. Always use `--json` when ca
4
4
 
5
5
  ## Global Flags
6
6
 
7
- `--json` (required for agents) | `-e <venue>` | `-n mainnet|testnet` | `--dry-run` (only commands whose `--help` says "supports --dry-run"; others refuse with `INVALID_PARAMS`) | `--fields <f1,f2>` | `--ndjson` | `-w, --wallet <name>` | `--ows <name>` (OWS wallet) | `--no-agent` (skip agent-key routing) | `--no-builder` | `--dex <name>` (HIP-3, Hyperliquid)
7
+ `--json` (required for agents) | `-e <venue>` | `-n mainnet|testnet` | `--dry-run` (honored by: every `trade` write, `arb exec|close|auto|rebalance`, `funds deposit|withdraw|transfer|faucet|bridge send|bridge exchange|rebalance execute|address-book add`, `outcome buy|sell`, `print deposit|cancel`, `vault deposit|withdraw`, `wallet builder approve|revoke`, `wallet manage referral set`, `strategy run`, `strategy plan execute` — `--help` does not always say so; every other command, read-only ones included, refuses it with `INVALID_PARAMS` = unsupported, nothing ran) | `--fields <f1,f2>` | `--ndjson` | `-w, --wallet <name>` | `--ows <name>` (OWS wallet) | `--no-agent` (skip agent-key routing) | `--no-builder` | `--dex <name>` (HIP-3, Hyperliquid)
8
8
 
9
9
  Venues (`-e`, id | aliases): `pacifica|pac`, `hyperliquid|hl`, `lighter|lt`, `lighter-rh|lrh|rh`, `aster|ast`, `ondo|ondo-perps`, `arcus`, `qfex|qf`, `risex|rise` (READ-ONLY in this release — market data + account reads; trading is planned for a later release, every trade / agent / bot write refuses with CAPABILITY_UNSUPPORTED), `txflow|txf` (market data only, UNOFFICIAL API — every write refuses with CAPABILITY_UNSUPPORTED), `variational|var|omni` (market data only, official API, RFQ venue: `market book` = indicative RFQ quotes, `market funding` = current terms — every write refuses with CAPABILITY_UNSUPPORTED), `grvt|grv` (market data only in this version, official API — every write refuses with CAPABILITY_UNSUPPORTED), `extended|ext|x10` (Extended on Starknet, official API, market data only in this version — every write refuses with CAPABILITY_UNSUPPORTED). Default = `settings.defaultExchange`, else `pacifica` — always pass `-e`.
10
10
  `-k <key>` is rejected (keys only via stdin / OWS vault). `--passphrase` is deprecated → `OWS_PASSPHRASE` env or stdin.
@@ -12,9 +12,11 @@ Venues (`-e`, id | aliases): `pacifica|pac`, `hyperliquid|hl`, `lighter|lt`, `li
12
12
  ## Market Data (read-only, safe)
13
13
  ```bash
14
14
  perp --json -e <EX> market list # all markets with prices, funding, volume
15
- perp --json market prices # cross-exchange price comparison
16
- perp --json -e <EX> market mid <SYMBOL> # mid price (fast)
17
- perp --json -e <EX> market info <SYMBOL> # mark/index price, funding, volume, OI, max leverage
15
+ perp --json market prices # cross-exchange price comparison (every market; takes no symbol)
16
+ perp --json -e <EX> market mid <SYMBOL> # mid price (fast) — the canonical single-symbol price read
17
+ perp --json -e <EX> market info <SYMBOL> # mark/index price, funding, volume, OI, max leverage, stepSize (no tickSize / min notional — see SKILL.md Step 4)
18
+ # No spot market reads: `market *` are perp markets (HYPE/USDC, @107, HYPE-SPOT → SYMBOL_NOT_FOUND). Spot balances / orders:
19
+ # `trade spot-balance`, `trade spot-orders` (keyed). `arb scan --basis` = cross-venue PERP basis, not spot-perp.
18
20
  perp --json -e <EX> market book <SYMBOL> # orderbook (bids/asks)
19
21
  perp --json -e <EX> market trades <SYMBOL> # recent trades
20
22
  perp --json -e <EX> market funding <SYMBOL> # funding rate history
@@ -24,10 +26,22 @@ perp --json -e hyperliquid --dex <DEX> market list # one HIP-3 dex's m
24
26
  perp --json -e hyperliquid --dex <DEX> market book <SYMBOL> # any market/account/trade command takes --dex the same way
25
27
  ```
26
28
 
29
+ Hyperliquid read-path notes:
30
+ - **Venue caps that cannot be paged are refused** (`INVALID_PARAMS` naming the cap; never fewer rows than asked, silently). `trades`: the venue serves only the last 10 trades — the default `--limit` is min(20, 10) = 10, an explicit `--limit` above 10 is refused. `book`: at most 20 levels per side — `-d` above 20 is refused (`-d` cuts JSON too). `kline`: only the most recent 5000 candles per interval exist — a `--start` before now − 5000 × interval is refused before any request, naming the earliest allowed start. `backtest grid --days N` clamps its start to that window and reports `dataFrom` / `truncated`.
31
+ - **kline intervals:** `1m,3m,5m,15m,30m,1h,2h,4h,8h,12h,1d,3d,1w,1M` (anything else → `INVALID_PARAMS`, not retryable). `1M` candles are **30-day buckets**, not calendar months; `1w` candles open **Thursday 00:00 UTC**. Each candle carries `closed` (false on the in-progress last candle).
32
+ - **funding:** `--limit N` = the last N hourly settlements (paged over the venue's 500-row cap; max 5000).
33
+ - **Delisted markets** (meta `isDelisted`, e.g. `MATIC`, every asset of `--dex km`) → `SYMBOL_NOT_FOUND` with `details.reason: "delisted"` on `info` / `trades` / `funding` / `book` / `kline`; orders / positions / history still resolve them. `market hip3` lists live assets only (`assets`), plus `delistedAssets` and `delisted: true` for a dex with no live asset; `deployer` comes from `perpDexs`.
34
+ - **Symbol naming:** `market list` / `info` rows use the plain coin `BTC` (HIP-3: `xyz:XYZ100`; the wire coin is in `venueSymbol`), as `market trades` rows and the WS codec. `-PERP` arguments still resolve. Keyed `account positions` rows still show `BTC-PERP`; strip `-PERP` to compare.
35
+ - **marginTiers:** a market on a single-tier table (`marginTableId` < 50) reports `[{ lowerBound: 0, maxLeverage: <id> }]` (docs "Margin tiers"), not null.
36
+
27
37
  ## Account (read-only, safe)
28
38
  ```bash
29
39
  perp --json portfolio -e <VENUE_ID> # perp balance + spot holdings + 24h funding; venue id or alias (hl, lt, …)
30
40
  perp --json -e <EX> account positions # open positions
41
+ perp --json -e <EX> account positions --address <ADDR> # ANY account's open positions, keyless (public data; nothing signed)
42
+ perp --json account positions --address <0xADDR> # every supporting venue: { venues, errors?, notes? }
43
+ perp --json -e <EX> account balance --address <ADDR> # ANY account's balances + spot, keyless (same venues; Lighter: per account, --account-index)
44
+ perp --json account balance --address <0xADDR> # every supporting venue: { venues, errors?, notes? }
31
45
  perp --json -e <EX> account orders # open/pending orders
32
46
  perp --json -e <EX> account history # order history
33
47
  perp --json -e <EX> account trades # trade fill history
@@ -38,6 +52,14 @@ perp --json -e <EX> account pnl # realized + unrealized + funding
38
52
  perp --json -e <EX> account twap-orders # active TWAP orders
39
53
  perp --json portfolio # cross-exchange unified view
40
54
  # funding24h is null (with fundingError) when a venue's funding history is unreadable; totals.fundingIncomplete = true then
55
+ # --address (public-address positions): hyperliquid / lighter / lighter-rh / risex take a 0x address, pacifica a base58
56
+ # Solana address (a wrong format → INVALID_PARAMS before any request); other venues → CAPABILITY_UNSUPPORTED
57
+ # (feature publicPositions). Rows = the account positions rows with plain symbols, plus:
58
+ # hyperliquid: native + EVERY HIP-3 dex (one read each), `dex: null | "<dex>"`; a dex that fails is in
59
+ # meta.errors["hip3:<dex>"] + meta.warnings — its rows are missing, the others are kept (exit 0).
60
+ # lighter / lighter-rh: every account (sub-account) of the address, `accountIndex` on each row; zero-size rows
61
+ # dropped; --account-index <n> narrows (not an account of the address → INVALID_PARAMS). No account → [] + meta.notes.
62
+ # --symbol <SYM> filters (GOLD matches xyz:GOLD). meta: { address, source: "public" }. MCP: get_positions_by_address.
41
63
  perp --json portfolio --arb # full dashboard with arb top 5
42
64
  ```
43
65
 
@@ -61,10 +83,13 @@ perp --json -e <EX> trade market <SYM> buy <SIZE> --split # split via flag
61
83
  perp --json -e <EX> trade limit <SYMBOL> <buy|sell> <PRICE> <SIZE> [--tif GTC|IOC|FOK|ALO] # default GTC on every venue; off-grid price → INVALID_TICK (never rounded)
62
84
  perp --json -e <EX> trade stop <SYMBOL> <SIDE> <SIZE> <STOP_PRICE> # reduce-only by default; --no-reduce-only to open (refused on ondo / qfex)
63
85
  perp --json -e <EX> trade tpsl <SYMBOL> <long|short> --tp <P> --sl <P> # positionSide = the open position's side
64
- perp --json -e <EX> trade buy <SYMBOL> <SIZE> --tp <P> --sl <P> # entry protected by TP/SL (verified fill)
86
+ perp --json -e <EX> trade buy <SYMBOL> <SIZE> --tp <P> --sl <P> # entry protected by TP/SL (verified fill); absolute prices, not %; not with --smart
87
+ # trade limit --tp/--sl: ondo / arcus any entry, other venues --tif IOC only
65
88
 
66
89
  # Order management
67
- perp --json -e <EX> trade edit <SYMBOL> <ORDER_ID> <PRICE> <SIZE>
90
+ perp --json -e <EX> trade edit <SYMBOL> <ORDER_ID> <PRICE> <SIZE> # SIZE = new open size; may return a NEW orderId — use it
91
+ # pacifica: TIF from the order's client id — ALO native edit, GTC / TOB cancel+replace (new id either way);
92
+ # ondo: cancel+replace; qfex: venue assigns a new id (client id kept); --tif only on ondo / pacifica
68
93
  perp --json -e <EX> trade cancel <SYMBOL_OR_ORDER_ID> [orderId]
69
94
  perp --json -e <EX> trade cancel-all
70
95
  perp --json -e <EX> trade cancel-stop <SYMBOL> <STOP_ORDER_ID> # pacifica / qfex only; other venues: trade cancel
@@ -82,6 +107,7 @@ perp --json -e <EX> trade check <SYM> <SIDE> <SIZE> --leverage 3
82
107
  perp --json -e <EX> trade close <SYMBOL> # close single position
83
108
  perp --json -e <EX> trade close-all # close all positions
84
109
  perp --json -e <EX> trade flatten # cancel all orders + close all positions
110
+ # close / close-all do NOT cancel resting TP/SL / stop / limit orders (QFEX: WARNING lists them) — check account orders
85
111
  perp --json -e <EX> trade reduce <SYMBOL> <PCT> # reduce by percentage
86
112
  perp --json -e <EX> trade leverage <SYMBOL> <N> [--isolated]
87
113
 
@@ -318,10 +344,18 @@ perp --json arb scan # default --mode all
318
344
  perp --json arb scan --mode perp-perp --min 10 # perp-only with min annual %
319
345
  perp --json arb scan --mode spot-perp --min 10 # spot+perp only
320
346
  perp --json arb scan --rates # funding rates across exchanges
347
+ # Which rate is compared: each venue's market-row `fundingRate` (the CURRENT rate it publishes), labelled
348
+ # per row by `rateKind` — Pacifica / Lighter / Lighter RH / Arcus / RISEx / Ondo "lastSettled", Hyperliquid /
349
+ # Aster / TxFlow / Extended "accruing", GRVT / Variational "predicted", null = QFEX (not established). It is NOT the WS comparator's kind:"next" (predicted
350
+ # next-period rate, where a venue publishes one: Pacifica `predictedFundingRate`).
321
351
  perp --json arb scan --basis [SYMBOL] # cross-exchange basis
322
352
  perp --json arb scan --gaps # cross-exchange price gaps
323
353
  perp --json arb scan --hip3 # HIP-3 cross-dex spreads
324
- perp --json arb scan --history [SYMBOL] # historical funding
354
+ perp --json arb scan --history [SYMBOL] [--hours 24] # LOCAL snapshots only (~/.perp/funding-rates/, written by
355
+ # `arb scan --rates` / `portfolio --arb`; hyperliquid / pacifica / lighter unless -e) — `rates: {}` until scans
356
+ # have run; `historicalAvg` (avg1h/8h/24h/7d) in --rates / --compare rows comes from the same store (null when empty).
357
+ # Real settled history: perp --json -e <EX> market funding <SYM> -l <N> (newest first; rate = fraction per
358
+ # intervalHours → hourly = rate / intervalHours, annual % = hourly × 8760 × 100; average the rows yourself)
325
359
  perp --json arb scan --compare <SYMBOL> # compare a symbol across exchanges
326
360
  perp --json arb scan --positions # position funding impact; actual24h null + fundingHistoryErrors when a venue's history is unreadable
327
361
  perp --json arb scan --live --interval 60 # continuous monitoring
@@ -329,15 +363,35 @@ perp --json arb scan --top 10 --hold-days 7 --bridge-cost 0 --size 100 # cost-a
329
363
  perp --json -e extended market list # Extended (read-only): rows carry assetClass, venueSymbol (TSLA_24_5-USD), tickSize, minSize, tradable, fundingRateKind "accruing"
330
364
  perp --json -e extended market funding BTC -l 24 # applied hourly prints: rateKind "lastSettled", intervalHours 1, annualizedPct
331
365
  perp --json arb scan --rates --include-unverified # also show QFEX, TxFlow, Variational, GRVT and Extended (unverified funding; TxFlow rows apiStatus "unofficial"; display only, never ranked)
366
+ perp --json -e qfex market funding AAPL -l 72 # hourly windows; outside the market's funding hours: rate null + marketClosed true (not a 0 rate)
367
+ # QFEX marketClosed limits: (1) a market holiday INSIDE a configured session (e.g. SAMSUNG-KRW on
368
+ # Hangul Day, a weekday) is not in market_hours, so its 0 prints as a real-looking rate "0" with
369
+ # marketClosed false; (2) US equities DO fund in the weekday overnight gap (post_market → pre_market),
370
+ # so only an exact 0 with no part of the hour in any funding session counts as closed — a real 0
371
+ # in a gap would also read as closed. Averages / APRs skip marketClosed rows only.
332
372
  # netSpread / grossSpread = annualized % (netSpread = gross minus round-trip costs amortized over --hold-days)
333
- # spot-perp rows: netSpreadPct / grossSpreadPct, spotExchanges[], perpExchange, direction
373
+ # estFeesPct = round trip on BOTH legs = 2 × (taker fee leg A + taker fee leg B) + 2 × 0.05 % slippage, taker fees from
374
+ # `perp settings fees show` (settings.fees, else the shipped table — the spot leg uses its venue's perp taker rate);
375
+ # e.g. hl+hl: 2 × (0.035 + 0.035) + 0.1 = 0.24 %. `settings fees show` is the per-fill rate, estFeesPct the round trip.
376
+ # perp-perp rows: mode, longExch, shortExch, markPrice, grossSpread(Pct), netSpread(Pct), estFeesPct, priceGapPct
377
+ # spot-perp rows: mode, spotExchanges[], perpExchange, direction, perpFundingRate, netSpreadPct / grossSpreadPct AND
378
+ # netSpread / grossSpread (same values), estFeesPct, estHourlyIncomeUsd (per $1000), breakEvenDays, markPrice.
379
+ # Executable only when direction == "long-spot-short-perp" (arb exec spot: always buys spot + shorts the perp and
380
+ # does not check the funding sign) — never act on "sell-spot-long-perp".
381
+ # --rates / --compare rows: symbol, rates[] (exchange, fundingRate, hourlyRate, annualizedPct, rateKind, fundingVerified,
382
+ # historicalAvg), maxSpreadAnnual / longExchange / shortExchange / estHourlyIncomeUsd (null with < 2 verified rates),
383
+ # executable (act only when true), readOnlyLegs, unverifiedLegs, mixedKinds; --rates top level: symbols[], minSpread,
384
+ # belowMinSpread, exchangeStatus, exchangeErrors. --compare <unknown> → ok:true, data { symbol, available: false }.
385
+ # Testnet funding / spreads are meaningless (thousands of %/yr) — analyse yield on mainnet only.
334
386
 
335
387
  # Execute (perp-perp or spot+perp via spot:<venue>; spot venues: hl, lt, lrh, aster, ondo)
336
388
  # Sequential: long first, then the short sized to the verified long fill; reconcile always on;
337
389
  # an unconfirmed leg quarantines the symbol. Supports --dry-run.
338
390
  perp --json arb exec <SYM> <longEx> <shortEx> <USD> # perp-perp dual-leg entry
339
- perp --json arb exec <SYM> spot:hl hl <USD> # spot+perp via HL spot
391
+ perp --json arb exec <SYM> spot:hl hl <USD> # spot+perp via HL spot (long-spot-short-perp rows only)
340
392
  perp --json arb exec <SYM> spot:lt pac <USD> # spot+perp via LT spot
393
+ # spot: validates balances (spot quote + transferable perp; perp margin), both books (empty book → refused),
394
+ # spot/perp mid gap ≤ 5 %, depth and venue minimums before anything moves
341
395
  perp --json arb exec <SYM> <longEx> <shortEx> <USD> \
342
396
  --leverage 2 --isolated --smart --max-slippage 0.5
343
397
 
@@ -351,6 +405,8 @@ perp --json arb close <SYM> --state-only --yes # drop a stale state
351
405
 
352
406
  # Status / history / config / rebalance
353
407
  perp --json arb status # open arb positions + PnL + funding; check unconfirmedPairs, staleStateEntries
408
+ # reads every configured venue; one failing venue fails the whole command (EXCHANGE_ERROR, no venue filter) →
409
+ # check per venue with `-e <EX> account positions`
354
410
  # spot-perp entries: fundingSource actual | partial | estimate | recorded (+ fundingError) — only "actual" is complete settled funding
355
411
  perp --json arb status --period 7 --symbol BTC # filter funding lookback / symbol
356
412
  perp --json arb history # alias: arb log
@@ -368,8 +424,7 @@ perp --json --dry-run arb auto # simulate (--backgr
368
424
 
369
425
  ## Wallet Management
370
426
  ```bash
371
- perp --json wallet generate evm # generate EVM wallet
372
- perp --json wallet generate solana # generate Solana wallet
427
+ perp --json wallet generate [name] [--words 12|24] # new multi-chain OWS vault wallet (EVM + Solana); passphrase via OWS_PASSPHRASE / stdin
373
428
  printf '%s' "$KEY" | OWS_PASSPHRASE=<pp> perp --json wallet import --name <n> [--chain evm|solana|dual] [--mnemonic] # import a key (stdin / hidden prompt; argv key, --evm/--solana <key>, --legacy rejected)
374
429
  printf '%s' "$KEY" | OWS_PASSPHRASE=<pp> perp --json wallet set hl # import key (stdin / hidden prompt; argv key rejected) into OWS vault → active wallet
375
430
  perp --json wallet set pac --name pac # Solana key, hidden prompt (TTY)
@@ -482,7 +537,7 @@ perp --json wallet policy delete <id>
482
537
  ## Risk & Analytics
483
538
  ```bash
484
539
  perp --json risk status # portfolio risk overview (level, violations, canTrade)
485
- perp --json health # adapter health: ping venue REST endpoints (connectivity + latency)
540
+ perp --json health # keyless venue ping: data.healthy (official venues up), allHealthy (+ unofficial), exchanges[], unofficial[], skipped[]
486
541
  perp --json risk liquidation-distance # % distance from liquidation for ALL positions
487
542
  perp --json risk limits # view current risk limits
488
543
  perp --json risk limits --min-liq-distance 30 --max-leverage 5 # set risk limits (also --max-position[-pct], --max-exposure[-pct], --max-positions, --daily-loss[-pct], --max-drawdown[-pct], --max-margin, --reset)