Claude Transcripts docs GitHub
Work in progressUnder active development — not tested as ready for use. Breaking changes land without notice, stored data may need to be discarded between revisions, and there is no auth or security model. These docs describe the intended design as much as the current state.

Hook setup

The hook (hook/) is the writer half of the project: a Claude Code plugin that logs every session's events, an end-of-session summary, and the full transcript to CouchDB + an S3-compatible blob store (Garage). The webapi/webui then read that data back.

Prerequisites

1. Configure

Fill a .env (copy the repo-root .env.example) with your CouchDB credentials and S3 (Garage) key, then generate the hook config:

cd hook
ENV_FILE=../.env bash scripts/setup.sh

This writes ~/.config/claude-transcripts/config.json (mode 600), creates the CouchDB database, and syncs the design docs + Mango index. Re-run with FORCE=1 to regenerate the config.

The config shape (the db/bucket names + features/logging blocks are baked in from the repo-root claude-transcripts.config.json — see configuration.md):

{
  "couch": { "url": "http://127.0.0.1:5984", "db": "claude-sessions", "auth": "user:pass" },
  "blob": {
    "endpoint": "http://127.0.0.1:3900",
    "region": "garage",
    "accessKey": "...",
    "secretKey": "...",
    "bucket": "claude-sessions"
  },
  "features": { "s3Blobs": true },
  "logging": { "chunk": { "maxEntriesPerChunk": 200, "flushIntervalMs": 15000 } }
}

Omit blob (or leave accessKey empty) to log event/summary docs to CouchDB only. Note S3 is the transcript's sole home (ADR 0014): without a blob backend, transcript content is not persisted anywhere — only the summary doc's transcript_bytes is recorded.

2. Verify

bun run scripts/smoke-test.ts

Seeds one synthetic session through the whole write path (CouchDB doc, S3 blob round-trip, view queries) and prints PASS/FAIL. It cleans up after itself; pass --keep to leave the seeded session for the UI.

3. Register the hook with Claude Code

The normal route needs neither a plugin nor a checkout — the installed binary registers itself:

claude-transcripts hook install

It merges into ~/.claude/settings.json, so other tools' hooks are untouched and re-running is a no-op. claude-transcripts hook status shows what's registered.

If you'd rather use Claude Code's plugin mechanism, install the hooks/ directory (so ${CLAUDE_PLUGIN_ROOT} resolves):

claude plugin install /absolute/path/to/claude-transcripts/hooks

That form still requires the CLI to be installed: the plugin is a shim that pipes each payload to claude-transcripts hook run.

Architecture

Either route ends in the same place — claude-transcripts hook run (hook.md) — which reads one payload on stdin and runs the actions bound to that event by the app model. One event can drive several actions; they run concurrently and settled, and the process always exits 0.

Registered events: SessionStart, UserPromptSubmit, PostToolUse, PostToolUseFailure, Stop, SubagentStart, SubagentStop, SessionEnd. Live events write as they happen; SessionEnd writes the summary + transcript.

To wire another supported event (PreToolUse, Notification, PreCompact, …), add the binding to the model's BINDINGS and re-run bun run gen:hooks — dispatch and registration are both projections of it, so neither is edited by hand.

4. (Optional) Backfill existing history

Adopting on-disk history is no longer a hook script — it's the CLI's backfill command (cli.md, tools.md), which reconstructs each session at parity with a live recording (summary + per-event docs, and — planned — chunk docs) rather than a thin summary-only record:

claude-transcripts backfill --dry-run   # preview
claude-transcripts backfill             # adopt ~/.claude/projects/**.jsonl

Backfilled summaries are tagged source: "backfill" (+ backfilled_at) to distinguish them from live (source: "live") recordings, and the transcript's real timestamps are preserved. Existing sessions are skipped, so it's safe to re-run.