Skip to content

Commit bdf5b2d

Browse files
committed
feat: optimize loaders with memory-mapped SQLite and parallel workers, add build.sh automation, and integrate release-please
1 parent 628d7f6 commit bdf5b2d

38 files changed

Lines changed: 3198 additions & 200 deletions
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: release-please
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
permissions:
9+
contents: write
10+
pull-requests: write
11+
12+
jobs:
13+
release-please:
14+
runs-on: ubuntu-latest
15+
outputs:
16+
release_created: ${{ steps.release.outputs.release_created }}
17+
tag_name: ${{ steps.release.outputs.tag_name }}
18+
steps:
19+
- uses: google-github-actions/release-please-action@v4
20+
id: release
21+
with:
22+
config-file: release-please-config.json
23+
manifest-file: .release-please-manifest.json
24+
25+
goreleaser:
26+
needs: release-please
27+
if: ${{ needs.release-please.outputs.release_created == 'true' }}
28+
runs-on: ubuntu-latest
29+
steps:
30+
- name: Checkout
31+
uses: actions/checkout@v4
32+
with:
33+
fetch-depth: 0
34+
ref: ${{ needs.release-please.outputs.tag_name }}
35+
36+
- name: Set up Go
37+
uses: actions/setup-go@v5
38+
with:
39+
go-version: "1.22"
40+
41+
- name: Run GoReleaser
42+
uses: goreleaser/goreleaser-action@v6
43+
with:
44+
version: "~> v2"
45+
args: release --clean
46+
env:
47+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Binaries
22
thermal
3+
/dist/
34
*.exe
45

56
# Go

.goreleaser.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,13 @@ builds:
1212
goarch:
1313
- amd64
1414
- arm64
15+
flags:
16+
- -trimpath
1517
ldflags:
1618
- -s -w
19+
- -X github.com/jadmadi/thermal/internal/version.Version={{ .Version }}
20+
- -X github.com/jadmadi/thermal/internal/version.Commit={{ .Short_commit }}
21+
- -X github.com/jadmadi/thermal/internal/version.Date={{ .Date }}
1722

1823
archives:
1924
- format: tar.gz

.release-please-manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
".": "0.1.0"
3+
}

