Observability for Claude Code agentic runs — live TUI dashboard for Claude Code sessions
Project description
Aegon
Observability for Claude Code agentic runs.
Watches the JSONL session files Claude Code writes during a run, parses them into typed Rust structs, tracks live session state, and displays everything in a split terminal UI — a raw event feed on the left and an aggregated dashboard on the right.
Demo
https://github.com/user-attachments/assets/a34fd65b-3872-40b2-a0a4-ef012dcf0c0a
What it looks like
┌─ Aegon 1 session 247 events ──────────────────────────────────────────────────────────┐
│ │
│ Events (newest first) │ Session │
│ ───────────────────── │ Live session ● LIVE 247 events │
│ 14:22:01 TOOL▶ Bash cargo… │ ───────────────────────────────────────────────────── │
│ 14:22:00 THINK I should… │ Tokens ████████████░░░░░░░░░░ 42k / 200k │
│ 14:21:59 ASST Let me run… │ in=38420 out=3801 cache_r=71204 │
│ 14:21:55 TOOL◀ Finished `d… │ est. cost: $0.0321 │
│ 14:21:54 TOOL▶ Read src/… │ ───────────────────────────────────────────────────── │
│ 14:21:54 TOOL▶ Bash ls -la… │ Steps │
│ 14:21:53 ASST I'll check… │ ⠋ Bash [1.2s] │
│ 14:21:52 USER lets start… │ ✓ Read 312ms │
│ │ ✓ Write 89ms │
│ │ ───────────────────────────────────────────────────── │
│ │ Flow │
│ │ USER → THINK → [Bash ‖ Read] → ASST → Write → ASST │
│ q quit │ │
└─────────────────────────────────────────────────────────────────────────────────────────────┘
Left panel — raw event feed: every tool call, result, thinking block, and assistant message in arrival order, coloured by type, newest first.
Right panel — live dashboard:
- Session header: title, live/idle status, event count
- Token gauge: progress bar auto-filling as the context window fills; estimated cost
- Steps: spinner on active tool calls, ✓/✗ for completed/failed, with timing
- Flow: one-line causal chain showing order, parallel branches (
[Bash ‖ Read]), and human turns
Architecture
~/.claude/projects/**/*.jsonl
│
│ notify (OS file events: FSEvents / inotify)
▼
aegon-cli / watcher.rs
┌─ background thread ──────────────────────────────────┐
│ seek to last-read byte → read new lines │
│ ClaudeAdapter::parse_line() → Vec<LogEvent> │
│ tx.send(event) │
└──────────────────────────────────────────────────────┘
│ mpsc channel
▼
aegon-cli / main.rs (main thread)
App::push(event)
├─► events: Vec<LogEvent> raw feed buffer (500 events)
└─► SessionRegistry::ingest()
└─► SessionState::ingest()
├─ pending: HashMap<id, Step> running tool calls
├─ steps: Vec<Step> completed with timing
├─ flow: Vec<FlowNode> causal chain
└─ token_totals: TokenTotals cumulative usage
aegon-ui / tui.rs draws every 50ms:
left → raw event list
right → dashboard::draw(SessionState)
├─ gauge::draw() token progress bar + cost
├─ steps::draw() spinners + completed steps
└─ flow::draw() USER → THINK → [T1 ‖ T2] → ASST
Crate map
| Crate | Role |
|---|---|
aegon-types |
All domain types — LogEvent, EventKind, ToolCall, ToolResult, TokenUsage, Session, StreamId |
aegon-adapters |
Claude JSONL → Vec<LogEvent>; lenient on unknown fields |
aegon-core |
Pure session logic — SessionState, SessionRegistry, Step, FlowNode, TokenTotals |
aegon-ui |
ratatui TUI — split event feed + dashboard |
aegon-cli |
Binary entry point — file watcher + channel wiring |
Running
Quickest start — opens in a new Terminal window:
just demo
In your current terminal:
just run # build + launch in one step
just watch # alias for run
Manual:
cargo build --workspace
./target/debug/aegon
Press q or Esc to quit.
The watcher automatically picks up ~/.claude/projects/**/*.jsonl and
~/.claude/sessions/**/*.jsonl. Start a Claude Code session in another
terminal — events appear in real time.
First time setup (installs system deps and Cargo tools):
just setup
Development
just --list # all available recipes
just ci # mirrors what CI runs (fmt + clippy + check + test + docs)
just build # cargo build --workspace
just test # cargo test --workspace
just audit-jsonl # scan ~/.claude/projects for JSONL structure insights
just demo # run the tool in a separate terminal for live demo
See CLAUDE.md for full design constraints, crate responsibilities, and the development workflow.
See CHANGELOG.md for release history and JOURNAL.md for design decisions and session notes.
Contributing
Workflow
All changes go through a branch → PR → squash-merge cycle. The full
loop is documented in CLAUDE.md and enforced by skills in
.claude/skills/. In short:
just branch feat/<name> # cut a branch from latest main
# ... make changes ...
just ci # must pass locally before pushing
just push # push and set upstream
just pr # open PR (gh will prompt for title + body)
just merge # squash-merge once CI is green
just cleanup feat/<name> # delete local branch + prune remote refs
Rules
- Never commit to
maindirectly. Every change goes through a PR. just cimust pass before pushing. It runsfmt,clippy -D warnings,check,test, andcargo doc -D warnings— exactly what CI runs.- Every public item needs a doc comment.
cargo doc -D warningsis an error, not a warning. - CHANGELOG.md and JOURNAL.md must be updated on every PR that changes
behaviour.
[Unreleased]in CHANGELOG for unreleased changes; add a dated JOURNAL entry with achievements, caveats, and next steps. - No
unwrap()orexpect()in library crates outside tests. - Adapters must not use
#[serde(deny_unknown_fields)]on top-level event types — the Claude JSONL format evolves without notice.
Adding a new tool adapter
- Create
crates/aegon-adapters/src/<tool>/mod.rsandraw.rs - Implement the
Adaptertrait fromcrates/aegon-adapters/src/lib.rs - Add fixture JSONL samples to
aegon-tests/fixtures/<tool>/ - Wire into
aegon-clivia config or format detection
Codeowners
@chinmaypandya is the default owner for all files. All PRs require
approval before merge.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file aegon_rs-0.1.0.tar.gz.
File metadata
- Download URL: aegon_rs-0.1.0.tar.gz
- Upload date:
- Size: 40.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.9.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
202c0bef91c198063afacafbaf68a6cf18a639f4dd035a98ba3825be4da6eb2d
|
|
| MD5 |
d10627d26a35bfe08e9c944e4b16184d
|
|
| BLAKE2b-256 |
0a18ea21540f1f08c6be6748cc13aebd5a9d47cd5a2fa2ea4321fd523ea55e87
|
File details
Details for the file aegon_rs-0.1.0-py3-none-win_amd64.whl.
File metadata
- Download URL: aegon_rs-0.1.0-py3-none-win_amd64.whl
- Upload date:
- Size: 809.2 kB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34fe6941a1bb88be03ec62d6a63281e9270d053db6fb5546b260109fae06a5c2
|
|
| MD5 |
505d784731f5c41b7d290b283e552dc5
|
|
| BLAKE2b-256 |
f8042c64b8b4ab95ef6914739154a464ce1b966e77a0a65e5667d128feb5bc59
|
File details
Details for the file aegon_rs-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: aegon_rs-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 979.2 kB
- Tags: Python 3, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a68e5b7d897c0f3014809619a9c0e517df035d21b4c2a4a00989eb6e9ce6ddb3
|
|
| MD5 |
1efde606560e51a420a2fa1712c5074d
|
|
| BLAKE2b-256 |
2dd54f9ef3d0c31da71e79fca833a9c6efe5b77bd9b9f3849ab9dd7ed5bc09c2
|
File details
Details for the file aegon_rs-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: aegon_rs-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 921.3 kB
- Tags: Python 3, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c8f2cb32c3140b8f1f2f69cb297af1cd422d317547550c712d7bdbbc126d40c
|
|
| MD5 |
c0bbe647a4242138fbb45a033a25eb92
|
|
| BLAKE2b-256 |
8a5347d387ed223a14a6f8959fcfdb22a49930c6c7be23947e0feed3bafda8b0
|
File details
Details for the file aegon_rs-0.1.0-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: aegon_rs-0.1.0-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 825.0 kB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.9.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c09bdea0b21fbcdcf0917f46ac9c3d6164b4edd8d857004a1e1b1fb33a2a295f
|
|
| MD5 |
e06e530bfd1df33aea6b6022290584ac
|
|
| BLAKE2b-256 |
00b48d743e2bc6b925371b9d203eabc0a74545833c06d2a2118f6819b28196b0
|
File details
Details for the file aegon_rs-0.1.0-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.
File metadata
- Download URL: aegon_rs-0.1.0-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
- Upload date:
- Size: 1.7 MB
- Tags: Python 3, macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
73fb2cb1874fe6df24bbf0dd33c16dba6c8d2250add753045bc7ea8e054a88dd
|
|
| MD5 |
9b8f2d1046a7f54c3433c4e1c78abadb
|
|
| BLAKE2b-256 |
96f923beaffdae15c9ddbe72d341a7fc03b25ea993dcdaabd9c112dbc8686922
|