agi-fireworks
v0.2.2
Published
Turn local coding-agent session logs into a private, offline fireworks show.
Maintainers
Readme
AGI Fireworks
Turn coding-agent session logs into a private fireworks show.
AGI Fireworks collects local sessions from Claude, Codex, Grok Build, Antigravity, Cursor, Qoder, and Cockpit (OpenCode), then generates one self-contained HTML file.

A demo generated with agi-fireworks --demo --all-time. Gold trails are
large sessions, while blue and purple chrysanthemums are standard sessions.
One session becomes one shell. Tool-call count controls the burst size, the agent controls the color, and start time controls the launch position. Sessions that use sub-agents become cluster shells, large jobs become golden crowns, and sessions with errors become erratic bee shells.
Logs are read only while the HTML is generated. Nothing is uploaded. The generated file contains no external resources and does not use
fetch,XMLHttpRequest,WebSocket, orsendBeacon.
Quick start
Run without installing:
npx agi-fireworksOr install the CLI globally with one command:
npm install --global agi-fireworksThen generate a show from anywhere:
agi-fireworksThe generated fireworks.html opens automatically in your default browser.
The show waits at a sound-first start screen because browsers require a user
gesture before WebAudio can play. Select Start with sound to begin the
visuals and synthesized audio together. Start silently remains available
when audio is not appropriate.
By default, the show contains the latest 31 calendar days, including today.
Days without collected sessions remain visible as empty nights, so every
default show has the same 31-night timeline. The collector automatically skips
agents whose log locations do not exist. Use --no-open when generating a file
for automation or later viewing.
Requirements:
- Node.js 18 or newer
sqlite3only when collecting Cockpit (OpenCode) sessions; other agents continue normally when it is unavailable
To preview the animation without reading local logs:
agi-fireworks --demoVideo export
Open the generated HTML and select Export video. The browser renders the
complete show, including synthesized audio, and downloads an .mp4 file.
- Current Chrome and Edge releases export the MP4 without waiting for the show to play in real time.
- Browsers with MediaRecorder MP4 support automatically fall back to real-time capture and tell you when the tab needs to remain visible.
- Select Cancel export to stop without downloading a file.
- The exported video contains the date, shell count, project labels, and final
summary. Press
Lbefore exporting to hide project labels.
Fast export uses the browser's built-in WebCodecs APIs with H.264 video and AAC audio. MediaRecorder MP4 capture remains an automatic compatibility fallback; WebM files are never produced.
CLI options
| Option | Description |
|---|---|
| --demo | Use synthetic data and do not read local logs |
| --anonymize | Replace project names with project-01, project-02, and so on |
| --no-open | Generate the HTML without opening a browser |
| --days N | Include and display the latest N calendar days; default: 31 |
| --all-time | Include all available sessions |
| --duration SECONDS | Set the show duration before the finale; default: 62 |
| --agents LIST | Limit collection to a comma-separated list; default: all |
| --logs PATH | Claude logs; default: ~/.claude/projects |
| --codex-logs PATH | Codex home; default: ~/.codex |
| --grok-logs PATH | Grok sessions; default: ~/.grok/sessions |
| --antigravity-logs PATH | Antigravity brain; default: ~/.gemini/antigravity-cli/brain |
| --cursor-logs PATH | Cursor projects; default: ~/.cursor/projects |
| --qoder-logs PATH | Qoder projects; default: ~/.qoder/projects |
| --opencode-db PATH | OpenCode database; default: ~/.local/share/opencode/opencode.db |
| --out PATH | Output file; default: ./fireworks.html |
Examples:
# Claude only, using the default 31-day window
agi-fireworks --agents claude
# Codex and Grok Build from the latest seven days
agi-fireworks --agents codex,grok --days 7
# Every available session with anonymized project names
agi-fireworks --all-time --anonymizePrivacy before sharing
The generated HTML contains project names and session timestamps. Before
sharing or streaming it, use --anonymize or press L during playback.
Playback controls
| Key | Action |
|---|---|
| ↑ / ↓ | Change volume in 5% steps |
| M | Mute or unmute |
| Space | Pause or resume |
| L | Show or hide project labels |
| R | Restart from the beginning |
URL parameters:
| Parameter | Example | Description |
|---|---|---|
| seek | ?seek=2026-07-07 | Start on a specific date |
| at | &at=0.05 | Start at a fraction of that date |
| still | &still=3 | Pause after N seconds for a thumbnail |
| labels | &labels=0 | Start with project labels hidden |
| flash | &flash=0 | Suppress full-screen flashes |
window.renderStill(date, fraction, seconds) renders one deterministic frame
without depending on requestAnimationFrame. It remains available for custom
thumbnail and frame-sequence workflows.
Flashing-light notice: the full screen flashes after bursts. Flashes are
automatically suppressed when prefers-reduced-motion is enabled. Use
?flash=0 to suppress them manually.
Shell types
| Shell | Appearance | Condition | |---|---|---| | Cluster | Child shells burst from a parent shell | The session used sub-agents | | Golden crown | A large gold burst with long trails | At least 110 tool calls | | Bee | Erratic zig-zag trails | The session had API errors or retries | | Peony | Short-lived points without trails | Three tool calls or fewer | | Chrysanthemum | Standard long-tailed burst | Any other session | | Shape | A logo-shaped burst | The final shell only | | Fizzle | Launches without bursting | The session ended while waiting for an answer |
The number of cluster-shell children matches the session's sub-agent call count, subject to a visual cap.
Add a custom shape
python3 tools/make_shapes.py your-logo.png --name yourlogoThe optional development script requires Python 3.8+ and Pillow. It traces the
dark portion of the PNG and writes normalized points into shapes.json. Add a
matching color to SHAPE_COLOR in template.html, then assign the shape key in
the finale logic.
The package includes a generic star and the AGI Cockpit outline. See
NOTICE.md for attribution.

