Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ htmlcov/

# Project-specific
*.db
.claude/
109 changes: 82 additions & 27 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,114 @@
# CLAUDE.md

Queryable analytics for Claude Code session logs, exposed as an MCP server.
Queryable analytics for Claude Code session logs, exposed as an MCP server and CLI.

## Project Overview

This MCP server replaces the bash script `~/.claude/contrib/parse-session-logs.sh` with a persistent, queryable analytics layer. It parses JSONL session logs from `~/.claude/projects/` and provides:

- **User-centric timeline**: Events across conversations, organized by timestamp
- **Rich querying**: Tool frequency, command breakdown, sequences, permission gaps
- **Persistent storage**: SQLite at `~/.claude/contrib/analytics/data.db`
- **Auto-refresh**: Queries automatically refresh stale data (>5 min old)
- **CLI access**: Full CLI for shell scripts and hooks
- **Tool frequency analysis**: Which tools you use most (Read, Edit, Bash, etc.)
- **Command breakdown**: Bash command patterns (git, make, cargo, etc.)
- **Workflow sequences**: Common tool chains like Read → Edit → Bash
- **Permission gap detection**: Commands that should be added to settings.json
- **Token usage tracking**: Usage by day, session, or model
- **Session timeline**: Events across conversations, organized by timestamp

## Architecture

Follows the `claude-event-bus` pattern:
- FastMCP for MCP server implementation
- SQLite for persistence
- LaunchAgent for always-on availability
- CLI wrapper for shell access
```
~/.claude/projects/**/*.jsonl → SQLite DB → MCP Server / CLI
~/.claude/contrib/analytics/data.db
```

Key components:
- **FastMCP** for MCP server implementation
- **SQLite** for persistent storage with incremental ingestion
- **Auto-refresh** queries automatically refresh stale data (>5 min old)
- **LaunchAgent** for always-on availability (macOS)

## Commands

```bash
make check # Run fmt, lint, test
make check # Run fmt, lint, test (84 tests)
make install # Install LaunchAgent + CLI
make uninstall # Remove LaunchAgent + CLI
make dev # Run in dev mode with auto-reload
```

## Key Files

- `src/session_analytics/server.py` - MCP tools + entry point
- `src/session_analytics/storage.py` - SQLite backend
- `src/session_analytics/ingest.py` - JSONL parsing
- `src/session_analytics/queries.py` - Query implementations
- `src/session_analytics/patterns.py` - Pattern detection
| File | Purpose |
|------|---------|
| `src/session_analytics/server.py` | MCP tools + HTTP server entry point |
| `src/session_analytics/cli.py` | CLI with formatter registry for output |
| `src/session_analytics/storage.py` | SQLite backend with migration support |
| `src/session_analytics/ingest.py` | JSONL parsing with incremental updates |
| `src/session_analytics/queries.py` | Query implementations with `build_where_clause()` helper |
| `src/session_analytics/patterns.py` | Pattern detection (sequences, permission gaps) |

## Architecture Patterns

- **Public API**: Use `storage.execute_query()` / `execute_write()` for raw SQL; avoid `_connect()`
- **Formatter Registry**: CLI uses `@_register_formatter(predicate)` decorator pattern
- **Schema Migrations**: Use `@migration(version, name)` decorator in storage.py for DB changes
- **Module Imports**: server.py uses `from session_analytics import queries, patterns, ingest`

## MCP Tools

| Tool | Purpose |
|------|---------|
| `get_status` | Database stats and last ingestion time |
| `ingest_logs` | Refresh data from JSONL files |
| `query_timeline` | Events in time window |
| `query_tool_frequency` | Tool usage counts |
| `query_commands` | Bash command breakdown |
| `query_sequences` | Common tool patterns |
| `query_permission_gaps` | Commands needing settings.json |
| `query_sessions` | Session metadata |
| `query_tokens` | Token usage analysis |
| `query_tool_frequency` | Tool usage counts (Read, Edit, Bash, etc.) |
| `query_timeline` | Events in time window with filtering |
| `query_commands` | Bash command breakdown with prefix filter |
| `query_sessions` | Session metadata and token totals |
| `query_tokens` | Token usage by day, session, or model |
| `query_sequences` | Common tool patterns (n-grams) |
| `query_permission_gaps` | Commands needing settings.json entries |
| `get_insights` | Pre-computed patterns for /improve-workflow |
| `get_status` | Ingestion status + DB stats |

