AI-powered Kalshi trading CLI that finds edge and executes trades.
Runs deep fundamental research on every market — independent probability estimates, ranked price drivers, catalyst calendars — then computes edge as the spread between model price and the live order book. Signals are sized using half-Kelly and filtered through a 5-gate risk engine before a dollar is risked.
Integrates with the Octagon Research API for AI-generated probability estimates that power the edge detection engine.

bun:sqlite and runs .tsx directly; Node.js won't work)
bash
curl -fsSL https://bun.com/install | bashbunx kalshi-trading-bot-cli@latest
That's it — no clone, no install. The setup wizard runs automatically on first launch and walks you through API keys.
Prefer a global install? bun add -g kalshi-trading-bot-cli then run kalshi.
Scripting and agent use — for parallel invocations,
--jsonconsumers, or anything that pipes our output: install globally and use thekalshibinary, notbunx. See Scripting & Parallel Use below for the gory details.
Or work from a clone:
git clone https://github.com/OctagonAI/kalshi-trading-bot-cli.git
cd kalshi-trading-bot-cli
bun install
bun start
~/.kalshi-bot/.env): ~/.kalshi-bot/.env — written by the setup wizard. A .env in the current directory takes precedence (handy for dev).Using @latest in the bunx command always pulls the newest published version — so bunx kalshi-trading-bot-cli@latest is the zero-friction path.
If you ran bunx kalshi-trading-bot-cli without @latest, Bun may serve a cached copy. Force a refresh:
bunx kalshi-trading-bot-cli@latest # pin latest for this invocation
bun pm cache rm # or clear Bun's install cache
If you installed globally with bun add -g kalshi-trading-bot-cli:
bun update -g kalshi-trading-bot-cli # update in place
bun add -g kalshi-trading-bot-cli@latest # or reinstall pinned to latest
Check your installed version with kalshi --version (or bun pm ls -g | grep kalshi).
$ bunx kalshi-trading-bot-cli@latest
Welcome to Kalshi Trading Bot CLI
Type help for commands, or just ask a question.
> search crypto
Ticker Title Last Volume
KXBTC-26APR-B95000 Bitcoin above $95k by Apr 30 $0.58 12,841
KXBTC-26APR-B100000 Bitcoin above $100k by Apr 30 $0.31 8,203
KXETH-26APR-B2000 Ethereum above $2k by Apr 30 $0.72 5,419
3 markets found
> analyze KXBTC-26APR-B95000
Octagon Research Report — KXBTC-26APR-B95000
─────────────────────────────────────────────
Model Probability 72%
Market Price 58%
Edge +14.0% (very_high confidence)
Top Drivers
1. Bitcoin ETF inflows accelerating impact: high
2. Halving cycle momentum impact: high
3. Macro risk-on sentiment impact: moderate
Kelly Sizing
Recommended: 3 contracts YES at $0.58
Risk gates: ✓ Kelly ✓ Liquidity ✓ Correlation ✓ Concentration ✓ Drawdown
> buy KXBTC-26APR-B95000 3 58
✓ Order placed: BUY 3 YES @ $0.58
Order ID: abc-123-def
> portfolio
Ticker Side Qty Entry Now Edge P&L
KXBTC-26APR-B95000 YES 3 $0.58 $0.61 +11.0% +$0.09
Cash: $487.26 · Exposure: $1.74 · Positions: 1
| Command | Description |
|---|---|
search [theme\|ticker\|query] |
Find markets by keyword or theme (Octagon-backed when key set) |
search edge [--min-edge N] |
Scan all markets by model edge (Octagon markets-with-edge) |
similar <ticker\|"query"> |
Semantic neighbors via Octagon embeddings |
clusters [--label X] |
Browse thematic clusters of the Kalshi universe |
clusters <id> |
List markets inside a cluster |
clusters --behavioral |
Behavioral clusters by 30-day return vectors |
clusters --ranked |
Rank clusters by historical basket return |
peers <ticker> |
Markets in the same cluster as a ticker |
correlate <t1> <t2> [...] |
Pairwise Pearson correlation matrix |
basket build |
Diversified basket with cluster + correlation caps |
basket backtest |
NAV summary: total return, Sharpe, max drawdown, win rate |
basket size |
Fractional Kelly sizing for picked legs |
basket candles |
OHLC bars for a weighted basket NAV |
basket validate |
One-call portfolio diagnostics (clusters, correlations, calendar clashes, warnings) |
basket size --auto-probs |
Auto-fetch model probabilities via markets/edge and Kelly-size |
basket backtest --theme <name> |
Resolve an editorial theme to a NAV basket and backtest it |
series events <ticker> |
List events inside a series |
events / events <ticker> |
Octagon events list + outcome ladder per event |
series / series <ticker> |
Kalshi series rollup (24h vol, market count) |
series candles <ticker> |
Series-level NAV (basket of top sub-markets) |
catalysts upcoming --days N |
Markets closing in the next N days, grouped by week |
trust <event_ticker> |
Trader Trust scorecard — per-market integrity scores (table view) |
trust <event> --market <market> |
Single-market Trader Trust detail card (use --verbose for evidence) |
report <ticker> |
Full Octagon markdown report for an event (accepts event/market/series/URL). --refresh forces a fresh pull. |
themes (registry) |
Editorial narrative buckets — list/show/import/create/delete/add-series |
themes report |
25-theme dashboard with SEO + liquidity |
themes audit |
Flag dead themes (high SEO + zero volume) |
themes overlap |
Cross-theme dedupe report |
analyze <ticker> |
Deep analysis: edge, drivers, Kelly sizing |
watch <ticker> |
Live price and orderbook feed |
watch --theme <theme> |
Continuous theme scan |
buy <ticker> <count> [price] [yes\|no] |
Buy contracts |
sell <ticker> <count> [price] [yes\|no] |
Sell contracts |
cancel <order_id> |
Cancel a resting order |
backtest |
Model accuracy scorecard + live edge scanner |
portfolio |
Positions, P&L, risk snapshot |
setup |
Re-run setup wizard (inside TUI) |
init |
Launch setup wizard from CLI (kalshi init) |
clear-cache |
Delete local cache and rebuild (kalshi clear-cache) |
help [command] |
Detailed help for a command |
| Flag | Description |
|---|---|
--json |
JSON output for scripts and agents |
--refresh |
Force fresh Octagon report (analyze, report) |
--performance |
Include win rate, Sharpe, Brier scores (portfolio) |
--dry-run |
Scan without persisting edges (watch) |
--verbose |
Verbose output |
--min-edge <n> |
Minimum edge threshold in pp (backtest default 0.5) |
--interval <min> |
Scan interval in minutes (watch) |
--live |
Force 15m scan interval (watch) |
--days <n> |
Lookback period in days (backtest, default 15) |
--max-age <n> |
Reject predictions older than N days (backtest, default = --days) |
--resolved |
Resolved markets only (backtest) |
--unresolved |
Open markets only (backtest) |
--category <cat> |
Filter by category (backtest, search edge) |
--limit <n> |
Max results to show (search edge, default 20) |
--min-volume <n> |
Min per-contract volume (from Octagon snapshot; falls back to Kalshi lifetime if missing). Backtest default 1. |
--min-price <n> |
Min contract price, 0-100 scale (backtest, default 5) |
--max-price <n> |
Max contract price, 0-100 scale (backtest, default 95) |
--export <path> |
Export per-market CSV (backtest) |
--top-k <n> |
Number of neighbors (similar); legs per cluster (clusters --ranked) |
--behavioral |
Use behavioral clustering (clusters, peers) |
--ranked |
Rank clusters by historical basket return (clusters) |
--label <substr,...> |
Filter by cluster label substring (clusters, basket build) |
--close-before <iso> |
Only markets closing before this timestamp |
--window-days <n> |
Correlation lookback (correlate; basket build) |
--correlation-interval <1h\|1d> |
Override candle bin size for correlate |
--timeframe <1w\|1m\|3m\|6m\|1y> |
Window/bin size for basket commands |
--weights <csv> |
Comma-separated weights for basket backtest/candles |
--bankroll <usd> |
Bankroll for Kelly sizing (basket size/build) |
--kelly <0-1> |
Kelly multiplier (default 0.25) |
-n <n> |
Basket size requested (basket build) |
--max-per-cluster <n> |
Cap legs per thematic cluster (basket build) |
--max-corr <-1..1> |
Pairwise correlation cap (basket build) |
--min-return <n> |
Minimum total_return for clusters --ranked |
--series <ticker> |
Filter to a Kalshi series (search, similar, basket) |
--sort-by <key> |
Sort key for search edge: edge_pp | expected_return | total_volume | model_probability |
--probs <csv> |
Per-leg probabilities, e.g. KX-A:0.62,KX-B:0.55 |
--tickers <csv> |
Comma-separated tickers (correlate, basket backtest/candles) |
-q "text" |
Free-text anchor for similar / basket build |
--show-cluster |
Print cluster membership only (peers) |
--theme <name> |
Resolve an editorial theme to a ticker list (basket backtest/candles/validate/size) |
--aggregate-by series |
Roll up search results to the series level |
--active-only |
Drop non-active markets (defensive flag — open universe by default) |
--series-prefix <prefix> |
Server-side series prefix match (e.g. KXBTC matches KXBTCD, KXBTCY, ...) |
--sides yes,no,yes |
Per-ticker side for correlate (sign-flipped) |
--cells |
Include per-cell detail (overlap, reason) in correlate |
--auto-probs |
basket size: auto-fetch model probabilities via markets/edge |
The search, similar, clusters, peers, correlate, and basket commands turn the whole Kalshi universe into a queryable database. When OCTAGON_API_KEY is set the bot routes searches through Octagon's typed endpoints — semantic embedding lookups, nightly k-means clusters (thematic + behavioral), Pearson correlation matrices, and one-call diversified basket construction with cluster caps and pairwise-correlation gates. Without a key, search and search edge fall back to the local SQLite cache.
# Free-text + structured search (semantic full-text + filters)
kalshi search "bitcoin price" --category crypto --min-volume 10000 --limit 20
# Edge ranking from Octagon's latest run (server-side, no local pre-fetch)
kalshi search edge --min-edge 5 --limit 10 --sort-by total_volume
# Semantic neighbors — catches matches keyword search misses
kalshi similar KXBTCD-26DEC31-T100000 --top-k 25
kalshi similar -q "Will Bitcoin pierce six figures" --category crypto
# Browse the universe by theme
kalshi clusters --label fed # find Fed-decision clusters
kalshi clusters 42 # markets in cluster 42
kalshi clusters --behavioral # behavioral clusters (mean ret + vol)
kalshi clusters --ranked --timeframe 1y --min-return 0.20 --top-k 5
# Same-theme dedup
kalshi peers KXBTCD-26DEC31-T100000 --kind thematic --limit 50
kalshi peers KXBTCD-26DEC31-T100000 --show-cluster # which cluster does this belong to?
# Pairwise correlation matrix — most-uncorrelated pairs first
kalshi correlate KXBTCD-... KXETHU-... KXSOL-... --window-days 90
# Build a diversified basket (one HTTP call — universe → cluster cap → corr cap → sizing)
kalshi basket build --category crypto --min-volume 10000 \
-n 8 --max-per-cluster 2 --max-corr 0.6 \
--bankroll 1000 --kelly 0.25 \
--probs KXBTCD-...:0.62,KXETHU-...:0.58
# "Find me 5 uncorrelated bets on macro themes" — one HTTP call
kalshi basket build --label fed,cpi,fomc,gdp,jobs \
-n 5 --max-per-cluster 1 --max-corr 0.4
# Backtest a basket and read total_return / Sharpe / max DD directly
kalshi basket backtest --tickers KX-A,KX-B,KX-C --weights 0.4,0.4,0.2 --timeframe 1y
# Kelly-size legs you've already picked
kalshi basket size --bankroll 1000 --kelly 0.25 --probs KX-A:0.62,KX-B:0.55
# Or let Octagon's model fill in the probabilities for you
kalshi basket size --auto-probs --tickers KX-A,KX-B,KX-C --bankroll 1000 --kelly 0.25
kalshi basket size --auto-probs --theme "AI Race Milestones" --bankroll 1000 --kelly 0.25
# Diversified basket builder over an explicit candidate pool
kalshi basket build --tickers KX-A,KX-B,KX-C,KX-D -n 3 --max-per-cluster 1 --max-corr 0.5
kalshi basket build --theme "Iran Escalation" -n 4 --max-per-cluster 1 --max-corr 0.5 --auto-probs --bankroll 1000
# Sanity-check a proposed basket before placing orders (one call, server-side)
kalshi basket validate --tickers KX-A,KX-B --bankroll 1000 --max-corr 0.5
kalshi basket validate --theme "Iran Escalation" --bankroll 1000
# → cluster breakdown, pairwise correlations (top by |corr|), calendar
# clashes (weeks where many legs resolve), duplicate underliers, warnings.
themes is a local registry of editorial narrative buckets (e.g. "AI Race Milestones", "Iran Escalation") that maps to lists of Kalshi series with optional
$ claude mcp add kalshi-trading-bot-cli \
-- python -m otcore.mcp_server <graph>