Skip to content
| Marketplace
Sign in
Visual Studio Code>Visualization>Token ForgeNew to Visual Studio Code? Get it now.
Token Forge

Token Forge

Kyle Sullivan

|
1 install
| (0) | Free
A pixel-art blacksmith forge in your sidebar that burns hotter and smokes more the more tokens your AI agent spends.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

Token Forge

A pixel-art blacksmith forge in your VS Code sidebar that burns hotter and smokes more the more tokens your AI agent burns in the current turn.

Quick question → a few embers. Big refactor → a white-hot roaring blaze.

Status: working prototype

Verified end-to-end against live session data:

claude-code    lastActivity=2s ago    tokensThisTurn=20757  -> intensity 0.558
copilot-chat   lastActivity=934s ago  tokens=13  credits=11.16675
MUX picks: claude-code

How it works

Heat providers (src/providers.ts) read whichever agent you're using and normalize it to one number. Both sources were confirmed to persist real per-turn usage on disk:

Tool Source Fields Status
Claude Code ~/.claude/projects/<workspace>/<session>.jsonl message.usage.output_tokens summed since the last real user prompt verified live
GitHub Copilot Chat <VSCode>/User/workspaceStorage/<ws>/chatSessions/*.jsonl outputTokens / completionTokens / copilotCredits verified live
GitHub Copilot CLI ~/.copilot/session-state/<id>/events.jsonl assistant.message.outputTokens, reset on user.message verified live
OpenAI Codex ~/.codex/logs_2.sqlite and its -wal total_usage_tokens per turn; turns ordered by the UUIDv7 timestamp embedded in turn.id verified live

Copilot CLI also mirrors totals into session-store.db, but the JSONL event log is used instead so the extension takes on no SQLite dependency.

HeatMultiplexer picks whichever tool wrote most recently, so it follows the agent you're actually using. toIntensity() maps usage → 0..1 on a log-ish curve (ordinary turns still show real fire; huge turns go white-hot).

Five themes ship with it — forge, arcane, rainbow, necrotic and ash. Each is a different furnace with its own flame ramp, glow and ember tints, switchable live from settings.

The fire is 100% procedural (media/forge.js) — no animation assets:

  • Doom-fire cellular simulation seeded from the coal bed; higher intensity = less decay = taller, brighter flames
  • 64-step palette: black → red → orange → amber → warm gold. Orange is held high up the ramp so a full blaze still reads as fire instead of washing out
  • Smoke whose volume, rise speed and lifetime all scale with heat, so a cold forge wisps and a hot one throws a tall billowing column. The ramp is linear-dominant — an earlier quadratic left mid-range turns (~10k tokens) reaching only a fifth of the available height. The canvas carries 118px of headroom, and the smoke is mid-gray so it reads on both dark and light editor themes. Puffs are blitted from one pre-rendered sprite rather than built per particle, which keeps hundreds of them cheap. Rise speed is tuned so the column burns out before the top of the canvas — note that velocity damping means travel is vy·(1−0.996^N)/0.004, not vy·N, and getting that wrong guillotines the plume at high heat. An alpha ramp over the last 34px catches any outliers.
  • Embers from the fire, plus sparks carried up the chimney once it's really hot; spawn rate scales with the square of intensity
  • Heat haze in the flue column — from just above the flames up through the hood and out the top of the chimney, i.e. the path the hot air actually takes, and horizontally confined to the channel above the fire opening so the outer brick piers stay still. The wobble is feathered across that channel (full mid-column, zero at the sides) so there's no seam against the stationary brickwork. Amplitude is deliberately small (~2px): the sprite has hard pixel edges, so a large per-row shift breaks the hood's silhouette and reads as a glitch. The smoke above the chimney has already cooled, so it is left crisp.

Worst-case cost measured at 0.55 ms/frame (intensity 1.0, ~350 smoke particles, 220 embers, haze on) — roughly 3% of a 60 fps budget.

  • A radial glow that lights the surrounding brick
  • Everything is clipped to the detected firebox cavity mask

The only art assets are the five forge bodies (media/forge*.png), cleaned from AI references with unfake.js — the same pipeline used for the Jimothy pet. Each furnace's firebox cavity is detected automatically: the cavity is a large flat field of a single colour, so it is found by sampling the middle of the arch and then eroding the matching mask to break the thin outlines that otherwise connect it to the sprite's edge.

Layout

src/providers.ts   heat interface + Claude Code / Copilot adapters + multiplexer
src/extension.ts   webview view provider, polls providers, posts heat messages
media/forge.js     procedural fire / smoke / ember / glow engine
media/main.js      webview entry — eases intensity, drives the render loop
media/forge.png    the forge sprite (from Furnace.png via unfake)
media/forge_regions.json  detected firebox + chimney coordinates

Run it

npm install
npm run compile
# then F5 in VS Code to launch the Extension Development Host

Open the Token Forge view in the activity bar and ask your agent to do something big.

Changing theme

Run Token Forge: Change Theme from the command palette, or use the palette button on the view's title bar. Themes preview as you arrow through them and revert if you cancel. The tokenForge.flameTheme setting can also be edited directly; either way the change applies without reloading.

Settings

Setting Default Meaning
tokenForge.flameTheme forge Flame colours: forge, arcane, rainbow, necrotic, ash
tokenForge.fullBlazeTokens 60000 Tokens in one turn = white-hot (lower = ramps up sooner)
tokenForge.pollMs 1000 How often to re-read session data
tokenForge.coldAfterSeconds 300 Idle time after which the forge goes cold

Known gaps / next steps

  • No agent streams partial usage to disk, so counts arrive per completed model message. The forge animates between readings rather than inventing numbers; a genuinely live count would need an API-proxy approach.
  • Codex's log format is confirmed, but only thread_title generations have been observed so far. Turn grouping (currently a 25s activity gap) should be re-checked against a real agent turn.
  • Ideas: coal pile that depletes, anvil + Jimothy working the bellows, status-bar mini-flame, cumulative session totals.

Agent support

Agent Status Source
Claude Code ✅ Verified ~/.claude/projects/**/**.jsonl — message.usage.output_tokens
GitHub Copilot Chat ✅ Verified chatSessions/*.jsonl in workspace storage
Copilot CLI ✅ Verified ~/.copilot/session-state/*/events.jsonl — outputTokens
Codex (openai.chatgpt) ✅ Verified ~/.codex/logs_2.sqlite (+WAL) — total_usage_tokens per turn.id

Whichever tool wrote most recently wins, so switching agents switches the fire. If nothing is active, the forge sits cold with banked embers.

On Codex: real agent turns are recorded in ~/.codex/logs_2.sqlite, not in the extension-host log (which only carries internal generations such as thread titles). To avoid a SQLite dependency the adapter scans the tail of the database and its WAL; because WAL frames are not in write order, turns are sequenced by the Unix-millisecond timestamp embedded in each turn.id (a UUIDv7) rather than by file position.

A note on live updates: every one of these tools writes usage only when a model message completes — nothing streams partial counts to disk. The forge therefore receives usage in steps, and animates the counter up to each new reading rather than snapping. The number shown is always one the agent actually reported; nothing is extrapolated.

Where it lives

The forge appears as a section in the Explorer sidebar, so it stays visible while you work with your files. Drag its header to move it anywhere you like — the secondary sidebar, the bottom panel, or its own activity-bar container. Drag the section divider to resize it; the forge scales to fit.

For a big view, run Token Forge: Open in Editor Tab from the Command Palette — it opens as a normal editor tab you can split, move, and resize freely.

Scoping

Every provider is restricted to the window's workspace, so multiple VS Code windows each show their own project's activity rather than mirroring one another. Claude Code reads only its encoded project directory, Copilot Chat only this window's workspaceStorage entry, and Codex — which keeps one shared log — filters turns by the working directory recorded against each thread.

Privacy

Token Forge reads only token/usage counters from agent session data that already exists on your machine:

Agent File read What is read
Claude Code ~/.claude/projects/<workspace>/*.jsonl usage.output_tokens per message
GitHub Copilot Chat VS Code workspaceStorage/**/chatSessions/*.json per-response token/credit counters

It does not read, store, or transmit your prompts, your code, or model responses. Nothing leaves your machine — it makes no network calls, and has no telemetry, and no analytics of any kind. Everything is rendered locally in a webview.

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft