ccq 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ccq-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 saagpatel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
ccq-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,150 @@
1
+ Metadata-Version: 2.4
2
+ Name: ccq
3
+ Version: 0.1.0
4
+ Summary: Query your own Claude Code agent history with DuckDB, read-only, straight over the JSONL transcripts.
5
+ Keywords: claude-code,duckdb,cli,jsonl,observability,agent-history
6
+ Author: saagpatel
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Topic :: Utilities
15
+ Requires-Dist: duckdb>=1.1.0
16
+ Requires-Dist: click>=8.1.0
17
+ Requires-Python: >=3.12
18
+ Project-URL: Homepage, https://github.com/saagpatel/ccq
19
+ Project-URL: Repository, https://github.com/saagpatel/ccq
20
+ Project-URL: Issues, https://github.com/saagpatel/ccq/issues
21
+ Description-Content-Type: text/markdown
22
+
23
+ # ccq — query your own Claude Code agent history
24
+
25
+ [![CI](https://img.shields.io/github/actions/workflow/status/saagpatel/ccq/ci.yml?style=flat-square&logo=githubactions&logoColor=white&label=CI)](https://github.com/saagpatel/ccq/actions/workflows/ci.yml)
26
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue?style=flat-square&logo=python&logoColor=white)](https://www.python.org/)
27
+
28
+ `ccq` makes your local Claude Code transcripts queryable. It runs **DuckDB directly
29
+ over the JSONL** at `~/.claude/projects/<project>/<session>.jsonl` — no copy, no ETL,
30
+ no database to maintain. The transcripts are only ever **read**, never written.
31
+
32
+ Ask it where your tokens go, which tools you lean on, where runs hit rate limits,
33
+ how much you delegate to subagents, and what happened inside any single session.
34
+
35
+ ```
36
+ $ ccq cost --by model
37
+ model turns in_tok out_tok cost_usd
38
+ ------------------------- ------ -------------- ----------- ---------
39
+ claude-opus-4-8 12,345 3,456,789,012 28,500,000 4,210.55
40
+ claude-sonnet-4-6 6,789 901,234,567 8,400,000 612.30
41
+ ...
42
+ ```
43
+
44
+ ## Install
45
+
46
+ ```bash
47
+ uv sync # create the venv + install deps
48
+ uv run ccq --help
49
+ ```
50
+
51
+ (Or `uv tool install .` to put `ccq` on your PATH.)
52
+
53
+ ## Commands
54
+
55
+ | Command | What it answers |
56
+ |---|---|
57
+ | `ccq sessions` | List sessions: project, span, message count, tokens, estimated cost. `--sort cost\|duration\|messages\|recent`, `--project`, `--since`, `-n`. |
58
+ | `ccq cost` | Cost rollups. `--by project\|model\|day\|session`. Main-loop only (see caveat). |
59
+ | `ccq tools` | Tool-use frequency. `--bash` breaks Bash calls down by leading command. |
60
+ | `ccq errors` | API errors / retries (429s, etc.) by project + status. `--list` for recent events. |
61
+ | `ccq agents` | Subagent (Agent tool) dispatches + token totals. `--by type\|model\|session\|project`. |
62
+ | `ccq session <id-prefix>` | One session's decision timeline: prompts, tool calls, errors, in order. |
63
+ | `ccq search <text>` | Full-text over your typed prompts and session titles → matching sessions. |
64
+ | `ccq sql "<SELECT…>"` | Run an arbitrary **read-only** query over the views (power surface). |
65
+ | `ccq serve` | Launch a local web dashboard (localhost only) with a read-only SQL box. |
66
+ | `ccq cache build\|status\|clear` | Manage the materialized snapshot that powers `--fast`. |
67
+
68
+ Every command takes `-f table|json|csv` and a global `--projects-dir` (defaults to
69
+ `~/.claude/projects`, handy for pointing at a backup).
70
+
71
+ ## Fast mode
72
+
73
+ A live query rescans ~1 GB of JSONL each time (~1-3 s). For instant repeat queries,
74
+ materialize a snapshot once and pass `--fast` (`-F`):
75
+
76
+ ```bash
77
+ ccq cache build # ~6 s, writes a ~100 MB snapshot to ~/.cache/ccq
78
+ ccq -F cost --by model # now ~0.1 s
79
+ ccq cache status # shows STALE once transcripts change; rebuild to refresh
80
+ ```
81
+
82
+ The snapshot lives under `$XDG_CACHE_HOME` (never in `~/.claude`), is opened
83
+ **read-only** at the engine level, and `--fast` builds it automatically on first use.
84
+
85
+ ## Web viewer
86
+
87
+ ```bash
88
+ ccq -F serve # http://127.0.0.1:8787 (Ctrl-C to stop)
89
+ ```
90
+
91
+ A dashboard (cost by model, tools, errors, subagents, priciest sessions) plus a SQL
92
+ box that runs the same read-only-guarded queries. **Drill down:** click a project
93
+ chip to filter to that project, or a session id to see its full decision timeline.
94
+ Standard-library `http.server`, no extra dependencies, binds to localhost only.
95
+
96
+ ## The query surface (`ccq sql`)
97
+
98
+ `sql` exposes these views — compose your own:
99
+
100
+ - **`sessions`** — one row per session: project, branch, span, `messages`, `models`, tokens, `cost_usd`.
101
+ - **`message_usage`** — one row per assistant turn: token breakdown + `cost_usd`.
102
+ - **`tool_calls`** — one row per tool invocation: `tool_name`, `tool_input` (JSON).
103
+ - **`errors`** — API error events: `status`, project, session, model.
104
+ - **`agents`** / **`agent_results`** — subagent dispatches joined to their `subagent_tokens`.
105
+ - **`prompts`** — searchable typed prompts + session titles.
106
+ - **`events`** — the raw per-line view everything else is built on.
107
+ - **`model_pricing`** — the per-model rate table used for costing.
108
+
109
+ ```bash
110
+ ccq sql "SELECT project, round(sum(cost_usd),2) usd
111
+ FROM message_usage WHERE ts >= DATE '2026-06-01'
112
+ GROUP BY 1 ORDER BY usd DESC"
113
+ ```
114
+
115
+ `sql` accepts a **single read-only statement** (SELECT/WITH/EXPLAIN/…). Writes,
116
+ `ATTACH`, `COPY`, `INSTALL`, and multi-statement input are refused. Tip: DuckDB
117
+ reserves words like `day`, `first`, `last` — quote them if used as aliases (`AS "day"`).
118
+
119
+ ## How it works
120
+
121
+ `read_ndjson_objects('~/.claude/projects/*/*.jsonl')` loads each line as an opaque
122
+ `JSON` value (zero schema inference — the records are heterogeneous), and SQL views
123
+ extract the entities. Two things the transcripts taught us are baked in:
124
+
125
+ - Numeric fields use `TRY_CAST` (heterogeneous lines otherwise break a hard cast).
126
+ - Token-casting views read from a type-filtered subquery so the optimizer can't
127
+ reorder a cast ahead of the `type = 'assistant'` filter.
128
+
129
+ ## Cost is estimated, and main-loop only
130
+
131
+ Transcripts store **token counts, not dollars**. `ccq` prices them with published
132
+ per-million-token rates (`src/ccq/pricing.py`) and the standard cache multipliers
133
+ (cache write 1.25×, cache read 0.10×). Two honest caveats:
134
+
135
+ 1. **Estimates, not invoices** — unknown/`<synthetic>` models price to `$0`.
136
+ 2. **Main-loop only** — a subagent's spend is **not** in the transcript. The only
137
+ signal that survives is `toolUseResult.totalTokens` (no input/output split, so it
138
+ can't be priced). `ccq agents` surfaces those token totals **separately**; they
139
+ are never folded into a dollar figure.
140
+
141
+ ## Develop
142
+
143
+ ```bash
144
+ uv run pytest # tests over synthetic fixtures
145
+ uv run ruff check . && uv run ruff format . # lint + format
146
+ uv run ty check src/ # type check
147
+ ```
148
+
149
+ Read-only on `~/.claude/projects` by contract — the test suite uses synthetic
150
+ fixtures and never reads your real history.
ccq-0.1.0/README.md ADDED
@@ -0,0 +1,128 @@
1
+ # ccq — query your own Claude Code agent history
2
+
3
+ [![CI](https://img.shields.io/github/actions/workflow/status/saagpatel/ccq/ci.yml?style=flat-square&logo=githubactions&logoColor=white&label=CI)](https://github.com/saagpatel/ccq/actions/workflows/ci.yml)
4
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue?style=flat-square&logo=python&logoColor=white)](https://www.python.org/)
5
+
6
+ `ccq` makes your local Claude Code transcripts queryable. It runs **DuckDB directly
7
+ over the JSONL** at `~/.claude/projects/<project>/<session>.jsonl` — no copy, no ETL,
8
+ no database to maintain. The transcripts are only ever **read**, never written.
9
+
10
+ Ask it where your tokens go, which tools you lean on, where runs hit rate limits,
11
+ how much you delegate to subagents, and what happened inside any single session.
12
+
13
+ ```
14
+ $ ccq cost --by model
15
+ model turns in_tok out_tok cost_usd
16
+ ------------------------- ------ -------------- ----------- ---------
17
+ claude-opus-4-8 12,345 3,456,789,012 28,500,000 4,210.55
18
+ claude-sonnet-4-6 6,789 901,234,567 8,400,000 612.30
19
+ ...
20
+ ```
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ uv sync # create the venv + install deps
26
+ uv run ccq --help
27
+ ```
28
+
29
+ (Or `uv tool install .` to put `ccq` on your PATH.)
30
+
31
+ ## Commands
32
+
33
+ | Command | What it answers |
34
+ |---|---|
35
+ | `ccq sessions` | List sessions: project, span, message count, tokens, estimated cost. `--sort cost\|duration\|messages\|recent`, `--project`, `--since`, `-n`. |
36
+ | `ccq cost` | Cost rollups. `--by project\|model\|day\|session`. Main-loop only (see caveat). |
37
+ | `ccq tools` | Tool-use frequency. `--bash` breaks Bash calls down by leading command. |
38
+ | `ccq errors` | API errors / retries (429s, etc.) by project + status. `--list` for recent events. |
39
+ | `ccq agents` | Subagent (Agent tool) dispatches + token totals. `--by type\|model\|session\|project`. |
40
+ | `ccq session <id-prefix>` | One session's decision timeline: prompts, tool calls, errors, in order. |
41
+ | `ccq search <text>` | Full-text over your typed prompts and session titles → matching sessions. |
42
+ | `ccq sql "<SELECT…>"` | Run an arbitrary **read-only** query over the views (power surface). |
43
+ | `ccq serve` | Launch a local web dashboard (localhost only) with a read-only SQL box. |
44
+ | `ccq cache build\|status\|clear` | Manage the materialized snapshot that powers `--fast`. |
45
+
46
+ Every command takes `-f table|json|csv` and a global `--projects-dir` (defaults to
47
+ `~/.claude/projects`, handy for pointing at a backup).
48
+
49
+ ## Fast mode
50
+
51
+ A live query rescans ~1 GB of JSONL each time (~1-3 s). For instant repeat queries,
52
+ materialize a snapshot once and pass `--fast` (`-F`):
53
+
54
+ ```bash
55
+ ccq cache build # ~6 s, writes a ~100 MB snapshot to ~/.cache/ccq
56
+ ccq -F cost --by model # now ~0.1 s
57
+ ccq cache status # shows STALE once transcripts change; rebuild to refresh
58
+ ```
59
+
60
+ The snapshot lives under `$XDG_CACHE_HOME` (never in `~/.claude`), is opened
61
+ **read-only** at the engine level, and `--fast` builds it automatically on first use.
62
+
63
+ ## Web viewer
64
+
65
+ ```bash
66
+ ccq -F serve # http://127.0.0.1:8787 (Ctrl-C to stop)
67
+ ```
68
+
69
+ A dashboard (cost by model, tools, errors, subagents, priciest sessions) plus a SQL
70
+ box that runs the same read-only-guarded queries. **Drill down:** click a project
71
+ chip to filter to that project, or a session id to see its full decision timeline.
72
+ Standard-library `http.server`, no extra dependencies, binds to localhost only.
73
+
74
+ ## The query surface (`ccq sql`)
75
+
76
+ `sql` exposes these views — compose your own:
77
+
78
+ - **`sessions`** — one row per session: project, branch, span, `messages`, `models`, tokens, `cost_usd`.
79
+ - **`message_usage`** — one row per assistant turn: token breakdown + `cost_usd`.
80
+ - **`tool_calls`** — one row per tool invocation: `tool_name`, `tool_input` (JSON).
81
+ - **`errors`** — API error events: `status`, project, session, model.
82
+ - **`agents`** / **`agent_results`** — subagent dispatches joined to their `subagent_tokens`.
83
+ - **`prompts`** — searchable typed prompts + session titles.
84
+ - **`events`** — the raw per-line view everything else is built on.
85
+ - **`model_pricing`** — the per-model rate table used for costing.
86
+
87
+ ```bash
88
+ ccq sql "SELECT project, round(sum(cost_usd),2) usd
89
+ FROM message_usage WHERE ts >= DATE '2026-06-01'
90
+ GROUP BY 1 ORDER BY usd DESC"
91
+ ```
92
+
93
+ `sql` accepts a **single read-only statement** (SELECT/WITH/EXPLAIN/…). Writes,
94
+ `ATTACH`, `COPY`, `INSTALL`, and multi-statement input are refused. Tip: DuckDB
95
+ reserves words like `day`, `first`, `last` — quote them if used as aliases (`AS "day"`).
96
+
97
+ ## How it works
98
+
99
+ `read_ndjson_objects('~/.claude/projects/*/*.jsonl')` loads each line as an opaque
100
+ `JSON` value (zero schema inference — the records are heterogeneous), and SQL views
101
+ extract the entities. Two things the transcripts taught us are baked in:
102
+
103
+ - Numeric fields use `TRY_CAST` (heterogeneous lines otherwise break a hard cast).
104
+ - Token-casting views read from a type-filtered subquery so the optimizer can't
105
+ reorder a cast ahead of the `type = 'assistant'` filter.
106
+
107
+ ## Cost is estimated, and main-loop only
108
+
109
+ Transcripts store **token counts, not dollars**. `ccq` prices them with published
110
+ per-million-token rates (`src/ccq/pricing.py`) and the standard cache multipliers
111
+ (cache write 1.25×, cache read 0.10×). Two honest caveats:
112
+
113
+ 1. **Estimates, not invoices** — unknown/`<synthetic>` models price to `$0`.
114
+ 2. **Main-loop only** — a subagent's spend is **not** in the transcript. The only
115
+ signal that survives is `toolUseResult.totalTokens` (no input/output split, so it
116
+ can't be priced). `ccq agents` surfaces those token totals **separately**; they
117
+ are never folded into a dollar figure.
118
+
119
+ ## Develop
120
+
121
+ ```bash
122
+ uv run pytest # tests over synthetic fixtures
123
+ uv run ruff check . && uv run ruff format . # lint + format
124
+ uv run ty check src/ # type check
125
+ ```
126
+
127
+ Read-only on `~/.claude/projects` by contract — the test suite uses synthetic
128
+ fixtures and never reads your real history.
@@ -0,0 +1,63 @@
1
+ [project]
2
+ name = "ccq"
3
+ version = "0.1.0"
4
+ description = "Query your own Claude Code agent history with DuckDB, read-only, straight over the JSONL transcripts."
5
+ readme = "README.md"
6
+ authors = [{ name = "saagpatel" }]
7
+ requires-python = ">=3.12"
8
+ license = "MIT"
9
+ license-files = ["LICENSE"]
10
+ keywords = ["claude-code", "duckdb", "cli", "jsonl", "observability", "agent-history"]
11
+ classifiers = [
12
+ "Development Status :: 4 - Beta",
13
+ "Environment :: Console",
14
+ "Intended Audience :: Developers",
15
+ "Operating System :: OS Independent",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Topic :: Utilities",
18
+ ]
19
+ dependencies = ["duckdb>=1.1.0", "click>=8.1.0"]
20
+
21
+ [project.urls]
22
+ Homepage = "https://github.com/saagpatel/ccq"
23
+ Repository = "https://github.com/saagpatel/ccq"
24
+ Issues = "https://github.com/saagpatel/ccq/issues"
25
+
26
+ [project.scripts]
27
+ ccq = "ccq.cli:main"
28
+
29
+ [dependency-groups]
30
+ dev = [{ include-group = "lint" }, { include-group = "test" }]
31
+ lint = ["ruff", "ty"]
32
+ test = ["pytest", "pytest-cov"]
33
+
34
+ [build-system]
35
+ requires = ["uv_build>=0.11.13,<0.12.0"]
36
+ build-backend = "uv_build"
37
+
38
+ [tool.ruff]
39
+ line-length = 100
40
+ target-version = "py312"
41
+
42
+ [tool.ruff.lint]
43
+ select = ["ALL"]
44
+ ignore = [
45
+ "D", # docstring rules - not enforcing full pydocstyle
46
+ "COM812", # trailing-comma conflict with formatter
47
+ "ISC001", # implicit-str-concat conflict with formatter
48
+ "S608", # SQL "injection" - SQL is internal; user SQL runs in a sealed read-only conn
49
+ "PLR0913", # too many arguments - CLI commands legitimately take several
50
+ ]
51
+
52
+ [tool.ruff.lint.per-file-ignores]
53
+ "tests/*" = ["S101", "PLR2004", "INP001", "ERA001", "SLF001", "DTZ"] # asserts, magic vals, no __init__, comments, test internals, naive fixture datetimes
54
+ "src/ccq/cli.py" = ["FBT001"] # Click maps --flags to bool params
55
+ "src/ccq/db.py" = ["E501"] # embedded SQL reads better unwrapped
56
+ "src/ccq/server.py" = ["E501"] # embedded HTML/CSS reads better unwrapped
57
+
58
+ [tool.pytest.ini_options]
59
+ addopts = ["--cov=ccq", "--cov-report=term-missing"]
60
+ testpaths = ["tests"]
61
+
62
+ [tool.ty.environment]
63
+ python-version = "3.12"
@@ -0,0 +1,3 @@
1
+ """ccq - query your own Claude Code agent history, read-only over the JSONL transcripts."""
2
+
3
+ __version__ = "0.1.0"