## CLI Commands

All commands support `--json` for machine-readable output:

```bash
session-analytics-cli status # DB stats
session-analytics-cli ingest --days 30 # Refresh data
session-analytics-cli frequency # Tool usage
session-analytics-cli commands --prefix git # Command breakdown
session-analytics-cli sessions # Session info
session-analytics-cli tokens --by model # Token usage
session-analytics-cli sequences # Tool chains
session-analytics-cli permissions # Permission gaps
session-analytics-cli insights # For /improve-workflow
```

## Integration

### With /improve-workflow

The `get_insights` tool (or `session-analytics-cli insights`) provides pre-computed patterns:
- Tool frequency for identifying high-value automations
- Command frequency for settings.json additions
- Tool sequences for workflow optimization
- Permission gaps with ready-to-use suggestions

### With session-start hook

Can be used to auto-ingest on session start:
```bash
session-analytics-cli ingest --days 1 --json 2>/dev/null || true
```

## Data Model

**Events table**: Individual tool uses with timestamps, tokens, commands
**Sessions table**: Aggregated session metadata
**Patterns table**: Pre-computed patterns for fast querying
**Ingested files table**: Tracks file mtime/size for incremental updates

## Reference

Full implementation plan: `~/.claude/plans/precious-crunching-crescent.md`

Reference implementation: `~/Documents/projects/claude-event-bus/`
73 changes: 73 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
.PHONY: check fmt lint test clean install uninstall dev venv

# Run all quality gates (format check, lint, tests)
check: fmt lint test

# Check/fix formatting with ruff
fmt:
ruff format --check .

# Run linter with ruff
lint:
ruff check .

# Run tests
test:
pytest tests/ -v

# Clean build artifacts
clean:
rm -rf build/ dist/ *.egg-info .pytest_cache .ruff_cache
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true

# Create virtual environment (requires Python 3.10+)
venv:
@if [ ! -d .venv ]; then \
echo "Creating virtual environment..."; \
PYTHON=$$(command -v python3.12 || command -v python3.11 || command -v python3.10 || echo "python3"); \
$$PYTHON -m venv .venv && .venv/bin/pip install --upgrade pip; \
fi

# Install with dev dependencies (for development)
dev: venv
.venv/bin/pip install -e ".[dev]"

# Full installation: venv + deps + LaunchAgent + CLI + MCP
install: venv
@echo "Installing dependencies..."
.venv/bin/pip install -e .
@echo ""
@echo "Installing LaunchAgent..."
./scripts/install-launchagent.sh
@echo ""
@echo "Adding to Claude Code..."
@CLAUDE_CMD=$$(command -v claude || echo "$$HOME/.local/bin/claude"); \
if [ -x "$$CLAUDE_CMD" ]; then \
$$CLAUDE_CMD mcp add --transport http --scope user session-analytics http://localhost:8081/mcp 2>/dev/null && \
echo "Added session-analytics to Claude Code" || \
echo "session-analytics already configured in Claude Code"; \
else \
echo "Note: claude not found. Run manually:"; \
echo " claude mcp add --transport http --scope user session-analytics http://localhost:8081/mcp"; \
fi
@echo ""
@echo "Installation complete!"
@echo ""
@echo "Make sure ~/.local/bin is in your PATH:"
@echo ' export PATH="$$HOME/.local/bin:$$PATH"'

# Uninstall: LaunchAgent + CLI + MCP config
uninstall:
@echo "Uninstalling..."
./scripts/uninstall-launchagent.sh
@echo ""
@echo "Removing from Claude Code..."
@CLAUDE_CMD=$$(command -v claude || echo "$$HOME/.local/bin/claude"); \
if [ -x "$$CLAUDE_CMD" ]; then \
$$CLAUDE_CMD mcp remove --scope user session-analytics 2>/dev/null && \
echo "Removed session-analytics from Claude Code" || \
echo "session-analytics not found in Claude Code"; \
fi
@echo ""
@echo "Uninstall complete!"
@echo "Note: venv and source code remain in place."
Loading