From left: golden crown, shape shell, and cluster shell.
Audio
Playback is sound-first: the show begins only after Start with sound enables WebAudio, so the opening shells are never silently skipped. All sound is synthesized in the browser; the package contains no recordings. Three details create the result:
- An extremely sharp attack: the burst reaches 95% of its peak within 30 ms.
- A low-frequency body: distance absorbs most high frequencies, with a 7.2 kHz master low-pass filter.
- A long reflection tail: a generated 2.2-second impulse response simulates reflections from buildings and hills.
The launch whistle follows measurements from a real recording: a descending 3.5 kHz to 2.5 kHz fundamental, almost no harmonics, and a fast 16.8 Hz vibrato. The output chain uses compression and limiting so dense sequences do not clip.
Open tools/sfx.html to audition and tune each synthesized sound. To analyze a
recording and print target measurements:
python3 tools/analyze_audio.py firework.mp3That optional script requires ffmpeg, NumPy, and SciPy.
Project structure
build.mjs Dependency-free CLI and single-file HTML generator
collectors.mjs Agent-specific collectors that emit one common format
template.html Self-contained player template and video export
audio.js Standalone copy of the WebAudio synthesis module
shapes.json Shape outlines for star and Cockpit shells
test/ Node.js unit tests
tools/ Optional development utilitiesbuild.mjs embeds the collected data, metadata, and shapes into
template.html. Editing the template changes the generated player without a
separate frontend build step.
Collected data
Each session contributes only these aggregate fields:
| Key | Meaning |
|---|---|
| t | First session timestamp |
| n | Tool-call count |
| f | Number of touched files; paths are not retained |
| m | Predominant model family |
| g | Agent type |
| p | Project name, derived from the final directory segment |
| a | Sub-agent call count |
| x | API error or retry count |
| d | Whether the session ended while waiting for an answer |
Unavailable fields use 0. Codex and Grok Build, for example, count tool
events without expanding tool-input bodies, so their touched-file count is 0.
| Agent | Default input | Counted as a tool call |
|---|---|---|
| Claude | ~/.claude/projects/**/*.jsonl | tool_use |
| Codex | ~/.codex/{sessions,archived_sessions}/**/*.jsonl | function_call, custom_tool_call, and related events |
| Grok Build | ~/.grok/sessions/**/{summary.json,events.jsonl} | tool_started |
| Antigravity | ~/.gemini/antigravity-cli/brain/**/transcript.jsonl | tool_calls |
| Cursor | ~/.cursor/projects/**/agent-transcripts/**/*.jsonl | tool_use |
| Qoder | ~/.qoder/projects/**/*.jsonl | tool_use |
| Cockpit (OpenCode) | ~/.local/share/opencode/opencode.db | part.type = tool |
Prompt text, responses, source code, and tool output are never written to the generated file. File paths are discarded; only the count is retained.
Development
npm test
npm run build:demo
npm pack --dry-runThe npm package name is agi-fireworks. Publishing is intentionally a separate
maintainer action:
npm publish --access public