CHANGELOG.md

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
### Added
11+
12+
- **`build.sh` build automation script** — versatile build script supporting `--release` (`-ldflags="-s -w" -trimpath`), `--dev`, and `--upx` modes, cross-compilation (`--target` and `--all`), and detailed `--help` documentation explaining build trade-offs and binary sizes.
13+
- **`--verbose` / `-v` diagnostic flag** — outputs non-fatal tool loading failures, missing databases, and parsing warnings directly to `os.Stderr`.
14+
- **`thermal upgrade` command** — self-upgrade by checking GitHub Releases, downloading the matching binary for your OS/arch, and atomically replacing the running executable.
15+
- **`thermal version` command** — prints version, commit hash, and build date (injected via ldflags at build time).
16+
- **`internal/version` package** — build-time version embedding via `-ldflags`.
17+
- **Token Warriors / Activity Hunters split** — the leaderboard now separates tools with real token consumption data from tools that only track activity (messages, steps). Tools are auto-categorized based on whether token data is available.
18+
- **Cost column** in the leaderboard for tools that track cost (OpenCode, MiMoCode, codewhale). Sub-cent formatting shows costs like `$0.0032`.
19+
- **Devin loader** — extracts real token metrics from `message_nodes.metadata.metrics` (input, output, cache, reasoning tokens), session duration from `sessions` table, and engagement from `prompt_history`. Devin moved from Activity Hunters to Token Warriors.
20+
- **Codex loader rewrite** — reads `state_5.sqlite` (`threads.tokens_used`, `model`, `source`, `reasoning_effort`, `agent_role`, session duration) as the primary source, supplements with rollout JSONL for the input/output/reasoning/cache token breakdown. Codex moved from Activity Hunters to Token Warriors.
21+
- **codewhale loader rewrite** — extracts `metadata.total_tokens`, `metadata.cost.session_cost_usd`, `metadata.model`, `metadata.mode`, and `metadata.cumulative_turn_secs` from session JSON files. codewhale moved from Activity Hunters to Token Warriors.
22+
- **OpenCode loader rewrite** — leverages pre-aggregated `session.tokens_*` columns, `cost`, `agent`, and `summary_additions/deletions/files` for faster and more comprehensive data extraction.
23+
- **MiMoCode loader** — aggregates from `message.data.tokens` and surfaces `session.summary_additions/deletions/files` and agent distribution.
24+
- **Agy loader rewrite** — reads `overview.txt` from all brain sessions (was only reading `transcript.jsonl` from 1 of 14 sessions). Now surfaces 304 steps across 14 sessions instead of 57 steps from 1 session. Extracts model info from `transcript.jsonl` USER_SETTINGS_CHANGE events.
25+
- **Session duration tracking**`LongestSessionMs` field added to Summary, surfaced in dashboard for all tools that have session timestamps.
26+
- **Model breakdown**`ModelBreakdown` field shows which models were used per tool (e.g., Codex: gpt-5.4-mini:6, gpt-5.4:1).
27+
- **Agent/source breakdown**`AgentBreakdown` field shows source distribution (e.g., Codex: cli:7, vscode:3, exec:1).
28+
- **Lines added/deleted and files touched**`LinesAdded`, `LinesDeleted`, `FilesTouched` fields added to Summary for tools that track code diffs (OpenCode, MiMoCode).
29+
- **Progress bar** — new `internal/render/progress.go` for loading indicator, hardened with `atomic.Bool` and `sync.Once` for thread safety.
30+
- **Session cache**`internal/loaders/cache.go` for caching loader results.
31+
- **GitHub Actions release workflow** and **GoReleaser config** for cross-platform binary builds with version injection.
32+
33+
### Performance & Optimization
34+
35+
- **Devin SQLite database optimization** — added incremental delta scanning (`row_id > c.MaxRowID`), memory-mapped I/O (`PRAGMA mmap_size`), and byte-string pre-filtering (`chat_message LIKE '%"assistant"%'`), reducing query times on large (7GB+) databases from ~11s down to `< 2ms`.
36+
- **SQLite memory-mapped I/O across all loaders**`LoadOpenCodeData` and `LoadMiMoCodeData` benefit from `PRAGMA cache_size = -64000` and `PRAGMA mmap_size = 30GB` alongside raw string pre-filters.
37+
- **Parallel multi-worker loaders**`internal/loaders/agy.go`, `commandcode.go`, and `codex.go` use bounded parallel worker pools (limit of 8 concurrent workers) to scan multi-file directories and JSONL rollouts simultaneously.
38+
- **Binary size reduction** — configured `-trimpath` and `-ldflags="-s -w"` in `.goreleaser.yml` and `build.sh` to strip DWARF symbol tables and host filepaths, reducing release binaries from ~15MB to ~9.8MB (35% reduction).
39+
40+
### Changed
41+
42+
- **Leaderboard format** — now split into two sections (Token Warriors, Activity Hunters) with a Cost column. Old format was a single flat list.
43+
- **Tool registry architecture (`DataSubdir`)** — refactored tool registry path resolution (`internal/loaders/registry.go`) to use clean `DataSubdir` property mappings instead of hardcoded switch cases.
44+
- **README** — updated supported tools table, leaderboard example, build instructions (`build.sh`), and How It Works section to reflect the new data sources, metrics, and optimizations.
45+
- **`.goreleaser.yml`** — added `-trimpath` and ldflags (`-s -w`) to inject version, commit, and date into the binary while minimizing size.
46+
47+
### Fixed
48+
49+
- **Daylight Saving Time (DST) streak accuracy** — replaced 24-hour time subtraction (`24*time.Hour`) in streak logic (`internal/thermal/streak.go`) with calendar date arithmetic (`AddDate(0, 0, 1)`) to guarantee accuracy during spring-forward (23h) and fall-back (25h) transitions. Ensured strictly ascending quartile thresholds.
50+
- **Self-upgrader network and decompression guards** — hardened `thermal upgrade` (`cmd/thermal/upgrade.go`) with package-wide 30-second HTTP timeouts, context propagation across requests, exact OS/arch asset checking, and `io.LimitReader(tr, 250*1024*1024)` decompression limits against disk starvation attacks.
51+
- **Codex token over-counting (260x)** — the old parser summed ALL cumulative `total_token_usage` values from every `token_count` event in every rollout file, producing 11.6B instead of the correct 43.9M. The new loader uses `state_5.sqlite` as the source of truth and only reads the LAST `token_count` event per rollout file for the breakdown.
52+
- **command-code session inflation** — the old glob `*.jsonl` matched 115 files (54 sessions + 54 checkpoints + 7 hooks-audit), inflating counts to 61 sessions and 6,303 messages. Now correctly filters to 54 sessions and 5,614 messages.
53+
- **Agy session under-counting** — the old loader only read `transcript.jsonl` (1 of 14 sessions = 57 steps). Now reads `overview.txt` from all 14 sessions (304 steps).
54+
- **SQLite NULL handling** — Codex `state_5.sqlite` has NULL values in `model`, `reasoning_effort`, and `agent_role` columns. Switched to `sql.NullString` to avoid scan errors.
55+
56+
## [v0.1.0] - 2026-06-12
57+
58+
### Added
59+
60+
- Initial open source release.
61+
- GitHub-style contribution heatmap for AI coding tools: MiMoCode, OpenCode, Codex, Agy, command-code, codewhale.
62+
- Leaderboard mode (`thermal`) showing all installed tools ranked by activity.
63+
- Per-tool heatmap mode (`thermal --tool <name>`).
64+
- JSON output (`thermal --json`).
65+
- Configurable weeks range (`thermal --weeks 26`).
66+
- Auto-detect mode (`thermal --tool auto`).
67+
- MIT license.
68+
69+
[Unreleased]: https://github.com/jadmadi/thermal/compare/v0.1.0...HEAD
70+
[v0.1.0]: https://github.com/jadmadi/thermal/releases/tag/v0.1.0

README.md

Lines changed: 66 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@ See your coding streaks, daily activity, and usage patterns rendered as a beauti
1212

1313
| Tool | Data Source | Metrics |
1414
|------|-------------|---------|
15-
| **MiMoCode** | SQLite DB | Token usage, sessions, cost |
15+
| **Devin** | SQLite DB (sessions + message_nodes) | Token usage, sessions, cost |
1616
| **OpenCode** | SQLite DB | Token usage, sessions, cost |
17-
| **Codex** | JSONL history | Command activity |
18-
| **Devin** | SQLite DB (sessions) | Session activity |
19-
| **Agy** | Transcript JSONL | Conversation steps |
20-
| **command-code** | JSONL history | Command activity |
21-
| **codewhale** | JSON sessions | Session activity |
17+
| **MiMoCode** | SQLite DB | Token usage, sessions, cost |
18+
| **Codex** | SQLite DB (state_5.sqlite) + rollout JSONL | Token usage, sessions, model/source breakdown |
19+
| **codewhale** | JSON sessions | Token usage, sessions, cost |
20+
| **command-code** | JSONL transcripts | Message activity, sessions, model breakdown |
21+
| **Agy** | Overview logs (JSONL) | Step activity, sessions, model breakdown |
22+
23+
Tools with token data appear in the **Token Warriors** leaderboard; activity-only tools appear in **Activity Hunters**.
2224

2325
Each tool also accepts short aliases: `mimo`, `oc`, `cmd`/`cc`, `whale`.
2426

@@ -32,12 +34,40 @@ go install github.com/jadmadi/thermal/cmd/thermal@latest
3234

