Skip to content

Repository files navigation

QuickCall OpenTrace

Multi-CLI AI coding session tracer. Normalize, store, and browse sessions from Claude Code, Codex CLI, Gemini CLI, Cursor, and pi.dev — in one PostgreSQL database with a web UI.

Session Browser

Session Browser — Search, filter, and inspect messages

Parallel Session View

Parallel Session View — Side-by-side comparison

Supported CLIs

CLIData sourceNotes
Claude Code~/.claude/projects/**/*.jsonlFull message + tool history
Codex CLI~/.codex/sessions/*/*/*/rollout-*.jsonlToken usage, tool calls
Gemini CLI~/.gemini/tmp/*/chats/session-*.jsonShell commands, file edits
Cursor~/.cursor/projects/*/agent-transcripts/*.txt + state.vscdbAgent transcripts, composer data
pi.dev~/.pi/agent/sessions/**/*.jsonlKimi model, thinking blocks

Quick Start

Full stack (with web UI)

git clone https://github.com/quickcall-dev/opentrace.git
cd opentrace
docker compose up -d
open http://localhost:3000

Backend only (PyPI)

pip install quickcall-opentrace
export QUICKCALL_OPENTRACE_DSN="postgresql://user:pass@localhost:5432/quickcall"
quickcall init
quickcall-server # :19777
quickcall-daemon # file watcher

The frontend is Docker-only. The PyPI package provides server + daemon CLIs only.

Run quickcall doctor to verify your setup.

See Bring Your Own Postgres for BYOP setup, multiple machines, and background mode.

Architecture

Full architecture and schema decisions: docs/architecture/README.md

flowchart LR
subgraph Host
A[Claude Code] --> D
B[Codex CLI] --> D
C1[Cursor] --> D
C2[pi.dev] --> D
C3[Gemini CLI] --> D
end
D["Daemon\n(file watcher + normalizer)"] --> |"HTTP batches"| S["Ingest Server\n:19777"]
S --> |"COPY writes"| P[(PostgreSQL)]
P --> |"API queries"| F["Frontend\nNext.js 15 :3000"]
Loading
  1. Daemon watches ~/.claude, ~/.codex, ~/.gemini, ~/.cursor, ~/.pi
  2. Collector normalizes each CLI format to NormalizedMessage
  3. Pusher batches messages to the ingest server
  4. Server validates, deduplicates, writes via COPY
  5. Frontend renders sessions with gantt, messages, minimap

Installation

MethodCommandIncludes UI
Docker (recommended)git clone ... && docker compose up -dYes
Sourceuv sync --extra devYes (run frontend separately)
PyPIpip install quickcall-opentraceNo

Configuration

All variables use the QUICKCALL_OPENTRACE_ prefix.

VariableUsed byDefaultDescription
DSNserverpostgresql://quickcall:quickcall@db:5432/quickcallPostgres connection string
HOSTserver0.0.0.0Bind interface
ADMIN_KEYSserveradmin_devComma-separated admin API keys
PUSH_KEYSserverpush_devComma-separated ingest API keys
INGEST_URLdaemonhttp://localhost:19777/ingestPush endpoint
API_KEYdaemonAPI key for pushes

See .env.example for a complete reference.

API Endpoints

MethodPathAuthDescription
GET/healthHealth check
POST/ingestPushSubmit normalized messages
GET/api/sessionsAdminList sessions
GET/api/messagesAdminMessages for a session
GET/api/statsAdminAggregate stats
GET/api/syncAdminFile sync state

Development

# Setup
uv sync --extra dev
# Start dependencies
docker compose up -d db
# Terminal 1 — Server
uv run python -m opentrace.server
# Terminal 2 — Daemon
uv run python -m opentrace.daemon
# Terminal 3 — Frontendcd frontend && npm install && npm run dev
# Tests
uv run pytest
# Lint
uv run ruff check opentrace/ tests/
uv run ruff format opentrace/ tests/
# Rebuild Docker
docker compose up -d --build server daemon
docker compose up -d --build frontend
# Pre-push validation
./scripts/e2e-pypi-smoke-test.sh
./scripts/e2e-docker-smoke-test.sh

Git hooks

git config core.hooksPath .githooks

Commits must follow conventional format (fix:, feat:, etc.) and include a Why: section with 2+ bullets.

Wipe and re-ingest

PGPASSWORD=quickcall psql -h localhost -p 15433 -U quickcall -d quickcall -c \
"TRUNCATE TABLE tool_calls, tool_results, token_usage, messages, file_progress, sessions, schema_version RESTART IDENTITY CASCADE; INSERT INTO schema_version (version) VALUES (1);"
rm ~/.quickcall-opentrace/state.json ~/.quickcall-opentrace/backfilled_sessions.json 2>/dev/null
docker compose restart daemon

Adding a new CLI source

  1. Schema — Add transform in opentrace/schemas/<source>/transform.py
  2. Collector — Add _collect_<source> in opentrace/daemon/collector.py
  3. Tests — Add fixtures in tests/fixtures/ and tests in tests/schemas/, tests/daemon/
  4. Watcher — Add glob pattern in opentrace/daemon/config.py if needed

Documentation

DocWhat's inside
ArchitectureSchema decisions, data flow, component design
BYOP GuideOwn Postgres, multiple machines, background mode
Dev EnvironmentFull local setup, IDE config, troubleshooting
PublishingPyPI release checklist and version bumping
Guide IndexAll user and contributor guides

License

Apache 2.0 — see LICENSE.

About

Multi-CLI AI coding session tracer. Normalize, store, and browse sessions from Claude Code, Codex CLI, Gemini CLI, Cursor, and pi.dev.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages