Skip to main content

cc-observatory

Local observability for Claude Code: see your sessions, subagents, blocks, logs, tokens and cost, on your own machine.

Leia em português

CI PyPI License: MIT Python 3.12+

Status

Pre-alpha. v0.5.0 closes milestone 4 of 8: the ccobs CLI. The cc-observatory package on PyPI now carries the CLI (uvx cc-observatory setup); the stack and the app still run from a clone of this repository.

What v0.5.0 adds (see docs/cli.md):

  • ccobs setup: writes the telemetry settings and the hooks into Claude Code's user settings, with a backup, --dry-run and an atomic write, and never removes or overwrites your own entries;
  • ccobs uninstall: removes only what setup added;
  • ccobs doctor: checks the settings, Claude Code, the stack and the host, and says how to fix what fails;
  • ccobs status: a short summary of the app and its sessions;
  • a diagnostics endpoint in the app for these commands, and an empty overview that leads with the setup command;
  • ADRs 0036 to 0040, including the decision to keep v0.5.0 metadata only and defer the content opt-in.

Earlier releases: v0.4.0 (milestone 3) added the web UI, v0.3.0 (milestone 2) the app that receives Claude Code's hooks, v0.2.0 (milestone 1) the observability stack in Docker Compose with a provisioned Grafana, and v0.1.0 (milestone 0) laid the foundation.

What comes next: milestone 5 (v0.6.0), alerts in the browser and on Discord. The full plan is in the roadmap below.

Unless a section says otherwise, the rest of this README describes the planned design.

What it shows

The release that brings each part is in parentheses. The parts up to v0.5.0 work today: the stack and the app run from a clone of this repository (see "Run the observability stack" and "Try the app" below), and the CLI comes from PyPI; the rest is planned.

  • Live overview of the Claude Code sessions on your machine, in a web UI at http://127.0.0.1:4300: the sessions waiting on you first, with how long each has waited, then the ones working, idle, recently ended or stale. It updates as Claude Code works, without a reload (v0.4.0).
  • Blocks: sessions waiting on you, such as a permission prompt or an MCP elicitation, with how long each one has been waiting and how it ended (tracked from v0.3.0, shown in the web UI from v0.4.0).
  • A page per session (v0.4.0) with its blocks, its agent tree (the subagents, each under the agent that started it), its tokens and cost (tokens by type, tokens and cost by model) and its hook timeline, metadata only.
  • Events and logs for each session: the hook timeline on its page, and a link to its Claude Code events in Grafana (v0.4.0).
  • Tokens and cost: per session on its page (v0.4.0), and across sessions by day and model in Grafana's overview dashboard (v0.2.0); by agent type (built-in agent names; your own agents show as custom unless you opt in to tool details) and by project (joined from the working directory that hooks report) are planned for v0.7.0. Cost is an estimate that comes from Claude Code's telemetry, not the amount you are billed.
  • Health page: whether each part of the stack is up and receiving data (planned, v0.7.0).
  • Grafana for deeper analysis, provisioned with its datasources and a Claude Code overview dashboard (v0.2.0); each session's page links to its logs, tokens and cost there (v0.4.0), and later dashboards will open already filtered to the agent or project you were looking at (v0.7.0).
  • Alerts (v0.6.0): browser notifications and, optionally, a Discord webhook when a session has been waiting on you for longer than a threshold, when API errors keep repeating, or when the estimated cost of a session or of a day goes over a limit. You set the thresholds with environment variables or on a settings screen.

How it works

Claude Code ──OTLP (4317/4318)──► OTel Collector ──► Prometheus (metrics)
     │                                         ├──► Loki (events/logs)
     │                                         └──► Tempo (traces, optional profile)
     └──hooks──► app (FastAPI) ──► SQLite (sessions, agents, blocks, alerts)
                    │  └─ /metrics ◄── scraped by Prometheus (live state)
                    └─ queries Prometheus and Loki over HTTP
Grafana ◄── Prometheus, Loki, Tempo (provisioned datasources and dashboards)
  • Telemetry. Claude Code's native OpenTelemetry support exports metrics, events and, optionally, traces over OTLP to an OpenTelemetry Collector. The collector removes personal attributes and sends metrics to Prometheus, events to Loki and traces to Tempo. Tempo runs only in an optional traces profile, because tracing is a beta feature in Claude Code.
  • Hooks. Claude Code hooks send lifecycle events (a prompt submitted, a permission request, a notification, a subagent starting or stopping, a compaction, the end of a session) to the app, a FastAPI service that keeps sessions, agents, blocks and alerts in SQLite.
  • Live state as metrics. The app exposes that live state on /metrics, which Prometheus scrapes, so it can be charted next to the telemetry.
  • The web UI. The app serves its own pages, which follow the sessions live over server-sent events, and reads each session's tokens and cost from Prometheus. It also closes permission prompts denied with Esc from Claude Code's events in Loki.
  • Grafana comes provisioned with the Prometheus, Loki and Tempo datasources and with the dashboards.
  • Why both sources: telemetry tells you what a session consumed (tokens, cost, API calls, tool results) but not that it is waiting on you right now, which only hooks report, at the moment it happens.

More detail for contributors is in docs/architecture.md. The decisions behind this design, and their reasons, are recorded as architecture decision records in docs/adr/.

Quick start (from v0.5.0)

  1. Start the stack:

    git clone https://github.com/Luanderson-Dev/cc-observatory
    cd cc-observatory
    docker compose up -d
    

    The first start downloads about 750 MB of images and builds the collector's and the app's images. docker compose ps shows each service and whether it is healthy.

  2. Connect Claude Code to it:

    uvx cc-observatory setup
    

    setup backs up your user settings (~/.claude/settings.json) and adds the hooks and the telemetry env block to them, keeping your own entries. It records what it added, so that ccobs uninstall removes only that; --dry-run shows the diff without writing anything, and running it again is safe.

  3. Start a new Claude Code session. The hooks reach the sessions already open at once, but telemetry (tokens, cost, events) starts only in sessions started after setup, so restart the ones you want to see in full.

  4. Open the app at http://127.0.0.1:4300, the address setup prints, and Grafana at http://localhost:4330.

If nothing shows up, run uvx cc-observatory doctor: it checks Claude Code, your settings, the policies that can block hooks or telemetry, and the stack, and says how to fix what it finds. uvx cc-observatory status is the short version.

  • The CLI. ccobs and cc-observatory are the same CLI: uvx cc-observatory <command> runs it without installing it, and uv tool install cc-observatory installs it as ccobs. docs/cli.md covers setup, uninstall, doctor and status, their options and exit codes, and troubleshooting.
  • Without changing your settings. To connect one session only, start Claude Code with the hooks in a file of their own, claude --settings <file>, as docs/app.md shows.
  • Undo. uvx cc-observatory uninstall takes out what setup added and puts back any value it replaced. The stack keeps running until docker compose down.

Run the observability stack (from v0.2.0)

From v0.2.0 you can run the observability stack from a clone of this repository and see Claude Code's metrics and events in Grafana. From v0.3.0 the stack also runs the app (hooks, sessions and blocks; see "Try the app" below), and from v0.4.0 the app's web UI.

  1. Start the stack as in the quick start. To also store Claude Code's traces, a beta feature, start it with docker compose --profile traces up -d, which adds Tempo, and pass --profile traces every time you start or update the stack.

  2. Open Grafana at http://localhost:4330. Use localhost: Grafana redirects any other host name, 127.0.0.1 included, there. There is no login. The home page is the Claude Code overview dashboard: cost, tokens, sessions, active time, code changes, API errors and recent events.

  3. Point Claude Code at the stack. ccobs setup writes these variables into the env block of your user settings, ~/.claude/settings.json (--traces adds the two trace variables below, --otlp-port changes the port). To set them by hand instead, add them to that block, keeping the entries you already have, or export them in the shell that starts Claude Code. Project settings (.claude/settings.json and .claude/settings.local.json) cannot set them.

    {
      "env": {
        "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
        "OTEL_METRICS_EXPORTER": "otlp",
        "OTEL_LOGS_EXPORTER": "otlp",
        "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
        "OTEL_EXPORTER_OTLP_ENDPOINT": "http://127.0.0.1:4318",
        "OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": "cumulative"
      }
    }
    
    • Use 127.0.0.1, not localhost: the ports listen on IPv4 only, and localhost can resolve to ::1.
    • Claude Code has no default protocol, so set one. grpc also works, with http://127.0.0.1:4317.
    • Cumulative temporality is recommended: with Claude Code's default, delta, some totals can come out low after a pause (the known limit).
    • Leave OTEL_METRICS_INCLUDE_SESSION_ID at its default (true): without session IDs, the series of concurrent sessions collide.
    • For traces, also set CLAUDE_CODE_ENHANCED_TELEMETRY_BETA to 1 and OTEL_TRACES_EXPORTER to otlp (or run ccobs setup --traces), and run the stack with --profile traces.
  4. Restart Claude Code so that new sessions load the settings. Metrics arrive every 60 seconds and events every 5 seconds, and the dashboard refreshes every minute. If nothing shows up, run ccobs doctor, or see No data in the dashboard.

  • Settings. Every setting is an environment variable with a default, so a .env file is optional: to change one, copy .env.example to .env, edit it and run docker compose up -d again. CCOBS_HOST_LABEL (default local) is the host label stored on every metric, event and trace; set it to name the machine. It is stored as you write it, so use the machine's real host name only if you want it stored. The ports and the retention (by default 90 days of metrics, 30 of events and 7 of traces) are set the same way. If you move a port, pass the same port to ccobs (--app-port, --otlp-port, --grafana-port).
  • After a reboot. The services restart unless you stop them with docker compose stop, so the stack comes back whenever Docker starts (ADR 0019). Docker Desktop starts when you sign in only if its "Start Docker Desktop when you sign in to your computer" setting is on, and it is off by default; on Linux, enable the Docker service at boot.
  • More. docs/stack.md covers stopping and updating the stack, its settings, data and retention, memory, and troubleshooting.