3335
Or download a pre-built binary from [Releases](https://github.com/jadmadi/thermal/releases).
3436

35-
Or build from source:
37+
Or build from source using the included build script:
3638

3739
```bash
3840
git clone https://github.com/jadmadi/thermal
3941
cd thermal
40-
go build -o thermal ./cmd/thermal
42+
./build.sh --release # Builds stripped production binary (~9.8MB) with embedded version tags
43+
```
44+
45+
You can run `./build.sh --help` to explore available build modes (`--release`, `--dev`, `--upx`) and cross-compilation targets. Or build manually with Go:
46+
47+
```bash
48+
CGO_ENABLED=0 go build -ldflags="-s -w" -trimpath -o thermal ./cmd/thermal
49+
```
50+
51+
## Update
52+
53+
If you installed via binary or `go install`:
54+
55+
```bash
56+
thermal upgrade
57+
```
58+
59+
This checks GitHub for a newer release, downloads the matching binary for your OS/arch, and atomically replaces the running binary.
60+
61+
If you installed via `go install`, you can also update with:
62+
63+
```bash
64+
go install github.com/jadmadi/thermal/cmd/thermal@latest
65+
```
66+
67+
Check your current version:
68+
69+
```bash
70+
thermal version
4171
```
4272

4373
## Usage
@@ -63,29 +93,34 @@ thermal --weeks 26
6393
# Output raw JSON
6494
thermal --json
6595

96+
# Enable verbose diagnostic warnings (outputs non-fatal loading errors to stderr)
97+
thermal --verbose
98+
6699
# Disable colors
67100
thermal --no-color
68101
```
69102

70103
## Example: Leaderboard
71104

72105
```
73-
THERMAL — Don't break the streak.
74-
Thursday, June 11 2026
75-
76-
# Tool Streak Best Active Activity
77-
──────────────────────────────────────────────────────────────
78-
🥇 OpenCode 4d 13d 40d 1.6B tok
79-
████████████████████ 🔥🔥
80-
🥈 command-code 2d 9d 23d 374 cmd
81-
██████████
82-
🥉 MiMoCode 2d 2d 3d 339M tok
83-
██████████
84-
Codex 0d 2d 4d 62 msg
85-
Agy 0d 1d 1d 57 step
86-
codewhale 0d 0d 0d 0 sess
87-
88-
🏆 OpenCode is on fire with a 4-day streak!
106+
THERMAL — Don't break the streak.
107+
108+
Token Warriors
109+
# Tool Strk Best Days Tokens Cost
110+
─────────────────────────────────────────────────────────────────
111+
1. Devin 38d 38d 67d 57.2B tok —
112+
2. OpenCode 2d 10d 46d 1.8B tok $234.37
113+
3. MiMoCode 1d 7d 23d 1.7B tok $419.00
114+
4. Codex 1d 2d 9d 44.0M tok —
115+
5. codewhale 1d 1d 1d 22.7K tok $0.0032
116+
117+
Activity Hunters
118+
# Tool Strk Best Days Activity
119+
───────────────────────────────────────────────────────
120+
1. command-code 1d 9d 28d 5.6K msg
121+
2. Agy 1d 1d 2d 304 step
122+
123+
>> Devin is on fire with a 38-day streak!
89124
90125
Keep the heat going. Don't break the streak.
91126
```
@@ -112,13 +147,14 @@ thermal --no-color
112147

113148
Thermal reads usage data from installed AI coding tools:
114149

115-
- **MiMoCode / OpenCode**: Queries SQLite databases for assistant message token usage
116-
- **Devin**: Queries the Devin CLI sessions SQLite database for session activity
117-
- **Codex / command-code**: Parses JSONL command history for activity timestamps
118-
- **Agy**: Reads transcript JSONL files from conversation logs
119-
- **codewhale**: Reads JSON session files
150+
- **Devin**: Queries the Devin CLI SQLite database, joining `message_nodes` (assistant `metadata.metrics` for real input/output/cache token counts) against `sessions` (duration, count) and `prompt_history` (engagement)
151+
- **OpenCode / MiMoCode**: Queries SQLite databases for pre-aggregated token usage, cost, and code diff stats
152+
- **Codex**: Reads `state_5.sqlite` (`threads.tokens_used`, model, source, reasoning_effort) as the primary source, supplements with rollout JSONL for the input/output/reasoning/cache token breakdown
153+
- **codewhale**: Reads JSON session files for `metadata.total_tokens`, `metadata.cost.session_cost_usd`, model, and mode
154+
- **command-code**: Parses JSONL session transcripts for message activity and model distribution (from `.meta.json` sidecars)
155+
- **Agy**: Reads `overview.txt` logs from all brain sessions for step activity, supplements with `transcript.jsonl` for model info
120156

121-
Databases are opened **read-only** Thermal never modifies your data.
157+
All SQLite databases are opened **read-only** (`?mode=ro`) with memory-mapped I/O (`PRAGMA mmap_size`) and incremental delta-caching. Multi-file directory and JSONL scanners (`Agy`, `command-code`, `codex`) run concurrently via bounded parallel worker pools. Thermal never modifies your data and processes multi-gigabyte historical databases in milliseconds.
122158

123159
## Requirements
124160

0 commit comments

Comments
 (0)