Arena

Arena CLI

Install the CLI

Your own login, the whole product, from a terminal. Node 20 or newer.

# install the binary (the agent prompt and the hook call arena)
npm install -g arena-prediction-cli
arena login

# or try it without installing (arena is not added to your PATH)
npx arena-prediction-cli login

One sign-in is enough. Your agent and the MCP server act with that login. For an agent, install the binary, because the prompt and the hook call arena directly.

Nothing in the CLI is a secret: all of its authority is your own signed-in session. There is nothing else to install for agent use. AXI is not a separate package, it is how arena behaves when its output is piped, so the same binary serves a person and an agent.

Sign in

Arena has no password login. arena login hands the browser the interactive step and catches the redirect on a loopback port.

$ arena login
arena: opening your browser to sign in. If nothing opens, visit:
  https://<auth host>/authorize?provider=google&redirect_to=http://127.0.0.1:53682/callback…
userId          4d2f8c1e-9b0a-4c6e-8f21-3a7b5d9e0c12
displayName     sharp_joe
isPro           true
balanceDollars  $1,046.00
monthKey        2026-09

Next:
  arena whoami
  arena balance

Providers

arena login --provider apple signs in with Apple instead of Google. There is no guest or anonymous sign-in: the CLI acts for an account, so every trade and every record belongs to the person who signed in.

Headless machines

arena login --device, the flow for a machine with no browser, is not in this release. On a headless box, sign in on a machine that has one and copy ~/.config/arena/credentials.json across.

Where credentials live

In your OS keychain, falling back to ~/.config/arena/credentials.json with mode 0600. The access token lives about an hour and refreshes itself; arena logout deletes the stored pair.

Command reference

Reads work signed out where the data is public. Writes need a session.

arena
Home view. Live balance, open-position count, season and next steps, not help text.
arena login [--provider google|apple]
Sign in. Opens a browser and catches the redirect on 127.0.0.1. --device, the headless flow, is not in this release.
arena logout
Forget the stored credentials.
arena whoami
Who you are signed in as, membership status, spendable balance, season.
arena markets [--sport …] [--league …] [--event …] [--limit 20]
Browse open markets. Default limit 20.
arena market <ticker|ins_id> [--contracts N]
One market in detail. Takes a ticker, an Arena instrument id (ins_…) or its slug; with an id, the output adds buy_for_yes and buy_for_no, the side of the ticker that holds each side of the instrument. --contracts N adds venue_fee_est_dollars, the estimated venue fee for that size, which is not charged on paper.
arena search <query>
Substring search over titles and tickers.
arena resolve <text…> [--limit 10]
Turn a bet in words, such as "chiefs ml", "kc -3.5" or "kc mia under 44.5 sunday", into an Arena instrument id, the ticker and the side to buy: the next step is arena buy <ticker> --side <buy_side>. NFL full-game moneylines, spreads and totals on half-point lines. It never guesses, so no rows means rephrase. Works signed out.
arena instrument <ins_id|slug>
One Arena instrument: its label (always its YES side), type, line, start time and each listed ticker with buy_for_yes and buy_for_no; --json adds yes_means, the YES side in a sentence. A ticker works too and finds the instrument listed on it. Works signed out.
arena game <game_id|slug|words…> [--type ml|spread|total]
One game and every Arena instrument on it, with their ids: moneylines first, then spreads and totals by line. No prices. Spreads and totals are added closer to kickoff. Works signed out.
arena games [--league nfl] [--date today|YYYY-MM-DD] [--week N] [--limit 20]
Upcoming games with their Arena game ids and how many instruments each has. --date is one calendar day in America/New_York. Works signed out.
arena catalog
The groups and leagues you can filter by. not yet shipped
arena screener [--league L] [--group G] [--min-volume N] [--max-spread C] [--price-min C] [--price-max C] [--closes-within 4h] [--min-move C] [--sort volume|move|spread|close_time] [--limit 20]
Screen open markets by volume, price, spread, time to close and move over about 24 hours. Rows add spread_cents and a signed move_cents. Needs arena login.
arena orderbook <ticker|ins_id> [--depth 10]
Resting bids and asks. Takes a ticker, an instrument id or its slug.
arena chart <ref> [--range 1h|6h|24h|7d] [--points 12]
A market's recent price path for a ticker, an instrument id or its slug: open, high, low, now, the change and a sparkline. For an instrument whose YES is the ticker's NO, the numbers price the instrument's YES, and ticker_side says which side was charted. Needs arena login.
arena buy <ticker|ins_id> --side yes|no --contracts N [--max-price CENTS] [--limit CENTS] [--tif gtc|ioc|fok] [--expires 4h] [--yes] [--dry-run]
Open a position. Without --limit it quotes, confirms, places and reconciles the actual fill against the quote. With --limit it names your price: the order fills at that price or better, or rests until it does. With an instrument id or slug, --side is the instrument's side: the CLI maps it to the ticker's side, and the quote and the receipt show both (instrument_side, ticker_side). --dry-run also shows venue_fee_est_dollars, the estimated venue fee, not charged on paper, and what walking the book for that size would cost (walk_vwap_cents, walk_slippage_cents).
arena sell <trade-id> [--limit CENTS] [--tif gtc|ioc|fok] [--expires 4h] [--yes] [--dry-run]
Close a position at the live bid, or rest a limit exit with --limit. Trade ids come from arena positions.
arena orders [--status resting|executed|canceled|all] [--ticker T]
Your limit orders. Resting by default: the ones still holding money and still able to fill on their own. --ticker takes the market's ticker. With --json, or --fields naming them, rows also carry instrument_id, instrument_label and instrument_side.
arena cancel <order-id> [--yes]
Withdraw a resting order and get its hold back. Cancelling one that already filled is not an error: it answers reducedBy 0 and the trade id.
arena settle
Settle anything already resolved. A backstop: the server settles automatically within about five minutes.
arena positions [--live]
Open positions with unrealised P&L. --live adds current prices with one extra market read. With --json, or --fields naming them, rows also carry instrument_id, instrument_label and instrument_side.
arena balance
Spendable balance and net worth.
arena history [--month 2026-08]
Your settled trades. --month reads a past season (a calendar month in America/New_York). Instrument columns as for arena positions.
arena stats [--month YYYY-MM] [--by league|band|hold]
Your season graded: win rate against the prices you paid, calibration by price band, closing-line value, return on stake and drawdown. --by adds a breakdown by league, entry price band or how the trade ended. An empty season prints zero counts and an emptyReason. Needs arena login.
arena picks
Today’s AI picks.
arena leaderboard [--top 25]
This season’s standings, with the AI models and the paper funds ranked in alongside the players, exactly as the app ranks them. Rows carry an AI, ETF or Team fund badge.
arena trader <ref> [picks]
A published trader record. Public, so it works signed out.
arena watch <ticker…> [--orderbook]
Live prices, repainted in place. not yet shipped
arena hook install
Install the ambient-context hook into your agent runner. not yet shipped

