Skip to content

Commit cd8abf2

Browse files
committed
Add multi-agent source support
1 parent fce967a commit cd8abf2

23 files changed

Lines changed: 970 additions & 166 deletions

README.md

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@
66

77
![Status: MVP](https://img.shields.io/badge/status-MVP-f2c94c)
88
![Local first](https://img.shields.io/badge/local--first-yes-2f855a)
9-
![Platform: Windows first](https://img.shields.io/badge/platform-Windows%20first-0078d4)
9+
![Platform: Cross-platform](https://img.shields.io/badge/platform-cross--platform-0078d4)
1010
![Backend: Go](https://img.shields.io/badge/backend-Go-00ADD8)
1111
![Frontend: Vue 3](https://img.shields.io/badge/frontend-Vue%203-42b883)
1212
![License: Apache-2.0](https://img.shields.io/badge/license-Apache--2.0-blue)
1313

14-
AgentMeter is a local-first dashboard for understanding Codex session usage:
14+
AgentMeter is a local-first dashboard for understanding coding-agent session usage:
1515
tokens, estimated cost, timing, session history, and tool-call behavior.
1616

17-
It reads local Codex session files, indexes them into SQLite, and shows the data
17+
It reads local agent JSONL session files, indexes them into SQLite, and shows the data
1818
in a private desktop UI. No proxy, no cloud service, no telemetry.
1919

2020
## Why AgentMeter
2121

2222
Coding agents can generate a lot of useful local session data, but that data is
23-
hard to inspect directly. AgentMeter turns Codex JSONL sessions into answers you
23+
hard to inspect directly. AgentMeter turns local JSONL sessions into answers you
2424
can actually use:
2525

2626
- How many sessions did I run?
@@ -33,6 +33,8 @@ can actually use:
3333
## Features
3434

3535
- Overview dashboard with sessions, tokens, estimated cost, daily usage, and model usage.
36+
- Multiple local source roots, with Codex, Claude Code, and generic JSONL detection.
37+
- Agent-level usage grouping for developers who run several coding agents side by side.
3638
- Searchable session history with parse status and raw source traceability.
3739
- Session detail timeline with model calls, tool calls, metadata, and source paths.
3840
- Tool-call analytics with call counts, success/failure counts, and durations.
@@ -50,16 +52,19 @@ AgentMeter is designed to stay local:
5052
- Does not require a cloud account.
5153
- Stores normalized data in a local SQLite database.
5254

53-
The default database path is:
55+
The default database path follows the host OS:
5456

5557
```text
56-
%LOCALAPPDATA%\AgentMeter\agentmeter.sqlite
58+
Windows: %LOCALAPPDATA%\AgentMeter\agentmeter.sqlite
59+
macOS: ~/Library/Application Support/AgentMeter/agentmeter.sqlite
60+
Linux: $XDG_DATA_HOME/AgentMeter/agentmeter.sqlite or ~/.local/share/AgentMeter/agentmeter.sqlite
5761
```
5862

59-
The default Codex source path is:
63+
Default source roots are detected from local agent homes when they exist:
6064

6165
```text
62-
%USERPROFILE%\.codex
66+
~/.codex
67+
~/.claude
6368
```
6469

6570
## Quick Start
@@ -83,9 +88,9 @@ source files change, starts AgentMeter, and opens:
8388
http://127.0.0.1:34115
8489
```
8590

86-
On first launch, click **Index Now** in the app. AgentMeter defaults to
87-
`%USERPROFILE%\.codex`, so no source path setup is required unless your Codex
88-
sessions live somewhere else.
91+
On first launch, click **Index Now** in the app. AgentMeter defaults to detected
92+
local agent homes such as `~/.codex` and `~/.claude`. In **Settings**, enter one
93+
source root per line when you use multiple agents or keep session logs elsewhere.
8994

9095
Build the frontend and start local HTTP mode manually:
9196

@@ -114,21 +119,22 @@ wails dev
114119
## How It Works
115120

116121
```text
117-
Codex JSONL -> scanner/parser -> SQLite -> Go query service -> Vue dashboard
122+
Agent JSONL -> scanner/parser -> SQLite -> Go query service -> Vue dashboard
118123
```
119124

120125
When the source path is a Codex home directory, AgentMeter scans `sessions\`
121126
first and then `archived_sessions\`, keeping the active copy when both contain
122-
the same relative JSONL path. A direct directory of saved JSONL output is also
123-
supported.
127+
the same relative JSONL path. When the source path is a Claude Code home,
128+
AgentMeter scans `projects/`. A direct directory of saved JSONL output is also
129+
supported through the generic JSONL adapter.
124130

125131
## Current Status
126132

127-
AgentMeter is currently an MVP focused on Codex on Windows. The repository
133+
AgentMeter is currently an MVP for local coding-agent JSONL usage. The repository
128134
already includes:
129135

130136
- Go backend with SQLite migrations and local app configuration.
131-
- Codex JSONL discovery, parsing, normalization, and incremental indexing.
137+
- Codex, Claude Code, and generic JSONL discovery, parsing, normalization, and incremental indexing.
132138
- Normalized sessions, events, token usage, model calls, and tool calls.
133139
- Vue 3 + TypeScript frontend using Ant Design Vue and ECharts.
134140
- MVP screens for Overview, Sessions, Session Detail, Tools, and Settings.
@@ -146,8 +152,7 @@ go test ./...
146152

147153
## Roadmap
148154

149-
Planned directions include packaged Windows builds, macOS/Linux support, more
150-
coding-agent adapters, export formats, project grouping, custom pricing, and
155+
Planned directions include packaged builds, more coding-agent adapters, export formats, project grouping, custom pricing, and
151156
richer timeline views.
152157

153158
See [Roadmap](docs/roadmap.md) for details.
@@ -163,4 +168,4 @@ See [Roadmap](docs/roadmap.md) for details.
163168
## Contributing
164169

165170
Issues and pull requests are welcome, especially for parser edge cases, pricing
166-
updates, Windows packaging, and adapters for other coding agents.
171+
updates, packaging, and adapters for other coding agents.

docs/architecture.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ AgentMeter
3636
3737
backend
3838
source discovery
39-
Codex parser
39+
agent source adapters
40+
JSONL parser
4041
ingestion pipeline
4142
SQLite repository
4243
pricing service
@@ -52,7 +53,7 @@ AgentMeter
5253
## Data Flow
5354

5455
```text
55-
discover Codex path
56+
discover configured agent source roots
5657
-> scan session JSONL files
5758
-> parse raw events
5859
-> normalize to internal event model
@@ -67,7 +68,8 @@ Proposed Go layout:
6768
```text
6869
internal/
6970
app/
70-
codex/
71+
agent/
72+
sessionjsonl/
7173
db/
7274
ingest/
7375
model/
@@ -79,14 +81,15 @@ internal/
7981

8082
Responsibilities:
8183

82-
- `codex`: understand Codex JSONL shape and convert it to normalized records.
84+
- `agent`: detect source roots such as Codex, Claude Code, or generic JSONL directories.
85+
- `sessionjsonl`: understand supported JSONL event shapes and convert them to normalized records.
8386
- `ingest`: scan, hash, deduplicate, and index files.
8487
- `db`: SQLite connection, migrations, repositories.
8588
- `model`: normalized domain structs.
8689
- `pricing`: model aliases, pricing table, cost calculation.
8790
- `query`: read models for UI screens.
8891
- `export`: JSON and CSV export.
89-
- `platform`: Windows path discovery and future platform-specific logic.
92+
- `platform`: OS-specific database and default source path discovery.
9093

9194
## UI Shape
9295

@@ -120,7 +123,7 @@ Session Detail should show:
120123

121124
## Runtime Rules
122125

123-
- AgentMeter must not modify Codex session files.
126+
- AgentMeter must not modify source session files.
124127
- AgentMeter must not upload data.
125128
- UI should bind to local desktop runtime, not a public interface.
126129
- Indexing should be incremental.

docs/data-model.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Data Model
22

3-
The database stores normalized records derived from Codex session JSONL. Raw
3+
The database stores normalized records derived from local coding-agent JSONL. Raw
44
source files remain the source of truth.
55

66
## Core Entities
@@ -12,7 +12,7 @@ Tracks configured local data sources.
1212
Fields:
1313

1414
- `id`
15-
- `kind` such as `codex`
15+
- `kind` such as `codex`, `claude`, or `jsonl`
1616
- `name`
1717
- `root_path`
1818
- `sessions_path`
@@ -38,13 +38,14 @@ Fields:
3838

3939
### sessions
4040

41-
One Codex session.
41+
One normalized agent session.
4242

4343
Fields:
4444

4545
- `id`
4646
- `source_id`
4747
- `source_file_id`
48+
- `session_key`
4849
- `codex_session_id`
4950
- `project_path`
5051
- `model`
@@ -63,6 +64,9 @@ Fields:
6364
- `event_count`
6465
- `parse_status`
6566

67+
`session_key` is the generic identity shown in the UI. `codex_session_id` is
68+
kept for backward compatibility with older databases and API clients.
69+
6670
### events
6771

6872
Normalized timeline events.

docs/project-brief.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
## One-line Description
44

5-
AgentMeter is an open-source, cross-platform-ready local dashboard for measuring
6-
coding agent session usage, starting with Codex on Windows.
5+
AgentMeter is an open-source, cross-platform local dashboard for measuring
6+
coding agent session usage from local JSONL session files.
77

88
## Problem
99

@@ -21,9 +21,12 @@ AgentMeter focuses on that gap:
2121

2222
## Initial Scope
2323

24-
The first version supports:
24+
The current version supports:
2525

26-
- Codex local sessions on Windows;
26+
- Codex local sessions;
27+
- Claude Code local sessions;
28+
- generic JSONL session directories;
29+
- multiple configured source roots for users running several coding agents;
2730
- token usage from local session data;
2831
- session duration from local JSONL timestamps;
2932
- tool-call statistics from local session events;
@@ -32,7 +35,6 @@ The first version supports:
3235

3336
## Non-goals For MVP
3437

35-
- Multi-agent support beyond Codex.
3638
- Proxy or gateway mode.
3739
- Cloud sync.
3840
- Team dashboards.
@@ -43,7 +45,7 @@ The first version supports:
4345

4446
## User
4547

46-
The first user is a developer who uses Codex locally and wants to understand:
48+
The first user is a developer who uses local coding agents and wants to understand:
4749

4850
- token burn;
4951
- estimated cost;
@@ -55,7 +57,7 @@ The first user is a developer who uses Codex locally and wants to understand:
5557

5658
## Product Principles
5759

58-
- Read-only against Codex data.
60+
- Read-only against source session data.
5961
- Prefer actual usage data over estimation.
6062
- Clearly label unknown, missing, and estimated values.
6163
- Keep data local unless the user explicitly exports it.
@@ -64,8 +66,8 @@ The first user is a developer who uses Codex locally and wants to understand:
6466

6567
## First Usable Version
6668

67-
The first useful build should let a user open AgentMeter, point it at a Codex
68-
data directory if needed, index sessions, and inspect:
69+
The first useful build should let a user open AgentMeter, point it at one or
70+
more local agent data directories if needed, index sessions, and inspect:
6971

7072
- overview totals;
7173
- daily usage;

docs/roadmap.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
## Phase 0: Discovery
44

5-
Goal: understand Codex session data well enough to design the parser safely.
5+
Goal: understand local coding-agent session data well enough to design the parser safely.
66

77
Tasks:
88

9-
- Locate Codex session directories on Windows.
9+
- Locate Codex and Claude Code session directories across supported OSes.
1010
- Collect representative local JSONL samples.
1111
- Document event types found in real sessions.
1212
- Identify where token usage appears.
@@ -32,23 +32,23 @@ Tasks:
3232
- Add SQLite dependency.
3333
- Add migration runner.
3434
- Add app configuration storage.
35-
- Add Windows Codex path discovery.
35+
- Add cross-platform database and default source path discovery.
3636

3737
Deliverables:
3838

3939
- runnable Wails app;
4040
- empty shell UI;
4141
- local SQLite database creation.
4242

43-
## Phase 2: Codex Indexer
43+
## Phase 2: Agent Indexer
4444

45-
Goal: index Codex sessions into SQLite.
45+
Goal: index local coding-agent sessions into SQLite.
4646

4747
Tasks:
4848

4949
- Implement source discovery.
5050
- Implement JSONL scanner.
51-
- Implement Codex parser.
51+
- Implement Codex, Claude Code, and generic JSONL parsing.
5252
- Normalize sessions, events, token usage, and tool calls.
5353
- Add incremental indexing based on path, size, modified time, and hash.
5454
- Add parse warnings.
@@ -82,15 +82,17 @@ Tasks:
8282

8383
Deliverables:
8484

85-
- usable local dashboard for Codex sessions.
85+
- usable local dashboard for local coding-agent sessions.
8686

8787
## Phase 4: Packaging
8888

89-
Goal: make Windows usage easy.
89+
Goal: make cross-platform usage easy.
9090

9191
Tasks:
9292

9393
- Windows app build.
94+
- macOS app build.
95+
- Linux app build.
9496
- Installer or portable zip.
9597
- Local database path decision.
9698
- Log file location.
@@ -104,8 +106,7 @@ Deliverables:
104106

105107
Possible additions:
106108

107-
- macOS and Linux support.
108-
- Claude Code adapter.
109+
- More complete Claude Code adapter coverage.
109110
- Gemini CLI adapter.
110111
- OpenCode adapter.
111112
- CSV export.

frontend/src/App.vue

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,14 @@ const settings = ref<Settings | null>(null)
1919
const indexing = ref(false)
2020
const refreshKey = ref(0)
2121
22-
const hasSource = computed(() => Boolean(settings.value?.sourcePath))
23-
const sourceStatusLabel = computed(() => (hasSource.value ? 'Source ready' : 'Source missing'))
24-
const sourcePathDisplay = computed(() => settings.value?.sourcePath || 'Configure a local JSONL source in Settings')
22+
const hasSource = computed(() => Boolean(settings.value?.sourcePaths?.length || settings.value?.sourcePath))
23+
const sourceStatusLabel = computed(() => (hasSource.value ? 'Sources ready' : 'Sources missing'))
24+
const sourcePathDisplay = computed(() => settings.value?.sourcePath || 'Configure local JSONL sources in Settings')
25+
const sourceSummary = computed(() => {
26+
const count = settings.value?.sourcePaths?.length || 0
27+
if (count > 1) return `${count} local sources`
28+
return sourcePathDisplay.value
29+
})
2530
2631
const selectedKeys = computed(() => {
2732
if (route.path.startsWith('/sessions')) return ['sessions']
@@ -99,7 +104,7 @@ onBeforeUnmount(() => {
99104
</div>
100105
<div class="brand-copy">
101106
<div class="brand-title">AgentMeter</div>
102-
<div class="brand-subtitle">Local Codex usage</div>
107+
<div class="brand-subtitle">Local agent usage</div>
103108
</div>
104109
</div>
105110
<div class="nav-section-label">Inspect</div>
@@ -120,9 +125,9 @@ onBeforeUnmount(() => {
120125
<span class="source-dot"></span>
121126
<span>{{ sourceStatusLabel }}</span>
122127
</div>
123-
<span class="source-label">Local source</span>
128+
<span class="source-label">Local sources</span>
124129
<a-typography-text class="source-path" :ellipsis="{ tooltip: sourcePathDisplay }">
125-
{{ sourcePathDisplay }}
130+
{{ sourceSummary }}
126131
</a-typography-text>
127132
</div>
128133
<div class="header-actions">

0 commit comments

Comments
 (0)