Try the app (from v0.3.0, web UI from v0.4.0)

From v0.3.0, docker compose up -d also builds the app's image from your clone and starts it at http://127.0.0.1:4300. The app receives Claude Code's hooks and tracks sessions, agents and blocks in SQLite. From v0.4.0 it shows them in a web UI at that address; it also serves them as a read-only JSON API.

  1. Start or update the stack as above. docker compose ps shows app as healthy once it serves requests.

  2. Point Claude Code at the app: ccobs setup writes the hooks (see the quick start). The hook URL uses 127.0.0.1, not localhost. To send the hooks of one session only, without changing your settings, use the hooks file and claude --settings of docs/app.md.

  3. Open http://127.0.0.1:4300 in your browser. The overview shows your sessions in bays by state, the ones waiting on you first, and follows them live; click a session for its blocks, agents, tokens and cost, and hook timeline, and for links to its logs and usage in Grafana. Until the first session arrives, the overview shows the ccobs setup command for its port. The same data is in the JSON API:

    curl -s http://127.0.0.1:4300/api/v1/sessions
    

    Each session has its state (working, waiting_user, idle, ended or stale), and /api/v1/sessions/<session_id> adds its agents and blocks.

  • Stack down. While the stack is down, Claude Code shows a hook-error notice in the transcript on most hook events; start the stack, or run ccobs uninstall to take the hooks out until it is back.
  • Esc denials, tokens and cost. A permission prompt denied with Esc fires no hook; the app closes it from Claude Code's events in Loki. A session's tokens and cost come from Claude Code's metrics in Prometheus. Both need the telemetry settings that ccobs setup writes (step 3 of the previous section).
  • More. docs/app.md covers the web UI, the API, the app's metrics in Grafana, its settings and retention, privacy and troubleshooting.

Privacy

  • Metadata only by default. Prompt text, tool inputs and outputs, assistant messages and error text are not stored.
  • No content capture yet. ccobs setup never turns content capture on, and the collector drops content from the telemetry even if Claude Code was set to send it; ccobs doctor warns when Claude Code's content variables are on. The explicit opt-in to keep content is deferred to a later release (ADR 0040).
  • Personal attributes are removed. The collector deletes your email address, your user, account and organization IDs and your machine's host name from the telemetry before anything is stored.
  • Everything stays on your machine. That is a design goal that the bundled configs enforce: every port binds to 127.0.0.1; Prometheus, Loki and Tempo publish no port and sit on an internal network with no route out; and the usage reporting and update checks of Grafana, Loki and Tempo are turned off. At runtime, nothing leaves your machine except the optional Discord webhook, if you configure one, and DNS lookups of a store's name while that store is stopped (see SECURITY.md).
  • The web UI (from v0.4.0) has no login either, loads nothing from the internet and changes nothing. It shows the working directory only as the project name, or with your home directory as ~, and refuses requests that other web pages make through your browser (a link to it still just opens it).
  • Grafana has no login. Whoever opens it is an Editor, who can query the data and save dashboards but cannot change its datasources, plugins, users or settings. It answers only as localhost, which keeps other web pages from reading it through DNS rebinding, and it refuses the cross-site requests that could change it or read its answers; a page can still make it run a query blindly, without seeing the result. Anything that runs on your machine can read the data.
  • Retention is configurable (the observability stack from v0.2.0, by default 90 days of metrics, 30 of events and 7 of traces; the app database from v0.3.0), so old data is deleted after the period you choose.

See SECURITY.md for the security model, including what a web page can still do, and how to report a vulnerability.