Flags that work everywhere

--json
Raw JSON on stdout. Works in both modes, on every command. The stable escape hatch.
--fields a,b,c
Widen a list beyond its default three or four columns.
--full
Stop truncating long text.
--yes
Skip the confirmation prompt. In agent mode buy, sell and cancel need it, and without it they exit 2 and send nothing. arena settle does not, because it only settles trades whose markets have already resolved.
--dry-run
On buy: the price and the stake, plus the estimated venue fee (not charged on paper), with nothing sent. On a market sell: only the position it would sell (ticker, side, contracts), with no price, so read yes_bid or no_bid with arena market <ticker> for that. cancel has no dry run.

A first session

Terminal samples on this page use the placeholder tickers ARENA-EXAMPLE-1 and ARENA-EXAMPLE-2. Real tickers come from arena markets and arena search.

human mode (a TTY)
$ arena balance
dollars           $1,046.00
netWorthDollars   $1,058.40
openStakeDollars  $12.40
monthKey          2026-09

Next:
  arena positions
  arena history

$ arena buy ARENA-EXAMPLE-1 --side yes --contracts 10
Example market — yes @ 62c ask (bid 58c) · stake $6.20 · balance $1,046.00 -> $1,039.80
Fills server-side at the LIVE ask — the fill may differ from this quote.
buy 10 contracts? [y/N] y
placed           true
tradeId          6f1c2a3b-4d5e-4f60-8a71-b2c3d4e5f607
ticker           ARENA-EXAMPLE-1
side             yes
contracts        10
quotedAskCents   62
entryPriceCents  63
stakeDollars     $6.30
idempotencyKey   0b9e8d7c-6a5b-4c4d-9e3f-2a1b0c9d8e7f
slippageCents    1

Next:
  arena positions
  arena sell <trade-id>

$ arena positions
ID                                    MARKET_TICKER              SIDE  CONTRACTS  UNREALIZEDPNLDOLLARS
6f1c2a3b-4d5e-4f60-8a71-b2c3d4e5f607  ARENA-EXAMPLE-1            yes          10                $0.40

totalCount  1

$ arena sell 6f1c2a3b-4d5e-4f60-8a71-b2c3d4e5f607 --yes
sold            true
tradeId         6f1c2a3b-4d5e-4f60-8a71-b2c3d4e5f607
sellPriceCents  67
pnlDollars      $0.40
idempotencyKey  3c2b1a09-8f7e-4d6c-b5a4-93827160f5e4

Three things about that buy

That was a market order: you never set a price, and the fill happens server-side at the live ask, which is why the CLI reconciles the actual fill against the quote and tells you the slippage. --max-price refuses to submit when the quoted ask is above your ceiling. And every buy carries a fresh idempotency key. If the request gets no answer, the CLI retries it with that same key, which can never fill twice. Do not resend the buy yourself: running arena buy again sends a new key and can open a second position, so check arena positions first.

Naming your own price

Pass --limit to place a limit order instead. It fills only at that price or better, and otherwise rests until it fills, reaches --expires, or you cancel it. A resting buy holds the cost out of your balance and returns it in full on cancel; a resting sell holds nothing, because the position is the collateral. --tif ioc or fok never rests. See your resting orders with arena orders and withdraw one with arena cancel.

Packages

Four packages on npm, one machine-readable spec, one file for language models.

arena-prediction-cli 0.3.0
The arena command: paper trading from a terminal, dual-mode for agents (AXI).
arena-mcp-server 0.3.0
The local stdio MCP server, run with npx -y arena-mcp-server. Reads the CLI’s stored login.
arena-mcp-tools 0.3.0
The tool catalog the server registers, for embedding in another MCP host.
arena-core 0.2.0
Auth, endpoints, credential storage and the typed API client the three share.

Specifications

GET https://arena-predictions.com/api/v1/openapi.json is the OpenAPI 3.1 document for the live endpoints; /llms.txt is the short version for a language model. The CLI and the MCP server call the same backends the website does, through arena-core. There is no separate SDK for the HTTP API.