|
| 1 | +# Agent Integration Guide: bitmex-cli |
| 2 | + |
| 3 | +> See [README.md](README.md) for safety warnings and disclaimer. |
| 4 | +
|
| 5 | +Self-contained guide for integrating `bitmex-cli` into AI agents, MCP clients, and automated pipelines. |
| 6 | + |
| 7 | +Fast entry points: |
| 8 | +- Runtime agent context: `CONTEXT.md` |
| 9 | +- Full command contract: `agents/tool-catalog.json` |
| 10 | +- Error routing contract: `agents/error-catalog.json` |
| 11 | +- Workflow skills: `skills/` |
| 12 | + |
| 13 | +## Installation |
| 14 | + |
| 15 | +### Pre-built binary (recommended) |
| 16 | + |
| 17 | +```bash |
| 18 | +curl -sSfL https://raw.githubusercontent.com/BitMEX/bitmex-cli/master/install.sh | sh |
| 19 | +``` |
| 20 | + |
| 21 | +Downloads a pre-built binary for your platform (macOS/Linux, x86_64/arm64), verifies the SHA256 checksum, and installs to `/usr/local/bin`. No Rust or build tools needed. Requires `curl`, `tar`, and `sha256sum` (or `shasum`). May prompt for `sudo` if `/usr/local/bin` is not writable. |
| 22 | + |
| 23 | +### From source (requires Rust) |
| 24 | + |
| 25 | +```bash |
| 26 | +# Install Rust if needed |
| 27 | +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh |
| 28 | + |
| 29 | +# Clone and install |
| 30 | +git clone https://github.com/BitMEX/bitmex-cli.git |
| 31 | +cd bitmex-cli |
| 32 | +cargo install --path . |
| 33 | +``` |
| 34 | + |
| 35 | +### Verify |
| 36 | + |
| 37 | +```bash |
| 38 | +bitmex --version |
| 39 | +``` |
| 40 | + |
| 41 | +## Authentication |
| 42 | + |
| 43 | +Public commands (market data, announcements) need no credentials. All other commands require a BitMEX API key. |
| 44 | + |
| 45 | +### New users |
| 46 | + |
| 47 | +If the user does not have a BitMEX account: |
| 48 | +1. Sign up at [bitmex.com/register](https://www.bitmex.com/register) |
| 49 | +2. Complete identity verification (Settings → Verification) |
| 50 | +3. Deposit funds (Wallet → Deposit) |
| 51 | + |
| 52 | +### API key setup |
| 53 | + |
| 54 | +1. Direct the user to [bitmex.com/app/apiKeys](https://www.bitmex.com/app/apiKeys) (or [testnet.bitmex.com/app/apiKeys](https://testnet.bitmex.com/app/apiKeys) for testnet). |
| 55 | +2. Create a key with **Order** and **Account** permissions (add **Withdraw** only if withdrawals/transfers are needed). |
| 56 | +3. Ask the user for the API key and secret. |
| 57 | +4. Store credentials: |
| 58 | + |
| 59 | +```bash |
| 60 | +bitmex auth set --api-key <KEY> --api-secret <SECRET> |
| 61 | +``` |
| 62 | + |
| 63 | +For testnet: |
| 64 | + |
| 65 | +```bash |
| 66 | +bitmex auth set --profile testnet --testnet --api-key <KEY> --api-secret <SECRET> |
| 67 | +``` |
| 68 | + |
| 69 | +5. Verify: |
| 70 | + |
| 71 | +```bash |
| 72 | +bitmex account me -o json |
| 73 | +``` |
| 74 | + |
| 75 | +### Alternative: environment variables |
| 76 | + |
| 77 | +For CI, Docker, or single-session use: |
| 78 | + |
| 79 | +```bash |
| 80 | +export BITMEX_API_KEY="..." |
| 81 | +export BITMEX_API_SECRET="..." |
| 82 | +``` |
| 83 | + |
| 84 | +### Credential resolution order |
| 85 | + |
| 86 | +1. `--api-key` / `--api-secret` flags |
| 87 | +2. `BITMEX_API_KEY` / `BITMEX_API_SECRET` env vars |
| 88 | +3. `--profile <name>` flag → OS keychain |
| 89 | +4. `BITMEX_PROFILE` / active profile in config → OS keychain |
| 90 | +5. Plaintext fallback in config file (when keychain unavailable) |
| 91 | + |
| 92 | +### Required permissions by command group |
| 93 | + |
| 94 | +| Group | BitMEX API permissions | |
| 95 | +|-------|----------------------| |
| 96 | +| market, announce, chat (read) | None (public) | |
| 97 | +| account, execution, position (read) | Order | |
| 98 | +| order (place/cancel) | Order | |
| 99 | +| wallet (read) | Account | |
| 100 | +| wallet (withdraw/transfer) | Withdraw | |
| 101 | +| staking, apikey, porl | Account | |
| 102 | + |
| 103 | +## Invocation Pattern |
| 104 | + |
| 105 | +```bash |
| 106 | +bitmex <command-group> <subcommand> [args...] -o json 2>/dev/null |
| 107 | +``` |
| 108 | + |
| 109 | +- Always pass `-o json` for machine-readable output. |
| 110 | +- Redirect stderr (`2>/dev/null`) to suppress diagnostic noise. |
| 111 | +- Check exit code: `0` = success, non-zero = failure. |
| 112 | +- On failure, stdout contains a JSON error envelope. |
| 113 | + |
| 114 | +## Testnet Mode |
| 115 | + |
| 116 | +All commands accept `--testnet` to target `https://testnet.bitmex.com`. Use testnet to validate agent workflows without risking real funds: |
| 117 | + |
| 118 | +```bash |
| 119 | +bitmex --testnet market instrument --active -o json |
| 120 | +bitmex --testnet order buy XBTUSD 100 --price 50000 --validate -o json |
| 121 | +``` |
| 122 | + |
| 123 | +Testnet requires separate API keys from [testnet.bitmex.com](https://testnet.bitmex.com). |
| 124 | + |
| 125 | +## Output Format |
| 126 | + |
| 127 | +All commands return JSON on stdout. Arrays of objects are typical for list endpoints: |
| 128 | + |
| 129 | +```json |
| 130 | +[ |
| 131 | + { |
| 132 | + "symbol": "XBTUSD", |
| 133 | + "lastPrice": 50000, |
| 134 | + "markPrice": 49998, |
| 135 | + "fundingRate": 0.0001, |
| 136 | + ... |
| 137 | + } |
| 138 | +] |
| 139 | +``` |
| 140 | + |
| 141 | +Error envelopes always contain `error` (stable category code) and `message`: |
| 142 | + |
| 143 | +```json |
| 144 | +{ "error": "auth", "message": "Authentication failed: Invalid API Key." } |
| 145 | +``` |
| 146 | + |
| 147 | +## Error Categories |
| 148 | + |
| 149 | +| Category | Meaning | Retry? | |
| 150 | +|----------|---------|--------| |
| 151 | +| `api` | Exchange rejected the request (4xx other than 429) | Depends on message | |
| 152 | +| `auth` | Invalid key, bad signature, insufficient permissions | No | |
| 153 | +| `network` | TCP connection failure or timeout | Yes | |
| 154 | +| `rate_limit` | HTTP 429 or 503 (exchange overloaded) | Yes — wait for reset | |
| 155 | +| `validation` | Bad CLI arguments | No | |
| 156 | +| `config` | Missing or invalid configuration | No | |
| 157 | +| `websocket` | WebSocket connection error | Yes | |
| 158 | +| `io` | Local file I/O error | No | |
| 159 | +| `parse` | Unexpected response format | No | |
| 160 | + |
| 161 | +### Rate limit envelope |
| 162 | + |
| 163 | +`rate_limit` errors include three extra fields added **client-side** (not from BitMEX): |
| 164 | + |
| 165 | +```json |
| 166 | +{ |
| 167 | + "error": "rate_limit", |
| 168 | + "message": "BitMEX rate limit exceeded: ... Retry after Unix timestamp 1713229600.", |
| 169 | + "suggestion": "BitMEX allows 300 requests per 5 minutes. Back off and retry after x-ratelimit-reset.", |
| 170 | + "retryable": true, |
| 171 | + "docs_url": "https://www.bitmex.com/app/restAPI#Rate-Limits" |
| 172 | +} |
| 173 | +``` |
| 174 | + |
| 175 | +- `message` includes the Unix retry timestamp from the `x-ratelimit-reset` response header |
| 176 | +- `suggestion` / `retryable` / `docs_url` are static hints for AI agent retry logic |
| 177 | + |
| 178 | +## Safety Protocol for Agents |
| 179 | + |
| 180 | +1. **Never execute dangerous commands** without explicit user approval. Check the `dangerous` field in `agents/tool-catalog.json`. |
| 181 | +2. **Validate orders first**: always pass `--validate` before submitting live orders. |
| 182 | +3. **Test on testnet**: use `--testnet` for new strategies. |
| 183 | +4. **Confirm destructive actions**: cancellations, withdrawals, transfers require `--yes` flag or interactive confirmation. |
| 184 | +5. **Never log secrets**: never print `BITMEX_API_SECRET` in output. |
| 185 | + |
| 186 | +## Dangerous Commands (require --yes or user confirmation) |
| 187 | + |
| 188 | +All order placement, amendment, and cancellation commands. All withdrawal and transfer commands. Position isolation, leverage changes, margin transfers. See `dangerous: true` entries in `agents/tool-catalog.json`. |
| 189 | + |
| 190 | +## MCP Server |
| 191 | + |
| 192 | +The built-in MCP server exposes bitmex-cli commands as tools directly to MCP clients: |
| 193 | + |
| 194 | +```bash |
| 195 | +bitmex mcp # market + account (safe defaults) |
| 196 | +bitmex mcp -s all # all groups except streaming |
| 197 | +bitmex mcp -s all --allow-dangerous # all commands including order placement |
| 198 | +``` |
| 199 | + |
| 200 | +Claude Desktop config (credentials from OS keychain): |
| 201 | + |
| 202 | +```json |
| 203 | +{ |
| 204 | + "mcpServers": { |
| 205 | + "bitmex": { |
| 206 | + "command": "bitmex", |
| 207 | + "args": ["mcp", "-s", "market,account,order,position,wallet"] |
| 208 | + } |
| 209 | + } |
| 210 | +} |
| 211 | +``` |
| 212 | + |
| 213 | +For CI or environments without a keychain, pass credentials via environment variables: |
| 214 | + |
| 215 | +```json |
| 216 | +{ |
| 217 | + "mcpServers": { |
| 218 | + "bitmex": { |
| 219 | + "command": "bitmex", |
| 220 | + "args": ["mcp", "-s", "market,account,order,position,wallet"], |
| 221 | + "env": { |
| 222 | + "BITMEX_API_KEY": "your-key", |
| 223 | + "BITMEX_API_SECRET": "your-secret" |
| 224 | + } |
| 225 | + } |
| 226 | + } |
| 227 | +} |
| 228 | +``` |
| 229 | + |
| 230 | +## WebSocket Streaming |
| 231 | + |
| 232 | +For real-time data, use `bitmex ws` instead of polling REST endpoints: |
| 233 | + |
| 234 | +```bash |
| 235 | +# Public — no auth needed |
| 236 | +bitmex ws trade:XBTUSD |
| 237 | +bitmex ws orderBookL2_25:XBTUSD instrument |
| 238 | + |
| 239 | +# Private — requires --auth |
| 240 | +bitmex ws --auth position order execution margin wallet |
| 241 | +``` |
| 242 | + |
| 243 | +Output is NDJSON (one JSON object per line) to stdout. Ctrl-C to stop. |
| 244 | + |
| 245 | +Available public topics: `trade`, `quote`, `instrument`, `orderBookL2_25`, `orderBook10`, `funding`, `liquidation`, `settlement`, `insurance`, `announcement`, `chat` |
| 246 | + |
| 247 | +Available private topics: `order`, `execution`, `position`, `margin`, `wallet`, `transact`, `affiliate`, `privateNotifications` |
| 248 | + |
| 249 | +## Rate Limits |
| 250 | + |
| 251 | +BitMEX allows 300 requests per 5 minutes for authenticated REST endpoints. Check response headers: |
| 252 | + |
| 253 | +- `x-ratelimit-remaining` — requests left in current window |
| 254 | +- `x-ratelimit-reset` — Unix timestamp when budget resets |
| 255 | + |
| 256 | +When rate limited (`error: "rate_limit"`), wait until `x-ratelimit-reset` before retrying. Use WebSocket streaming for real-time data instead of polling. |
| 257 | + |
| 258 | +## Common Agent Patterns |
| 259 | + |
| 260 | +### Morning market brief |
| 261 | + |
| 262 | +```bash |
| 263 | +bitmex market instrument --symbol XBTUSD -o json |
| 264 | +bitmex market funding --symbol XBTUSD --count 3 --reverse -o json |
| 265 | +bitmex market stats -o json |
| 266 | +``` |
| 267 | + |
| 268 | +### Monitor positions and PnL |
| 269 | + |
| 270 | +```bash |
| 271 | +bitmex position list -o json |
| 272 | +bitmex execution trade-history --count 20 -o json |
| 273 | +bitmex wallet balance -o json |
| 274 | +``` |
| 275 | + |
| 276 | +### Tick size and lot size alignment |
| 277 | + |
| 278 | +Every instrument enforces a minimum price increment (`tickSize`) and minimum quantity increment (`lotSize`). Submitting a price or quantity that isn't a multiple of these will return a `400 Invalid price` or `400 Invalid quantity` error. |
| 279 | + |
| 280 | +Fetch constraints before placing: |
| 281 | + |
| 282 | +```bash |
| 283 | +constraints=$(bitmex market instrument --symbol XBTUSD -o json | jq '.[0] | {tickSize, lotSize}') |
| 284 | +tick_size=$(echo "$constraints" | jq -r '.tickSize') |
| 285 | +lot_size=$(echo "$constraints" | jq -r '.lotSize') |
| 286 | +``` |
| 287 | + |
| 288 | +Round before submitting: |
| 289 | + |
| 290 | +```bash |
| 291 | +# round price to nearest tick |
| 292 | +price=$(echo "$raw_price $tick_size" | awk '{printf "%g", int($1/$2+0.5)*$2}') |
| 293 | +# round qty down to nearest lot |
| 294 | +qty=$(echo "$raw_qty $lot_size" | awk '{printf "%g", int($1/$2)*$2}') |
| 295 | +``` |
| 296 | + |
| 297 | +### Safe order placement workflow |
| 298 | + |
| 299 | +```bash |
| 300 | +# 1. Fetch tick/lot constraints and align price/qty before submitting |
| 301 | +constraints=$(bitmex market instrument --symbol XBTUSD -o json | jq '.[0] | {tickSize, lotSize}') |
| 302 | + |
| 303 | +# 2. Preview the constructed request body (local only — does not validate against exchange) |
| 304 | +bitmex order buy XBTUSD 100 --price 50000 --validate -o json |
| 305 | + |
| 306 | +# 3. Confirm with user, then execute (--yes skips interactive prompt for agent use) |
| 307 | +bitmex order buy XBTUSD 100 --price 50000 --yes -o json |
| 308 | +``` |
| 309 | + |
| 310 | +### Stream live data to a pipeline |
| 311 | + |
| 312 | +```bash |
| 313 | +bitmex ws trade:XBTUSD | jq -c '{time: .timestamp, price: .price, size: .size}' |
| 314 | +``` |
0 commit comments