CCXT CLI
The CCXT CLI (ccxt-cli on npm) exposes the entire unified CCXT API as a terminal command. Anything you can call in code — fetchTicker, fetchOHLCV, createOrder, fetchBalance, withdraw, exchange-specific implicit methods — you can call as:
It supports 100+ exchanges, REST and WebSocket, public and private endpoints, live terminal dashboards, and interactive OHLCV charts.
Installation
One-off use without installing (note -p ccxt-cli — the package name differs from the binary name):
From a clone of the CCXT repository (contributor mode — uses the local source tree instead of the published package):
Quick start
Every run prints the CCXT version, the resolved call (e.g. kraken.fetchTicker ("BTC/USD")), the result, and timing. Use --raw to suppress everything except the JSON result.
Discovering methods and arguments
ccxt explain <method> output shows the argument order you must follow:
Argument rules (important)
Arguments are positional and must follow the method's signature order. The CLI auto-converts each argument:
Rule 1 — pad skipped optionals with undefined. To pass limit without since:
Rule 2 — --param key=value appends to the trailing params object. Repeat it for multiple keys. Values are coerced the same way (true, false, null, numbers, strings):
Rule 3 — when using --param, explicitly fill ALL earlier optional positionals with undefined. If you leave gaps, the CLI mis-assigns arguments (a known quirk — the params object can end up in the wrong position). Correct:
Authentication
Private methods (fetchBalance, createOrder, fetchMyTrades, ...) need credentials. Three sources:
1. Environment variables
Pattern: <EXCHANGEID>_<CREDENTIAL> upper-cased. The credential names come from each exchange's requiredCredentials (apiKey, secret, password, uid, walletAddress, privateKey, ...):
Pass --no-keys to ignore detected credentials and force unauthenticated calls.
2. Config file (persistent)
The CLI keeps a config at $CACHE/ccxt-cli/config.json, keyed by exchange id. ccxt --help prints the exact path for your OS:
- macOS:
~/Library/Caches/ccxt-cli/config.json - Linux:
~/.cache/ccxt-cli/config.json(or$XDG_CACHE_HOME/ccxt-cli/) - Windows:
%LOCALAPPDATA%\ccxt-cli\cache\config.json
Any key in the exchange object is set as a property on the exchange instance — so options lets you set persistent per-exchange behavior. To store the config somewhere else: ccxt config ./some/path/config.json.
3. keys.json / keys.local.json in the current directory
If the working directory contains keys.json and/or keys.local.json (same shape as the config file), they are loaded too and override the config file. This is how the CLI picks up credentials inside the CCXT repo.
Precedence: config.json < keys.json < keys.local.json; environment variables fill only credentials still missing.
Market type, sandbox, and demo flags
--sandbox requires the exchange to declare test URLs; otherwise it fails (with TypeError: Invalid URL or NotSupported). Exchanges with demo-trading portals (binance, bybit, okx, gate, ...) use --demo with API keys generated in the demo portal.
Output control and scripting
Array results render as a table by default; --no-table disables that.
Scripting example:
Scripting facts:
- The CLI exits with code
1on errors — check$?. - Errors print to stdout, not stderr, even with
--raw— on failure your pipe receives colored non-JSON text. Guard withjq -eor check the exit code before parsing. - WebSocket/
--pollmodes stream continuously — for scripts stick to one-shotfetch*calls. - Each
npxinvocation pays startup overhead; for repeated calls install globally (npm i -g ccxt-cli) or use--iinteractive mode.
Real-time data (WebSocket)
Any watch* method streams continuously until Ctrl+C:
Built-in live terminal dashboards (WebSocket, one or more exchanges, comma-separated, no spaces):
Poll a REST method in a rate-limited loop:
OHLCV charts
Fetches candles via REST, generates a self-contained interactive HTML chart (candlesticks + volume), and opens it in the browser. Charts are saved under $CACHE/ccxt-cli/charts/.
Interactive mode
Keeps the session open and prompts for the next command ([command]:), reusing the process — faster for exploring an exchange (markets stay loaded).
Market cache
loadMarkets() results are cached for 24h under $CACHE/ccxt-cli/markets/, which makes repeat invocations much faster.
If a symbol is reported as not found but exists on the exchange, refresh the market cache first.
Note:
--no-load-markets(skip market loading) is currently non-functional in released ccxt-cli versions — it is accepted but ignored, and markets load anyway.
Debugging
--verbose is the first thing to reach for on signing, parsing, or rate-limit issues.
⚠️ Do NOT rely on
--no-sendas a dry run. In current ccxt-cli releases the flag is accepted but silently ignored — the request IS sent to the exchange. Use--sandboxor an exchange-side test param (below) to validate orders safely. There is also no keyless dry-run: private calls fail at signing (AuthenticationError: requires "apiKey") before any request is built.
Capturing static-test fixtures (contributors)
Running from the repo, the CLI is how CCXT's static test fixtures are produced:
--static makes a real call and records the actual URL, body and HTTP response as entries in both
ts/src/test/static/request/<id>.json and ts/src/test/static/response/<id>.json. --request / --response
capture one side only. --name auto-saves; omit it to print the entries for review first. For watch* methods
--static records ws frames until ctrl+c into ts/src/test/static/ws/<id>.json, with --recordLimit <n>
capping the resolutions kept.
🚨 Static fixtures must never be hand-written or invented — capture them with this command. A fabricated fixture asserts what you assumed the exchange does, so the test passes while the integration is broken, and it becomes the reference all seven languages are verified against. If the endpoint is unreachable (no credentials, geo-block, venue down), ship no fixture and say so rather than guessing one.
Trading safely
- Always test with small amounts, on sandbox first.
createOrderargument order issymbol type side amount [price] [params]— for market orders passundefinedfor price if you need to add--paramvalues after it.- Never share or commit API keys; prefer environment variables or the config file with restricted permissions.
Common errors
Errors print in red with the CCXT exception class name (ExchangeError subclasses) — the same hierarchy as the CCXT library, so RateLimitExceeded, InsufficientFunds, OrderNotFound, etc. mean exactly what they do in code.
Quirks and pitfalls
- Positional
undefinedpadding is mandatory when skipping optionals and especially before--param(see Argument rules Rule 3). - Perpetual swaps use the
BASE/QUOTE:SETTLEsymbol format (BTC/USDT:USDT) or--swapwith the plain symbol, depending on the exchange. - Date-only strings don't auto-convert —
"2025-05-01"stays a string; use"2025-05-01T00:00:00Z". - JSON arguments need shell quotes:
'{"recvWindow":5000}'. watch*and--pollnever exit on their own — Ctrl+C stops them.- First call per exchange is slow (downloads markets); subsequent calls hit the 24h cache.
- A failed
loadMarkets()aborts the call — even public methods die if market loading fails (e.g. geo-block), and the CLI still echoes the resolved call after printing the loadMarkets error, which can be misleading. - Broken flags in current releases:
--no-sendand--no-load-marketsare accepted but silently ignored — don't rely on either (see Debugging). - Command history is saved (including any inline arguments) to
$CACHE/ccxt-cli/history/commands.json— keep secrets in env vars or config, never as CLI arguments.
Reference: options summary
Learn more
- CCXT documentation: https://docs.ccxt.com
- CLI source and README: https://github.com/ccxt/ccxt/tree/master/cli
- Unified symbols/markets: https://docs.ccxt.com/#/?id=markets
- For writing programs instead of shell commands, see the language skills:
/ccxt-typescript,/ccxt-python,/ccxt-php,/ccxt-csharp,/ccxt-go,/ccxt-java