No interference with Claude Code

  • Hooks never change Claude Code's decisions. The app answers every hook call with an empty 2xx response, never with a decision, and setup gives every hook a short timeout.
  • If the stack is down, Claude Code keeps working. While the stack is down, Claude Code shows a hook-error notice in the transcript on most hook events (Claude itself does not see these notices). ADR 0011 explains this trade-off and how cc-observatory keeps it small: ccobs doctor checks that the hook endpoint answers and reports failing hooks, and ccobs uninstall removes the hooks.

Requirements

  • Docker Engine 25.0 or later with the Docker Compose plugin 2.20.2 or later (and, if the Buildx plugin is installed, Buildx 0.17.0 or later): Docker Desktop on Windows and macOS, or Docker's own packages on Linux, where Docker Engine 28.0 or later also keeps ports published to 127.0.0.1 out of reach of other hosts on the local network.
  • Memory: leave Docker at least 2304 MiB for the stack (2816 MiB with Tempo), the sum of its memory limits. Measured use was about 260 to 290 MiB idle and 420 to 450 MiB while the dashboard's queries ran through Grafana's API, before the app joined the stack; the app, measured on its own, used about 64 to 70 MiB. Loading Grafana's UI in a browser briefly took Grafana alone to about 630 MiB.
  • Disk: about 3 GB for the images, plus about 250 MB for the app's image, plus the data.
  • Tested on Linux and on Windows 11 with Docker Desktop, both on amd64; macOS and arm64 have not been tested. Details are in docs/stack.md.
  • uv, for the ccobs CLI (uvx cc-observatory; see docs/cli.md).
  • Claude Code 2.1.296 or later. That is the version cc-observatory was tested against (ADR 0012); older versions are not supported until they are tested.

Roadmap

Milestone Release Scope Status
0 v0.1.0 Foundation, tooling, CI, ADRs, telemetry and hooks spike, fixtures, first PyPI release Released
1 v0.2.0 Observability stack in compose, provisioned Grafana Released
2 v0.3.0 Hook ingestion, session state machine, SQLite, blocks, /metrics Released
3 v0.4.0 Web UI (HTMX + SSE) Released
4 v0.5.0 ccobs setup, uninstall, doctor, status Released
5 v0.6.0 Alerts (browser and Discord) Planned
6 v0.7.0 Grafana dashboards and polish Planned
7 v1.0.0 Distribution: GHCR multi-arch images, release hardening, contributor docs Planned

Development

You need uv; it installs the right Python version for you.

uv sync                                # create the virtualenv with the dev dependencies
uv run pre-commit install              # install the pre-commit and commit-msg hooks
uv run pytest                          # unit tests with the coverage gate
uv run mypy                            # strict type checks
uv run pre-commit run --all-files      # every check that the CI lint job runs
uv run pytest -m integration --no-cov  # integration tests (need Docker)
  • The integration tests start their own compose project, ccobs-it, on ports of their own, so they can run next to your stack; see docs/stack.md.
  • The project uses Gitflow. develop is the default branch: feature pull requests target develop and are squash-merged, and release pull requests go to main with merge commits.
  • The title of a feature pull request becomes its commit on develop (and, for feat, fix, refactor and perf, a changelog line), so every PR title must be a Conventional Commit (for example, feat: add the session state machine). CI checks it.
  • A contributor guide comes with v1.0.0.

Disclaimer

cc-observatory is an independent open-source project. It is not affiliated with, endorsed by or sponsored by Anthropic. "Claude" and "Claude Code" are trademarks of Anthropic, PBC.

License

MIT. Copyright (c) 2026 Luanderson Pimenta Mendes (Luanderson-Dev).

Metadata

Release files for cc-observatory 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cc-observatory 0.5.0
File Size Uploaded Provenance
cc_observatory-0.5.0.tar.gz 348.3 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for cc-observatory 0.5.0
File Interpreter ABI Platform
cc_observatory-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 732.2 kB

Release files / cc_observatory-0.5.0.tar.gz

Download URL cc_observatory-0.5.0.tar.gz
Size 348.3 kB
Tags Source
SHA-256 checksum
How to use checksums
24366c5d1a451d72c5a7d29fdc2b750d45f47a5768a03e1f0e1dd1cc2b65dc46
BLAKE2b-256 checksum
How to use checksums
457045cc758260b5c0d813bd25da576270e6739adac8e42fa63586d227a7ee08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Release files / cc_observatory-0.5.0-py3-none-any.whl

Download URL cc_observatory-0.5.0-py3-none-any.whl
Size 383.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4648c0c202d57e7526f7e547701f2bd683b53b6e8861cebf2ea29394b2992dcd
BLAKE2b-256 checksum
How to use checksums
f9c93198cbecd1e3a9669a27a6a5c4e7187f09425229804e274c276ae9b76349
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

Security for cc-observatory 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for cc_observatory-0.5.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page