{"id":51126906,"url":"https://github.com/yasyf/cc-transcript","last_synced_at":"2026-06-25T08:32:26.560Z","repository":{"id":363282680,"uuid":"1262633876","full_name":"yasyf/cc-transcript","owner":"yasyf","description":"Typed, non-lossy events for Claude Code transcripts: superset JSONL parser (Rust fast path), sentiment + feedback-mining domains, and a transcript-investigation CLI","archived":false,"fork":false,"pushed_at":"2026-06-23T06:07:11.000Z","size":23292,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-23T08:08:33.199Z","etag":null,"topics":["anthropic","claude","claude-code","claude-code-plugin","cli","jsonl","parser","pyo3","python","rust","transcripts"],"latest_commit_sha":null,"homepage":"https://yasyf.github.io/cc-transcript/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yasyf.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-08T07:09:45.000Z","updated_at":"2026-06-23T06:06:54.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yasyf/cc-transcript","commit_stats":null,"previous_names":["yasyf/cc-transcript"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/yasyf/cc-transcript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasyf%2Fcc-transcript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasyf%2Fcc-transcript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasyf%2Fcc-transcript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasyf%2Fcc-transcript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yasyf","download_url":"https://codeload.github.com/yasyf/cc-transcript/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasyf%2Fcc-transcript/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34767543,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-25T02:00:05.521Z","response_time":101,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anthropic","claude","claude-code","claude-code-plugin","cli","jsonl","parser","pyo3","python","rust","transcripts"],"created_at":"2026-06-25T08:32:19.504Z","updated_at":"2026-06-25T08:32:26.548Z","avatar_url":"https://github.com/yasyf.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cc-transcript\n\n![cc-transcript banner](https://github.com/yasyf/cc-transcript/raw/main/docs/assets/readme-banner.webp)\n\n[![PyPI](https://img.shields.io/pypi/v/cc-transcript.svg)](https://pypi.org/project/cc-transcript/)\n[![Python](https://img.shields.io/pypi/pyversions/cc-transcript.svg)](https://pypi.org/project/cc-transcript/)\n[![Docs](https://img.shields.io/github/actions/workflow/status/yasyf/cc-transcript/docs.yml?branch=main\u0026label=docs)](https://yasyf.github.io/cc-transcript/)\n[![License: PolyForm Noncommercial](https://img.shields.io/badge/License-PolyForm--Noncommercial--1.0.0-blue.svg)](https://github.com/yasyf/cc-transcript/blob/main/LICENSE)\n\nA non-lossy parser for Claude Code's on-disk JSONL transcripts, plus a CLI to investigate sessions.\n\n`cc-transcript` parses Claude Code's JSONL transcripts into a typed superset event model — every entry type preserved, nothing dropped. The parser never silently discards sidechains, synthetic turns, tool results, or unrecognized entries; filtering is opt-in and lives in your code, not buried in the parser. It ships as a Python library, a `uvx`-runnable CLI, and a Claude Code plugin.\n\n## Install\n\n```bash\nuvx cc-transcript --help    # run the CLI\n```\n\n## Quickstart\n\nDiscover the transcripts on disk, parse one, and walk the events:\n\n```python\nimport anyio\n\nfrom cc_transcript import AssistantEvent, TranscriptDiscovery, UserEvent, parse_events_from_bytes\n\npath = anyio.run(TranscriptDiscovery.find_transcripts)[0]\nevents = parse_events_from_bytes(path.read_bytes())\n\nfor event in events:\n    match event:\n        case UserEvent(text=text):\n            print(\"user:\", text[:80])\n        case AssistantEvent(model=model, text=text):\n            print(f\"assistant ({model}):\", text[:80])\n```\n\nFiltering is opt-in. Compose a spec from small builders and apply it — `build_spec` assembles clauses, `apply_spec` yields the survivors. `NOISE_SPEC` is a ready-made spec for universal structural noise (system reminders, local-command output, skill banners):\n\n```python\nfrom cc_transcript import apply_spec, build_spec, keep_only, drop_junk, drop_short\n\nspec = build_spec(keep_only(\"user\", \"assistant\"), drop_junk(\"structural\"), drop_short(2))\nclean = list(apply_spec(events, spec))\n```\n\n## CLI\n\nEvery command runs as `uvx cc-transcript \u003ccommand\u003e ...`; see `--help` on any command for its flags.\n\n| Command  | What it does |\n| -------- | ------------ |\n| `list`   | Find transcripts on disk, newest first |\n| `stats`  | Summarize a session — counts, kinds, models, tools, token sizes, span |\n| `show`   | Render one compact line per event (`--signal` keeps the conversational spine) |\n| `grep`   | Search event content; hit indexes feed back into `show --range` |\n| `slice`  | Emit per-tool-call JSONL for a session UUID and time window (the bridge cc-review consumes) |\n| `digest` | Generate and check the cross-language fixture corpus for the tool-digest contract |\n\nThe output is compact by design — one line per event, hard truncation — so an agent triages a session in a few hundred tokens instead of paging through megabytes of JSONL:\n\n```console\n$ uvx cc-transcript stats ~/.claude/projects/-Users-yasyf-Code-cc-transcript/4c77d556-8694-4613-8f50-253d905da68e.jsonl\nfiles        1\nevents       181\nkinds        other 68 · assistant 53 · user 33 · mode 22 · system 5\nmodels       claude-fable-5 53\ntools        TaskCreate 10 · Agent 5 · Read 5 · TaskUpdate 5 · Bash 2 · ToolSearch 2 · AskUserQuestion 1 · ExitPlanMode 1\ntext         14.8KB\nthinking     8.7KB\ntool io      89.0KB\nsessions     1\nspan         2026-06-12 01:07:55 → 2026-06-12 02:28:03\ninterrupts   0\ntool errors  0\nsidechain    0\n```\n\n## Claude Code plugin\n\nInstall the bundled plugin from inside Claude Code:\n\n```\n/plugin marketplace add yasyf/cc-transcript\n/plugin install cc-transcript@cc-transcript\n```\n\nThe plugin's skill teaches Claude to answer questions about its own history — \"what did I ask yesterday\", \"find the session where we fixed the parser\" — by funneling through the CLI's `list`, `stats`, `grep`, and `show` commands instead of reading raw JSONL.\n\n## How it works\n\nThe event model is a superset: sidechains, `\u003csynthetic\u003e` turns, thinking blocks, and unrecognized entry types all survive parsing, so you decide what to drop via composable filter specs. Two engines sit behind one `Backend` protocol — `RustBackend` (PyO3 + rayon) is the default fast path, `PythonBackend` is the readable reference, parity-asserted against each other. On top of the spine, `SessionActivity` lifts events into turns and typed tool calls, `FileStateStore` tracks per-file mtimes in SQLite for incremental re-parses, and `cc_transcript.mining`/`judge`/`sentiment` extract feedback, run LLM verdict passes, and score conversational sentiment. The [docs site](https://yasyf.github.io/cc-transcript/) covers each of these in depth.\n\n## Docs\n\nEach section of [the docs site](https://yasyf.github.io/cc-transcript/) is a focused guide:\n\n- [Getting Started](https://yasyf.github.io/cc-transcript/docs/getting-started/index.html) — install, parse, filter, persist.\n- [Filtering events](https://yasyf.github.io/cc-transcript/docs/guide/filtering-events.html) — clauses, specs, and `NOISE_SPEC`.\n- [Scoring sentiment](https://yasyf.github.io/cc-transcript/docs/guide/scoring-sentiment.html) — the lexicon engine and score specs.\n- [Rust/Python backends \u0026 parity](https://yasyf.github.io/cc-transcript/docs/guide/backends-and-parity.html) — the `Backend` protocol and parity testing.\n- [Compose your own policy](https://yasyf.github.io/cc-transcript/docs/guide/compose-your-own-policy.html) — building a bespoke filtering policy.\n- [Mining feedback](https://yasyf.github.io/cc-transcript/docs/guide/mining-feedback.html) — detectors, confidence, candidates, and verdicts.\n- [The transcript CLI](https://yasyf.github.io/cc-transcript/docs/guide/transcript-cli.html) — `list`/`show`/`grep`/`stats` end to end.\n- [API reference](https://yasyf.github.io/cc-transcript/reference/index.html) — the complete typed surface.\n\n## License\n\n[PolyForm Noncommercial 1.0.0](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyasyf%2Fcc-transcript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyasyf%2Fcc-transcript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyasyf%2Fcc-transcript/lists"}