docs › AI scan mode
AI scan mode
An observe-only watcher that scores every coin on screen, pulls up the one that lights up, and keeps analysing it.
AI scan mode watches the screener for you: it scores every coin from data the app already holds, and when one crosses the line it opens that coin's token screen and starts a short analyst read. It is off by default, it adds no network requests, and it is observe-only: a scan session can never open a ticket, sign, confirm or trade. Four structural layers enforce that, not a prompt.
Keys, flag, command#
- Z toggles the scan from any screen. R resumes scanning after a lock (releases the coin).
- esc on the locked coin cancels the analysis but keeps the coin (state PAUSED); a second esc navigates as usual. esc on the screener table while SCANNING stops the scan.
--scanstarts it with the run;--scan-*flags set thresholds and caps (full list in the CLI reference)./scanon the screener's / line or in the chat input:/scan(toggle) ·/scan on(on) ·/scan start(on) ·/scan off(off) ·/scan stop(off) ·/scan resume(resume) ·/scan next(resume) ·/scan status(status)
The header shows ◉ AI SCAN SCANNING · ai 1/8 per h while it is on. Row 1 of every list screen carries the ticker: state, coins scanned, the top scores with the triggers that fired. On the locked coin's screen the same row reads WHY IT TRIGGERED: the reasons with their numbers, the score, when, how many reads, and the keys.

Triggers and score#
Inputs come from memory and the local SQLite cache only: the screener rows, the DexScreener pair already cached for the flow panel, the open token's loaded view, and LARP verdicts that already exist. A unit test wraps the HTTP client and asserts zero calls over fifty scan ticks; measured live, requests per minute with the scan on and off were the same.
| trigger | fires when (defaults) | weight |
|---|---|---|
vol | 5m volume ≥ 3× the coin's own average 5-minute pace (6h, falling back to 1h/24h), at least $2,000; full strength at 10× | 30 |
flow | buy/sell flip: 5m buy share ≥ 0.62 while the 1h share ≤ 0.52, at least 20 5m transactions | 25 |
fresh | age ≤ 60 min, ≥ 40 5m transactions, 5m buy share ≥ 0.58, 5m volume ≥ $5,000 | 20 |
breakout | last close above the prior 20 cached candles' high by ≥ 2% (only coins whose candles are already loaded, in practice the open one) | 20 |
liq | liquidity ≥ +20% vs the coin's own 10-minute minimum | 15 |
holders | holders ≥ +5% and ≥ +25 vs the oldest 10-minute sample | 15 |
Points per fired trigger = weight × (0.5 + 0.5 × strength); the score is the sum, capped at 100. A coin is exciting at score ≥ 45 with ≥ 2 triggers. Gate: liquidity ≥ $10,000. Vetoes set the score to zero and say why: an existing LARP verdict (the detector is never invoked by the scan), or a mint or freeze authority that is still enabled.
States#
off → scanning (a 30 s warm-up builds the rolling samples; the ticker shows the top five) → locked (one coin: its token screen opens, the analyst starts, refreshes follow) → paused (esc: analysis cancelled, coin held) → scanning again only on R.
No-hop rule: while locked or paused the engine never returns a new lock, even if a higher-scoring coin appears (proven by a test feeding one for 300 ticks). A lock also waits while a PAPER ticket, an overlay, the filter or sort editor, or a half-typed question has the keys, so you are never yanked out of something.
Cost control#
Every analyst turn the scan starts counts against two caps: 8 per rolling hour and 4 per coin per hour; a lock needs budget for one turn. A refresh of the locked coin happens only when ≥ 90 s have passed since the last read, the analyst is idle, and the data materially moved (price ≥ 3%, 5m buy share ≥ 10 points, 5m volume up or down 1.5×, or a new trigger). After a lock ends the same coin is barred for 15 min and no new lock happens for 60 s. The header meter shows ai used/cap per h · coin n/4.
In calm mode the scan adds no draws; measured idle CPU with the scan on was the same 2% median as off.
The read#
A lock opens the coin exactly as ⏎ would (the same loader, the same fetches that token costs anyway) and starts a chat turn asking for the short read, with the WHY reasons passed as numbers only, never token text. Refreshes ask the same warm session what changed. Answers follow the short style: call, why, levels, size, one risk.
Safety: four layers#
- The scan session is created with an empty action-type list. The shared validator that every analyst action passes through refuses all five UI actions for it.
- The screen state the MCP server sees carries
actions.types = [], so every action tool errors inside the server and writes nothing to the action channel. - The
claudelaunch adds--disallowedToolsforopen_ticket,open_token,show_in_screener,add_to_watchlistandswitch_feed. - The app's scan handler re-validates with the same empty list and toasts
AI scan blocked analyst action "…" · observe-onlyso you see any attempt.
Statically, the scan code imports nothing from the trade, paper, executor, bridge or wallet modules; a test resolves its whole import closure and fails if a trade import is planted. A compromised-model test feeds a fake claude that emits open_ticket during a scan and asserts nothing happens, while the same fake opens the PAPER ticket in a normal session.