Skip to content

v2.0.0

Choose a tag to compare

@osauer osauer released this 11 Jul 20:53

The data flows out. Orders don't go in.

ibkr is a read-only interface to your Interactive Brokers account, reachable from a Go library, a shell CLI, a stdio MCP server (Claude Desktop, Cursor, Continue, Zed), and a Claude Code plugin. Hand it to an assistant, a cron job, a notebook, or your own service.

What's new in v2.0.0

  • v2.0.0 is a Go-library major, not a product rewrite. The ibkr CLI, daemon, MCP tools, and paired app behave the same as v1.15 plus the improvements below; the major bump exists because the published pkg/ibkr Go API modernized in one breaking pass (context-first methods, no Get prefixes — details under Changed) and Go-module semver therefore requires the module path to move to github.com/osauer/ibkr/v2. Action required only for Go developers importing the library: update imports to github.com/osauer/ibkr/v2/pkg/ibkr and installs to go install github.com/osauer/ibkr/v2/cmd/ibkr@latest. Binary, MCPB, and plugin users are unaffected.
  • Trading rulebook v2, from the 2026-07-08 dual senior review against a live confirmed-stress tape. The checklist grows from 12 to 14 rules: rule 13 exit_discipline fences long-option losses at −40% of premium paid (watch) / −60% (act), with classified hedge legs exempt — the hedge is allowed to decay — and an advisory preview warning when a draft would average down into a flagged line (averaging down resets the basis; the fence does not follow it down). Rule 14 fx_exposure makes non-base-currency NLV explicit (watch-only above 60% — a structural breach must inform, not become a permanently lit act). Rules 3/4/12 thresholds are now regime-conditional: the daemon latches the regime lifecycle stage (persisted across restarts, so a bounce mid-stress cannot reset thresholds to calm), buckets it calm / early_warning / confirmed (cash floor −25/0/+10% of NLV; ex-hedge extrinsic budget 10-15/7.5-12/5-10%; hedge band 25-35/30-50/40-70%), and a carried or never-seen stage evaluates BOTH the carried and calm sets and reports the worse verdict — stale regime data can hold or tighten a verdict, never relax it, in either band direction. Partial data may now indict but never acquit: rule 1 reports provable lower-bound breaches ("at least X% of NLV", observed_is_lower_bound) from signed interval arithmetic when deltas are missing, instead of hiding a certain breach behind unknown.

Claude Desktop MCPB

Download ibkr.mcpb from the Assets section below or from:

https://github.com/osauer/ibkr/releases/latest/download/ibkr.mcpb

Open the .mcpb file with Claude Desktop, drag it into Claude Desktop, or use Settings -> Extensions -> Advanced settings -> Install Extension. The bundle carries the local ibkr binary for macOS and Linux. Windows is not supported outside WSL because the daemon uses Unix-only primitives.

Shell and generic MCP install

curl -fsSL https://raw.githubusercontent.com/osauer/ibkr/main/install.sh | sh
ibkr setup claude-desktop

The first command picks the right binary for your platform, verifies its SHA-256, installs it to ~/.local/bin/ibkr, and adds that directory to your PATH if needed. On macOS it also clears the Gatekeeper quarantine flag. The second command writes the legacy MCP server entry into Claude Desktop's config; fully quit Claude Desktop and reopen.

If you only want the shell tool, stop after the first command and try:

ibkr account
ibkr quote AAPL
ibkr positions --by underlying

Prerequisite: a running IB Gateway 10.37+ or TWS (paper or live) on the same machine. The daemon auto-discovers it across the four standard ports.

See the README for the full feature menu and the troubleshooting matrix. Read-only by construction; the Safety section walks through the four guards.

⚠️ Broker-write capable build (ibkr-trading-* tarballs)

Everything above — the installer, the MCPB bundle, and the plain ibkr-v2.0.0-* tarballs — is read-only by construction: order transmission is not compiled in.

The ibkr-trading-v2.0.0-* tarballs are different: that binary can place, modify, and cancel orders with your broker once you configure the trading gates ([trading] mode plus a pinned gateway endpoint and account, cross-checked against the connected session; every write still needs a submit-eligible preview token). Only download it if you intend to trade through ibkr. Before enabling anything, read SECURITY.md and the trading preview guide, start against a paper account, and verify with ibkr trading status. Each release's order pipeline is exercised by an automated paper-trading round-trip before tagging.


Paranoid? Inspect the installer before running it

curl -fsSL https://raw.githubusercontent.com/osauer/ibkr/main/install.sh -o install.sh
less install.sh
sh install.sh

Doing something custom?

  • go install: go install github.com/osauer/ibkr/v2/cmd/ibkr@v2.0.0 (or @latest).
  • Different install dir: IBKR_INSTALL_DIR=/usr/local/bin sh install.sh. The installer won't touch your shell rc when you override; manage PATH yourself.
  • Manual download: pick a tarball or .mcpb from the Assets section below. Verify against SHA256SUMS.
  • Cursor / Continue / Zed / other local MCP clients: see Pick your path in the README for the JSON snippet (config file path differs per client).
  • Claude Code: /plugin marketplace add osauer/ibkr then /plugin install ibkr@ibkr inside any session.

Windows isn't supported. The daemon uses Unix-only primitives (setsid, flock, AF_UNIX sockets). WSL works.


