A command line interface for trading APIs. Supports Schwab (via
huskly.finance auth) and Interactive Brokers
(via @huskly/ibkr-client, which owns
the native OAuth 1.0a and Interactive Brokers API integration).
- Market Data: Real-time quotes, options chains, historical data, instrument search, and market movers
- Instrument Search: Search by symbol or description with fundamental data support
- Account Management: View positions, balances, and transaction history
- Order Management: View orders and place simple MARKET/LIMIT orders
- Caching: Redis-backed caching for improved performance
- Multi-broker: Schwab (default) and IBKR via the global
--brokerflag - MCP server:
huskly-cli-mcpexposes market data as MCP tools for Claude
Select the broker per invocation with the global --broker flag (default schwab):
huskly-cli account # Schwab (default)
huskly-cli --broker ibkr account # Interactive Brokers
huskly-cli --broker ibkr positions
huskly-cli --broker ibkr transactions
huskly-cli --broker ibkr orders
huskly-cli --broker ibkr replUse this matrix to track broker parity as IBKR support expands. A checkmark means the command supports that broker today; a cross means it is not yet implemented for that broker.
| Command | Schwab | IBKR |
|---|---|---|
quote |
✓ | ✓ |
search |
✓ | ✓ |
movers |
✓ | ✗ |
history |
✓ | ✗ |
chart |
✓ | ✗ |
vix |
✓ | ✗ |
expiries |
✓ | ✗ |
chain |
✓ | ✗ |
option resolve |
✗ | ✓ |
option chain |
✗ | ✓ |
spread quote |
✗ | ✓ |
spread preview |
✗ | ✓ |
spread submit |
✗ | ✓ |
order show/watch/cancel |
✗ | ✓ |
broker doctor |
✗ | ✓ |
account |
✓ | ✓ |
user-preference |
✓ | ✗ |
positions |
✓ | ✓ |
transactions |
✓ | ✓ |
orders |
✓ | ✓ |
place-order |
✓ | ✗ |
repl |
✓ | ✓ |
IBKR currently supports the shared account, quote, search,
positions, transactions, orders, and repl commands plus
exact-series option resolve, option chain, spread quote, guarded
spread preview/spread submit, and derivative order lifecycle commands. IBKR
search supports symbol lookup via symbol-search / search; Schwab-specific
regex, description, and fundamental projections report a clear error under
--broker ibkr. All other broker commands (chain, movers, place-order,
etc.) are Schwab-only and will report a clear error under --broker ibkr.
IBKR uses OAuth 1.0a. Copy .env.example to .env and fill in the consumer
key / access token / secret from the IBKR self-service portal, and place the
PEM key files (private_signature.pem, private_encryption.pem, dhparam.pem)
in the working directory (or set IBKR_KEYS_DIR). See .env.example for the
full list of variables.
All IBKR transport, OAuth, endpoint response normalization, instrument search,
transactions, and order behavior lives in @huskly/ibkr-client. This project
keeps only the shared CLI presentation adapter and Redis read cache.
The read-only derivative foundation uses a separate DerivativeDiscoveryClient
capability instead of widening the account-oriented BrokerClient. Its normalized
identity includes asset class (OPT or FOP), underlying, expiration, strike,
right, trading class, exchange, multiplier, and optional settlement/exercise
metadata. That identity distinguishes contracts such as NDX and NDXP even when
their underlying, expiration, and strike match.
IBKR conids are converted by IbkrDerivativeAdapter into an opaque
brokerReference. This reference is useful for an immediate broker request but
is not durable identity and must not be persisted in place of the semantic fields.
Market-data availability remains explicit (live, delayed, frozen,
frozen-delayed, or unavailable), and missing prices, activity, or Greeks stay
nullable. Discovery cannot reach preview or order-write endpoints.
The broker-neutral research service powers the user-facing option and spread
commands. Its current production adapter is IBKR; Schwab remains unsupported until
it can supply the exact trading-class/exchange identity without guessing. The
existing top-level expiries and chain commands remain unchanged and Schwab-only.
- Node.js >= 20.0.0
- Redis (for Schwab caching)
- Schwab API credentials (via huskly.finance), and/or
IBKR OAuth 1.0a credentials for
--broker ibkr
npm install -g @huskly/cli
git clone https://github.com/huskly/cli.git
cd cli
npm install
npm run build# Login via huskly.finance auth
huskly-cli auth login
# Check authentication status
huskly-cli auth status
# Logout
huskly-cli auth logoutGet current price quotes for one or more symbols.
huskly-cli quote AAPL
huskly-cli quote AAPL MSFT GOOGLSearch for instruments by symbol or description. Supports multiple search modes including fundamental data retrieval.
# Search by symbol prefix (default)
huskly-cli search AAPL
# Search by symbol using regex
huskly-cli search "^AA" --projection symbol-regex
# Search by description
huskly-cli search "Apple" --projection desc-search
# Search description with regex
huskly-cli search "tech.*inc" --projection desc-regex
# Get fundamental data for a symbol
huskly-cli search AAPL --projection fundamentalOptions:
-p, --projection <type>- Search type (default: symbol-search)symbol-search- Search by symbol prefixsymbol-regex- Search by symbol using regex patterndesc-search- Search by description textdesc-regex- Search description using regex patternsearch- General searchfundamental- Get detailed fundamental data (P/E, EPS, market cap, dividends, margins, etc.)
Get the top 10 movers for a specific index or market segment.
# Get top movers for Dow Jones Industrial Average
huskly-cli movers '$DJI'
# Get top movers for S&P 500 sorted by percent change up
huskly-cli movers '$SPX' --sort PERCENT_CHANGE_UP
# Get NASDAQ movers sorted by volume
huskly-cli movers NASDAQ --sort VOLUME
# Get all equity movers with 5-minute frequency
huskly-cli movers EQUITY_ALL --frequency 5Arguments:
<index>- Index symbol:$DJI,$COMPX,$SPX,NYSE,NASDAQ,OTCBB,INDEX_ALL,EQUITY_ALL,OPTION_ALL,OPTION_PUT,OPTION_CALL
Options:
-s, --sort <type>- Sort by:VOLUME,TRADES,PERCENT_CHANGE_UP,PERCENT_CHANGE_DOWN-f, --frequency <minutes>- Frequency in minutes: 0, 1, 5, 10, 30, 60 (default: 0)
Get historical price data for a symbol.
huskly-cli history AAPL
huskly-cli history AAPL --days 30Options:
-d, --days <n>- Number of days of history (default: 10)
Display an ASCII chart of price history.
huskly-cli chart SPY
huskly-cli chart SPY --days 60 --height 20
huskly-cli chart SPY --image # Open image chart in browserOptions:
-d, --days <n>- Number of days of history (default: 30)-h, --height <n>- Chart height in rows (default: 15)-i, --image- Generate image chart and open in browser
Get the current VIX level with sentiment indicator.
huskly-cli vixList available option expiration dates for a symbol.
huskly-cli expiries SPX
huskly-cli expiries SPY --type CALL
huskly-cli expiries AAPL --from 2024-01-01 --to 2024-06-30Options:
-t, --type <type>- Contract type: PUT or CALL (default: PUT)-f, --from <date>- Start date (YYYY-MM-DD)-e, --to <date>- End date (YYYY-MM-DD)
Get the options chain for a symbol and expiration date.
huskly-cli chain SPX
huskly-cli chain SPX 2024-12-20
huskly-cli chain AAPL --around 180 --strikes 5Options:
-a, --around <strike>- Filter strikes around this price (defaults to last price)-s, --strikes <count>- Number of strikes to show above/below center (default: 10)
Resolve one exact contract or quote a series without collapsing trading class,
exchange, asset class, or multiplier. Every exploratory command supports --json.
huskly-cli option resolve NQ --broker ibkr \
--asset FOP --expiry 2026-08-21 --class QN3 --exchange CME --json
huskly-cli option chain NDX --broker ibkr \
--asset OPT --expiry 2026-08-20 --class NDXP --exchange SMART --right PUT \
--around 26600 --strikes 4For futures options, the reference quote is the actual underlying futures contract
reported by IBKR, not a guessed spot/index proxy. For example, the NQ QN3 option
series can reference the September NQ future.
Analyze call/put debit or credit verticals from exact individual-leg markets. Amounts include contract multiplier and quantity.
huskly-cli spread quote put-credit NQ --broker ibkr \
--asset FOP --expiry 2026-08-21 --class QN3 --exchange CME \
--long 26400 --short 26600 --quantity 1 --limit 39 --json
huskly-cli spread quote put-credit NDX --broker ibkr \
--asset OPT --expiry 2026-08-20 --class NDXP --exchange SMART \
--long 26400 --short 26600The natural and midpoint scenarios are synthetic values computed from individual leg quotes. They are not a broker combo NBBO, executable preview, or order quote. The result includes maximum profit/loss, breakeven, return on risk, net delta, an expiration payoff table, and an explicit settlement/residual-exposure warning. Derivative research calls bypass the Redis read cache; each DTO retains the broker quote timestamp and live/delayed/frozen/unavailable availability state.
Preview one atomic vertical without submitting it. An exact account is mandatory,
either through --account or IBKR_ACCOUNT_ID. User-facing credits and debits are
always positive; IBKR's signed combo-price encoding stays inside the broker adapter.
huskly-cli spread preview put-credit NQ --broker ibkr \
--account U1234567 --asset FOP --expiry 2026-08-21 --class QN3 \
--exchange CME --short 26600 --long 26400 --quantity 1 --credit 39 --jsonThe output masks the account, identifies live versus paper, includes exact legs,
margin, commissions/fees, warnings and rejections, and states submitted: false.
Its preview ID binds the account/environment, exact contracts, quantity, limit,
TIF, session, timestamp, and normalized What-If result and expires after five minutes.
The owner-readable preview file stores only a one-way account digest and masked DTO so a
separate CLI invocation can submit it without persisting the full account ID. Unknown or
incomplete What-If results fail closed.
Submit only the exact unexpired preview that was reviewed. Futures and futures-option writes also require the operator identity used for CME audit metadata.
export HUSKLY_EXT_OPERATOR=felipecsl
huskly-cli spread submit <preview-id> --broker ibkr --account U1234567 --confirm --json
# A known broker warning must be acknowledged explicitly; unknown warnings stop the flow.
huskly-cli spread acknowledge <preview-id> <reply-id> \
--broker ibkr --account U1234567 --confirm --json
huskly-cli order show <order-id> --broker ibkr --account U1234567 --json
huskly-cli order watch <order-id> --broker ibkr --account U1234567 --json
huskly-cli order cancel <order-id> --broker ibkr --account U1234567 \
--operator felipecsl --confirm --jsonBefore placement the workflow verifies the exact account/session and environment, rejects
expired previews or contract drift, and submits one atomic combo with a unique client order ID.
After placement and cancellation it reads fresh broker state and verifies the legs, signed
ratios, quantity, signed limit, and client order identity against the reviewed preview. Partial
fills remain visible; cancellation succeeds only after the broker reaches CANCELED.
Paper accounts are allowed by default. Live execution fails closed unless both
HUSKLY_ENABLE_LIVE_EXECUTION=true and an exact comma-separated
HUSKLY_LIVE_ACCOUNT_ALLOWLIST include the requested account. Execution state persists only an
account digest and masked preview DTO, never the full account identifier.
huskly-cli broker doctor --broker ibkr --account U1234567 --trading --jsonThis command is read-only. It reports masked account/environment identity, authentication and competing-session state, market-data access, and advisory asset permissions. Permission metadata is diagnostic only; an explicit What-If response is the authoritative pre-submission gate.
Show account equity and net liquidation value.
huskly-cli accountShow all account positions, optionally filtered by symbol.
huskly-cli positions
huskly-cli positions AAPLList account transaction history.
huskly-cli transactions
huskly-cli transactions --start 2024-01-01 --end 2024-12-31
huskly-cli --broker ibkr transactionsOptions:
-s, --start <date>- Start date (YYYY-MM-DD, defaults to start of year)-e, --end <date>- End date (YYYY-MM-DD, defaults to today)-t, --type <type>- Filter by transaction type (e.g., TRADE, DIVIDEND, BUY, SELL)--csv- Output in CSV format instead of table
IBKR transaction history is sourced from the Web API PortfolioAnalyst
/pa/transactions endpoint, which requires one contract id per request. The CLI
queries the contract ids present in current IBKR positions, then filters the
results to the requested date range.
List account orders with optional filtering.
huskly-cli orders
huskly-cli --broker ibkr orders
huskly-cli orders --from 2024-01-01 --to 2024-12-31
huskly-cli orders --status FILLED
huskly-cli orders --max-results 10Options:
-f, --from <date>- From entered time (YYYY-MM-DD, defaults to 30 days ago)-t, --to <date>- To entered time (YYYY-MM-DD, defaults to today)-s, --status <status>- Filter by order status (FILLED, WORKING, CANCELED, etc.)-m, --max-results <n>- Maximum number of orders to retrieve
IBKR orders are sourced from the live /iserver/account/orders endpoint, then
filtered locally by date and maximum result count.
Place an order for equities.
# Market order to buy 10 shares of AAPL
huskly-cli place-order AAPL 10 BUY
# Limit order to buy 5 shares of MSFT at $400
huskly-cli place-order MSFT 5 BUY --type LIMIT --price 400
# Market order to sell 20 shares
huskly-cli place-order GOOGL 20 SELL
# Sell short with Good Till Cancel duration
huskly-cli place-order SPY 100 SELL_SHORT --duration GOOD_TILL_CANCELArguments:
<symbol>- Stock symbol to trade<quantity>- Number of shares<instruction>- Order instruction: BUY, SELL, BUY_TO_COVER, SELL_SHORT
Options:
-t, --type <type>- Order type: MARKET or LIMIT (default: MARKET)-p, --price <price>- Limit price (required for LIMIT orders)-s, --session <session>- Trading session: NORMAL, AM, PM, SEAMLESS (default: NORMAL)-d, --duration <duration>- Order duration: DAY, GOOD_TILL_CANCEL, FILL_OR_KILL, IMMEDIATE_OR_CANCEL (default: DAY)
Start an interactive REPL to run multiple commands without re-authenticating.
huskly-cli repl
huskly-cli --broker ibkr replhuskly-cli-mcp exposes market-data, account, and guarded derivative operations as MCP
tools — get_quote, search_symbol, get_positions, get_price_history,
get_movers, get_vix_level, get_option_chain, get_option_expiries, and
place_option_order, plus get_derivative_chain, quote_option_spread,
preview_option_spread_order, submit_option_spread_order,
acknowledge_order_warning, get_order_status, and cancel_order
— so Claude can answer questions like "what's the MSFT price now", "what's
the AAPL last 12 months price history", or "what are my current positions"
with live data.
place_option_order is Schwab-only and
requires confirm: true to submit a real live order; when confirm is omitted
or false, it returns a preview without calling the broker. The IBKR derivative tools reuse the
same exact-preview and lifecycle services as the CLI. Submission, warning acknowledgment, and
cancellation require confirm: true; unknown warning IDs and unguarded order IDs fail closed.
It communicates over stdio and reuses the same Schwab/IBKR auth as the CLI, so
authenticate first (huskly-cli auth login for Schwab, and/or set the IBKR
env vars — see IBKR setup) before registering it.
get_quote, search_symbol, and get_positions work with either broker
(schwab by default, overridable per-call or via HUSKLY_MCP_DEFAULT_BROKER);
the rest (get_price_history, get_movers, get_vix_level,
get_option_chain, get_option_expiries) always use Schwab, since IBKR
doesn't expose that data today.
Register it with Claude Code:
# After `npm run build`, from this repo:
claude mcp add huskly-cli-mcp -- node /path/to/huskly-cli/dist/mcp/server.js
# Or, once published/linked so `huskly-cli-mcp` is on PATH:
claude mcp add huskly-cli-mcp -- huskly-cli-mcp
# To default to IBKR instead of Schwab:
claude mcp add huskly-cli-mcp -e HUSKLY_MCP_DEFAULT_BROKER=ibkr -- huskly-cli-mcpRegister it with Codex:
codex mcp add huskly-cli-mcp -- node /path/to/huskly-cli/dist/mcp/server.jsIf Codex will launch the server outside this repository, set the MCP server
cwd to the repository path so local .env and IBKR PEM files resolve the same
way they do for the CLI.
The server is long-lived (same as huskly-cli repl), so a broker client — and
the access token/session it holds — is created once and reused across tool
calls. If a Schwab or IBKR session expires or is revoked mid-session, restart
the MCP server (e.g. via claude mcp reconnect) to force re-authentication.
src/
├── auth/ # Authentication (huskly.finance device auth)
├── cli/ # CLI commands
├── mcp/ # MCP server (huskly-cli-mcp) exposing market data and account positions as tools
├── schwab/ # Schwab API integration
├── types.ts # TypeScript type definitions
├── cache.ts # Redis caching layer
├── helpers.ts # Utility functions
├── logger.ts # Logging configuration
└── marketDataSource.ts # Market data abstraction
test/ # Tests, mirroring the src/ directory tree
├── brokers/
├── cli/
├── derivatives/
├── orders/
├── cachedIbkrClient.test.ts
└── helpers.test.ts
LOG_LEVEL- Set logging level (trace, debug, info, warn, error)REDIS_URL- Redis connection URL (defaults to localhost:6379)HUSKLY_MCP_DEFAULT_BROKER- Default broker (schwaboribkr) for the MCP server's broker-agnostic tools when a call omitsbroker(defaults toschwab; an invalid value logs a warning to stderr and falls back toschwabrather than failing startup)HUSKLY_EXT_OPERATOR- CME operator identity used by derivative submit/cancel CLI commands when--operatoris omittedHUSKLY_ENABLE_LIVE_EXECUTION- Must be exactlytrueto permit live derivative executionHUSKLY_LIVE_ACCOUNT_ALLOWLIST- Comma-separated exact account IDs permitted for live derivative executionHUSKLY_PREVIEW_DIR/HUSKLY_EXECUTION_DIR- Optional owner-readable workflow-state directories
MIT © Huskly Finance