The Eye β self-hosted observability for AI coding assistants.
You use Claude Code, Codex, or Gemini CLI every day. You have no idea how much they cost, which tools they call, or whether they're actually helping. This fixes that.
More screenshots
Tools β 5K calls across all three CLIs, top tools ranked, failing tools by error count:
Operations β live event rate, breakdown by source and event type:
Claude Code Deep Dive β per-model cost, token breakdown, cache efficiency, productivity ratio:
Claude Code Deep Dive (Tools) β tool decisions, active time breakdown:
Quality β cache hit rates, error rates, session trends:
- Highlights
- Quick Start
- Dashboards
- How It Works
- Hook Setup
- Claude Code Skills
- Rust Accelerator
- Alerting
- Services
- Architecture
- Project Structure
- Contributing
- License
- One command to start:
./scripts/init.shβ 6 services, 8 dashboards, under a minute - Three CLIs supported: Claude Code, Codex, Gemini CLI β hooks + native OpenTelemetry
- Eight Grafana dashboards auto-provisioned: cost, tools, operations, quality, per-provider deep dives, and session timeline
- Minimal dependencies β Docker, plus
bash,curl, andjqon the host for hooks and tests. No Python, no Node, no cloud accounts - Optional Rust accelerator β drop-in
shepard-hookbinary replaces bash+jq+curl. Hooks auto-detect it; falls back to bash if absent - Six Claude Code skills β
/obs-status,/obs-cost,/obs-sessions,/obs-tools,/obs-alerts,/obs-queryβ query the stack without leaving your terminal - Works offline β everything runs on localhost, your data stays on your machine
Prerequisites: Docker (with Compose v2), curl, jq, and at least one AI CLI installed.
git clone https://github.com/shepard-system/shepard-obs-stack.git
cd shepard-obs-stack
./scripts/init.sh # starts stack + health check
./hooks/install.sh # injects hooks into your CLI configsOpen localhost:3000 (admin / shepherd). Use your CLI as usual β data appears in dashboards within seconds.
./scripts/test-signal.sh # verify the full pipeline (11 checks)| Dashboard | Question it answers |
|---|---|
| Cost | How much is this costing me? |
| Tools | Who is performing and who is wandering? |
| Operations | What is happening right now? |
| Quality | How well is the system working? |
| Dashboard | What you see |
|---|---|
| Claude Code | Token usage, cost by model, tool decisions, active time |
| Codex | Sessions, API latency percentiles, reasoning tokens |
| Gemini CLI | Token breakdown, latency heatmap, tool call routing |
| Dashboard | What you see |
|---|---|
| Session Timeline | Synthetic traces from all 3 CLI session logs β tool call waterfall, MCP timing, sub-agents |
Click any Trace ID to open the full waterfall in Grafana Explore β Tempo.
Dashboard template variables: Tools and Operations support $source and $git_repo filtering.
Deep Dive dashboards use $model. Session Timeline uses $provider. Cost and Quality show aggregated data without filters.
AI CLIs emit telemetry through two channels:
AI CLI (Claude Code / Codex / Gemini)
β
βββ bash hooks β OTLP metrics (tool calls, events, git context)
β βββ OTel Collector :4318
β
βββ native OTel β gRPC (tokens, cost, logs, traces)
βββ OTel Collector :4317
β
βββ metrics β Prometheus :9090
βββ logs β Loki :3100
βββ traces β Tempo :3200
β
Loki recording rules ββββ remote_write ββββ Prometheus
β
Grafana :3000 βββ PromQL + LogQL βββββββββββ
Hooks provide what native OTel cannot: git repo context and labeled tool/event counters. Everything else (tokens, cost, sessions) comes from native OTel export.
./hooks/install.sh # all detected CLIs
./hooks/install.sh claude # specific CLI
./hooks/install.sh codex gemini # selective
./hooks/uninstall.sh # clean removalThe installer auto-detects installed CLIs and merges hook configuration into their config files (creating backups first).
| CLI | Hooks | Native OTel signals |
|---|---|---|
| Claude Code | PreToolUse, PostToolUse, SessionStart, Stop |
metrics + logs |
| Codex CLI | agent-turn-complete |
logs |
| Gemini CLI | AfterTool, AfterAgent, AfterModel, SessionEnd |
metrics + logs + traces |
Six slash-command skills for querying the obs stack directly from Claude Code β no browser needed.
| Skill | What it does |
|---|---|
/obs-status |
Stack health: service status, scrape targets, last telemetry, active alerts |
/obs-cost |
Cost report by provider and model (supports today, yesterday, week, 24h) |
/obs-sessions |
Recent sessions with model, duration, tool count, cost |
/obs-tools |
Top tools, error rates, usage by provider and repo |
/obs-alerts |
Active alerts with severity and resolution hints |
/obs-query |
Free-form PromQL or LogQL β run any query inline |
Skills are installed automatically when you clone the repo (they live in .claude/skills/). All API calls go through scripts/obs-api.sh β a centralized helper that's ready for auth and TLS when you need it:
# Default: plain HTTP to localhost (single-machine, no auth)
./scripts/obs-api.sh prometheus /api/v1/query --data-urlencode 'query=up'
# With auth (set env vars when hardening or going multi-machine)
SHEPARD_API_TOKEN=secret ./scripts/obs-api.sh prometheus /api/v1/query ...
SHEPARD_CA_CERT=/path/to/ca.pem ./scripts/obs-api.sh loki /readyAll hooks work out of the box with bash + jq + curl. For faster execution, you can optionally install the Rust accelerator β a single static binary that replaces the entire bash pipeline:
./scripts/install-accelerator.sh # latest release β hooks/bin/ (no sudo)
./scripts/install-accelerator.sh v0.1.0 # specific versionThe installer downloads a pre-built binary from GitHub Releases (linux/macOS, x64/arm64) and verifies it against the SHA256SUMS file published with each release. The binary is placed in hooks/bin/ (gitignored, project-local).
Hooks auto-detect it via hooks/lib/accelerator.sh (project-local β PATH β bash fallback). No configuration needed β if the binary is present, hooks use it; if not, they fall back to bash.
Remove with ./hooks/uninstall.sh or simply delete hooks/bin/.
Alertmanager runs on :9093 with 16 alert rules in three tiers:
| Tier | Alerts | Examples |
|---|---|---|
| Infrastructure | 6 | OTelCollectorDown, CollectorHighMemory, PrometheusHighMemory, export failures |
| Pipeline | 5 | LokiDown, ShepherdServicesDown, TempoDown, PrometheusTargetDown, LokiRecordingRulesFailing |
| Business logic | 5 | HighSessionCost (>$10/hr), HighTokenBurn (>50k tok/min), HighToolErrorRate (>10%), SensitiveFileAccess, NoTelemetryReceived |
Inhibit rules suppress business-logic alerts when infrastructure is down.
Native Telegram, Slack, and Discord receivers are included β uncomment and configure in configs/alertmanager/alertmanager.yaml:
# telegram_configs:
# - bot_token: 'YOUR_BOT_TOKEN'
# chat_id: YOUR_CHAT_ID
# send_resolved: true| Service | Port | Purpose |
|---|---|---|
| Grafana | 3000 | Dashboards & explore |
| Prometheus | 9090 | Metrics & alerts |
| Loki | 3100 | Log aggregation |
| Tempo | 3200 | Distributed tracing |
| Alertmanager | 9093 | Alert routing |
| OTel Collector | 4317/4318 | OTLP gRPC + HTTP |
C4 diagrams (click to expand)
shepard-obs-stack/
βββ docker-compose.yaml
βββ .env.example
βββ .claude/skills/ # Claude Code slash-command skills
β βββ obs-status/ # /obs-status β stack health
β βββ obs-cost/ # /obs-cost β cost report
β βββ obs-sessions/ # /obs-sessions β session summary
β βββ obs-tools/ # /obs-tools β tool usage
β βββ obs-alerts/ # /obs-alerts β active alerts
β βββ obs-query/ # /obs-query β free-form PromQL/LogQL
βββ hooks/
β βββ bin/ # Rust accelerator binary (gitignored, downloaded)
β βββ lib/ # shared: accelerator, git context, OTLP metrics + traces, sensitive file detection, session parser
β βββ claude/ # PreToolUse + PostToolUse + SessionStart + Stop
β βββ codex/ # notify.sh (agent-turn-complete)
β βββ gemini/ # AfterTool + AfterAgent + AfterModel + SessionEnd
β βββ install.sh # auto-detect + inject
β βββ uninstall.sh # clean removal
βββ scripts/
β βββ init.sh # bootstrap
β βββ install-accelerator.sh # download Rust accelerator to hooks/bin/
β βββ obs-api.sh # centralized API client (auth-ready)
β βββ test-signal.sh # pipeline verification (11 checks)
β βββ render-c4.sh # render PlantUML β SVG
βββ tests/
β βββ run-all.sh # test orchestrator (--e2e for Docker smoke)
β βββ test-shell-syntax.sh # bash -n + shellcheck
β βββ test-config-validate.sh # JSON + YAML validation
β βββ test-hooks.sh # behavioral tests (41 tests)
β βββ test-parsers.sh # session parser tests (24 tests)
β βββ fixtures/ # minimal session logs (Claude, Codex, Gemini)
βββ configs/
β βββ otel-collector/ # receivers β processors β exporters
β βββ prometheus/ # scrape targets + alert rules
β βββ alertmanager/ # routing, Telegram/Slack/Discord receivers
β βββ loki/ # storage + 15 recording rules
β βββ tempo/ # trace storage, 7d retention
β βββ grafana/ # provisioning + 8 dashboard JSONs
βββ docs/c4/ # architecture diagrams
113 automated tests across 4 suites, plus a Docker-based E2E smoke test:
bash tests/run-all.sh # unit tests: syntax, configs, hooks, parsers
bash tests/run-all.sh --e2e # + Docker E2E (starts stack, runs test-signal.sh)| Suite | Tests | What it checks |
|---|---|---|
| Shell Syntax | 23 | bash -n on all scripts, shellcheck (if installed) |
| Config Validation | 25 | JSON dashboards (jq) + YAML configs (PyYAML) + promtool rules + alert regression |
| Hook Behavior | 41 | PreToolUse guard, PostToolUse metrics, Stop compaction, all Gemini hooks, Codex, install/uninstall |
| Session Parsers | 24 | Span count, required fields, attributes, error status, trace_id consistency |
CI runs automatically on push/PR via GitHub Actions.
Issues and pull requests are welcome. Before submitting changes, run the tests:
bash tests/run-all.shElastic License 2.0 β free to use, modify, and distribute. Cannot be offered as a hosted or managed service.
Part of the Shepard System.