Added

  • Rule 2 hedge-premium tier: option lines classified as rule-12 hedges measure against 15%/25% of NLV instead of the 5%/10% speculative tier, disclosed per offender — the designated hedge no longer tops the premium list every single day (alarm-fatigue fix), while rule 12 gains an act tier at more than twice the band top ("a directional short wearing a hedge's clothing"). The two changes ship atomically: a hedge past twice the band top always keeps an act somewhere.
  • Rule 7 now covers short puts spanning an earnings print: watch by default, act when the line's assignment notional reaches 10% of NLV (or a name's spanning short puts together reach 20%) — a gap through the strike is a forced size-up on earnings day.
  • Option legs whose greeks tick carried no underlying spot now borrow the same-name stock leg's account mark (disclosed as stock_leg_mark, quality-gated, never classifying hedge legs), so rules 4 and 6 evaluate pre-market for stock-backed names instead of reporting unknown until the option surface opens.
  • The rules result's input_health gains a regime_stage row; row notes disclose which regime threshold set applied and why.

Fixed

  • Rule 6 (catalyst_coverage) could assert pass with every option leg's OTM-ness unassessable: legs with no underlying spot were silently skipped, so pre-market the rule passed a book holding an OTM call that expires five days before its name's earnings — a live violation of the never-false-pass invariant, observed 2026-07-08. Such legs are now named unknowns, and the property test covers per-leg nil underlying with healthy positions.
  • Rule 8 (earnings_size_freeze) had the same silent-skip shape: names with material greeks gaps were dropped from the sweep entirely, letting the rule pass while rule 1 reported the same name unknown. Gapped names now stay unknown offenders unless earnings are provably beyond the freeze window.
  • The rules-decisions journal now creates its state directory before appending (matches the order/regime journals); previously a missing ~/.local/state/ibkr/ made journaling silently no-op.
  • Gateway-down reconnect attempts are now paced by an exponential backoff (1s→2s→4s→8s, capped at 15s), and the per-attempt "connection failed" line dropped from Error to Debug. Reconnection is demand-driven — every read handler that finds the connector down triggers one — and a refused dial returns instantly, so a multi-hour outage retried ~2.6×/s and wrote 66,900 identical connection refused lines to ibkr-daemon.log over a single 7h gateway outage (observed 2026-07-08). The streak resets on a completed handshake and stays exempt on the first attempt, so a fresh drop still reconnects immediately; the 15s cap stays below the CLI's 25s ibkr status handshake wait, so a Gateway→TWS switch still recovers in one invocation.

Changed

  • Breaking — pkg/ibkr Go API, and the module path is now github.com/osauer/ibkr/v2. The published client library dropped its pre-context idioms in one pass; the ibkr CLI, daemon, MCP, and app surfaces are unaffected. Accessors lose the Get prefix (CachedPositions, OptionIV, OptionGreeks, OptionUnderlyingPrice, OptionQuoteBidAsk, OptionPrevClose, MarketDataTypeForSymbol, Connection.MarketDataType), and GetMarketData is now MarketDataSnapshot — the bare name would collide with the MarketData type. The five X/XCtx method pairs collapsed to one ctx-first method each: FetchHistoricalDailyBars(ctx, symbol, lookbackDays, timeout), FetchHistoricalDailyBarsWhatToShow(ctx, symbol, lookbackDays, whatToShow, timeout), FetchHistoricalDailyBarsWithContract(ctx, contract, lookbackDays, timeout) — timeout ≤ 0 keeps the 45 s default, and a ctx deadline always caps the effective budget — plus Connection.RequestHistoricalData(ctx, …) and Connection.CancelHistoricalData(ctx, reqID). Nil contexts are no longer tolerated (the 21 per-method ctx == nil guards are gone; pass context.Background() explicitly). The unused Order struct left the public surface (internal trackedOrder now); IBKROrder stays the wire type and the OrderSide/OrderType/TimeInForce/OrderStatus enums are unchanged.
  • Rulebook policy rulebook-v1rulebook-v2 (version 2): every new threshold is part of the policy fingerprint, and the flat rule-3/4/12 threshold fields moved into the three regime sets (the calm set carries the v1 numbers unchanged).
  • Design doc corrected where it had drifted from the implementation: the rules-decisions journal lives under ~/.local/state/ibkr/, rules 9/10 read a dedicated best-effort SPY snapshot quote (not the regime snapshot), and the operator TOML policy override is documented as planned, not shipped.

Engineering notes

  • Repo-wide taste-review pass (2026-07-11), no behavior or rendered-output changes: the ±2% dealer-gamma band and its gap→regime classifier now live once in internal/rpc/regime_policy.go (GammaRegimeFromGap, GammaBucketRegime, HeuristicThresholds) instead of six hand-coded copies across daemon and CLI — the same single-copy treatment the 2026-06-12 incident forced on regime headlines; fixed-fractional sizing moved from the CLI adapter into internal/risk (risk.ComputeSize), so MCP no longer imports a sibling adapter for policy math; computeGammaZeroFor decomposed from 604 to 399 lines (contract prewarm and leg fan-out extracted with their abort machinery); dead SPA CSS and an inert IBKR_HANDSHAKE_PERMISSIVE test knob deleted.