ckforensics 0.2.1 → 0.2.3

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.
@@ -0,0 +1,206 @@
1
+ ---
2
+ name: ck:forensics
3
+ description: "Forensic analysis of Claude Code sessions — token cost, context map, audit manifest, skill recommendations. Use when user asks 'what did Claude touch', 'where did my tokens go', 'how much did this session cost', 'show last session', 'what skill should I have used', or wants post-hoc review of CC work."
4
+ category: dev-tools
5
+ keywords: [claude-code, audit, forensics, observability, token-cost, context, skill-recommender, session-review]
6
+ argument-hint: "summary|sessions|audit|map|suggest|skills|ingest [args]"
7
+ metadata:
8
+ author: phong28zk
9
+ version: "0.2.1"
10
+ upstream: "https://github.com/phong28zk/ckforensics"
11
+ ---
12
+
13
+ # ck:forensics — Claude Code Session Forensics
14
+
15
+ Read-only post-hoc analysis of `~/.claude/projects/**/*.jsonl` transcripts. Surfaces:
16
+ - **What was burned:** tokens, $, time, by tool/skill/file
17
+ - **What changed:** files touched, diff, reasoning trail, subagent attribution
18
+ - **What lives in context:** heatmap of items by category (tool_result, message, ...)
19
+ - **What you missed:** skills that would have replaced repeated manual sequences
20
+
21
+ Powered by the `ckforensics` CLI (npm `ckforensics@^0.2.1`). Local-only, no telemetry.
22
+
23
+ ---
24
+
25
+ ## Default (No Arguments)
26
+
27
+ If invoked without arguments, use `AskUserQuestion` to present operations:
28
+
29
+ | Operation | Description |
30
+ |-----------|-------------|
31
+ | `summary` | Token + cost rollup (last 7d default) |
32
+ | `sessions` | List recent sessions with cost/duration |
33
+ | `audit` | Per-session change manifest (files, diff, reasoning) |
34
+ | `map` | Context-window heatmap (what eats tokens?) |
35
+ | `suggest` | Skills that would have helped (pattern detection) |
36
+ | `skills` | List/search indexed skills with usage stats |
37
+ | `ingest` | Refresh DB from `~/.claude/projects/` |
38
+
39
+ Present via `AskUserQuestion` with header "Forensics" and question "Which analysis?".
40
+
41
+ ---
42
+
43
+ ## Installation Check
44
+
45
+ Before running any command, ensure CLI is installed:
46
+
47
+ ```bash
48
+ command -v ckforensics >/dev/null || {
49
+ echo "ckforensics not installed. Install with: npm i -g ckforensics"
50
+ exit 1
51
+ }
52
+ ```
53
+
54
+ If missing, ask user to install before proceeding.
55
+
56
+ ---
57
+
58
+ ## Workflows
59
+
60
+ | Workflow | Reference |
61
+ |----------|-----------|
62
+ | End-of-day session review | `references/workflow-eod.md` |
63
+ | Pre-commit audit | `references/workflow-pre-commit.md` |
64
+ | Weekly cost retro | `references/workflow-weekly-retro.md` |
65
+ | Command reference | `references/commands.md` |
66
+ | Output interpretation | `references/interpretation.md` |
67
+
68
+ ---
69
+
70
+ ## Core Commands
71
+
72
+ ### `summary [--days N]`
73
+
74
+ Token/cost rollup. Default 7 days.
75
+
76
+ ```bash
77
+ ckforensics summary # last 7 days
78
+ ckforensics summary --days 1 # today
79
+ ckforensics summary --days 30 # this month
80
+ ckforensics summary --json # for piping to jq
81
+ ```
82
+
83
+ **Cost interpretation:** API-rate equivalent. Subscription users (Pro/Max) pay flat fee — treat as "value extracted", not actual bill. See `references/interpretation.md`.
84
+
85
+ ### `audit [--last|<session-id>] [--out FILE]`
86
+
87
+ Per-session change manifest:
88
+ - Header (model, duration, cost, total events)
89
+ - Files changed (with chronological edits + reasoning quotes)
90
+ - Subagent dispatches + recursive cost breakdown
91
+ - Reasoning correlator: each tool call linked to preceding assistant text
92
+
93
+ ```bash
94
+ ckforensics audit --last # most recent session
95
+ ckforensics audit <session-id> --out review.md # for PR review
96
+ ckforensics audit --last --format json | jq # script-friendly
97
+ ```
98
+
99
+ ### `map [--last|<session-id>] [--top N]`
100
+
101
+ Context-window heatmap. Shows what categories eat the most tokens:
102
+ - `tool:Bash` → shell output
103
+ - `tool:Read` / `tool:Edit` → file ops
104
+ - `assistant` / `user` → messages
105
+ - `unknown` → unattributable
106
+
107
+ Use `--simulate-compact` to project what survives next auto-compact.
108
+
109
+ ```bash
110
+ ckforensics map --last --top 20
111
+ ckforensics map --simulate-compact --target-pct 50
112
+ ```
113
+
114
+ ### `suggest [--session ID|--last|--days N] [--min-confidence 70]`
115
+
116
+ Skill recommendations: detects repeated tool patterns and matches against `~/.claude/skills/` catalog. Suggests skills that would have replaced manual work.
117
+
118
+ ```bash
119
+ ckforensics suggest --last # for most recent session
120
+ ckforensics suggest --days 7 --min-confidence 30 # weekly retro
121
+ ```
122
+
123
+ ### `sessions [--project SLUG] [--limit N]`
124
+
125
+ List recent sessions with cost/duration. Filter by project.
126
+
127
+ ```bash
128
+ ckforensics sessions --limit 10
129
+ ckforensics sessions --project ckforensics --limit 50
130
+ ```
131
+
132
+ ### `skills [--unused|--used] [--search QUERY] [--refresh]`
133
+
134
+ List indexed skills. `--unused` shows skills you have but never invoked. Discoverability tool.
135
+
136
+ ```bash
137
+ ckforensics skills --refresh # re-scan ~/.claude/skills/
138
+ ckforensics skills --unused | head # what am I missing?
139
+ ```
140
+
141
+ ### `ingest`
142
+
143
+ Refresh DB from `~/.claude/projects/`. Incremental — only new jsonl content.
144
+
145
+ ```bash
146
+ ckforensics ingest # one-shot
147
+ ckforensics ingest --watch # poll every 5s
148
+ ```
149
+
150
+ ---
151
+
152
+ ## When to Use This Skill
153
+
154
+ **After CC session:** Run `audit --last` to review what Claude changed.
155
+
156
+ **Cost review:** Run `summary` to see token burn vs subscription value.
157
+
158
+ **Habit improvement:** Run `suggest --days 7` weekly to find skill opportunities.
159
+
160
+ **Context optimization:** Run `map --last` when session hits compaction wall — see what eats tokens.
161
+
162
+ **Pre-commit:** Run `audit --last --out review.md` then `redact review.md --in-place` before sharing.
163
+
164
+ ---
165
+
166
+ ## Output Interpretation
167
+
168
+ | Pattern | Meaning |
169
+ |---------|---------|
170
+ | `tool:Bash` >40% of map | Heavy shell output; consider piping to `tail`/`head` |
171
+ | `tool:Read` repeats on same dir | `/ck:scout` candidate |
172
+ | Subagent cost > main cost | Runaway subagent — review prompt scope |
173
+ | Cost in red (>$10) | High-value session; worth saving manifest for retro |
174
+ | Suggest confidence <50% | Probably noise; only act on ≥70% |
175
+
176
+ See `references/interpretation.md` for full guide.
177
+
178
+ ---
179
+
180
+ ## Important Notes
181
+
182
+ - **All operations are read-only.** Never modifies `~/.claude/projects/`.
183
+ - **Cost is API-rate estimate** (Nov 2025 Anthropic pricing); subscription users see flat fee.
184
+ - **±20% attribution margin** on context map (heuristic-based).
185
+ - **Cache local at** `~/.local/share/ckforensics/store.db` (mode 0600).
186
+ - **Logs at** `~/.local/state/ckforensics/logs/` (Linux), `~/Library/Logs/ckforensics/` (macOS).
187
+
188
+ ## Token Efficiency
189
+
190
+ - Activate `ck:context-engineering` skill if running `audit` or `map` on very long sessions (output can be 100k+ tokens of markdown — pipe to file).
191
+ - Use `--json` for downstream tools; avoids markdown formatting overhead.
192
+ - For routine ingest, cron handles it: `0 * * * * ckforensics ingest >> ~/.local/state/ckforensics/logs/ingest.log 2>&1`.
193
+
194
+ **Sacrifice grammar for concision when reporting findings to user.**
195
+
196
+ ---
197
+
198
+ ## Quick Start (User's First Run)
199
+
200
+ ```bash
201
+ npm i -g ckforensics # install
202
+ ckforensics doctor # verify
203
+ ckforensics ingest # populate DB (~20s for 1000+ jsonl)
204
+ ckforensics summary # see weekly totals
205
+ ckforensics audit --last | head -50 # review last session
206
+ ```
@@ -0,0 +1,108 @@
1
+ # ck:forensics — Command Reference
2
+
3
+ Quick reference for every `ckforensics` subcommand exposed via `/ck:forensics`.
4
+
5
+ ## Global flags
6
+
7
+ | Flag | Default | Description |
8
+ |------|---------|-------------|
9
+ | `--db <path>` | XDG data dir | Override SQLite path |
10
+ | `--no-color` | off | Disable ANSI |
11
+ | `-v, --verbose` | off | Info-level logging to stderr |
12
+ | `--debug` | off | Debug-level logging |
13
+ | `--log-dir <path>` | XDG state dir | Override log dir |
14
+ | `--json` | off | Force JSON output globally |
15
+
16
+ ## Subcommands
17
+
18
+ ### `summary [--days N] [--format text|md|json]`
19
+
20
+ Aggregate token/cost/files across a rolling window.
21
+
22
+ **Output fields:**
23
+ - `sessionCount`
24
+ - `totalInputTokens`, `totalOutputTokens`, `totalCacheRead`, `totalCacheCreate`
25
+ - `estimatedCostUsd` (API-rate equivalent)
26
+ - `filesTouched`, `editOps`
27
+ - `oldestSession`, `newestSession`
28
+
29
+ ### `sessions [--project SLUG] [--limit N] [--format text|md|csv|json]`
30
+
31
+ List recent sessions ordered by `started_at DESC`.
32
+
33
+ **Columns:** ID, Project, Started, Model, Events, Cost, Duration
34
+
35
+ Cost color-coded: red >$10, yellow $1-10, green <$1, dim — for null.
36
+
37
+ ### `audit [<session-id>|--last] [--out FILE] [--format md|json]`
38
+
39
+ Per-session change manifest.
40
+
41
+ **Sections:**
42
+ 1. Header (session ID, project, model, duration, cost, total events)
43
+ 2. Summary (files changed, lines +/-, edit ops, tokens, cache read)
44
+ 3. File Changes (chronological edits, reasoning quotes, unified diff)
45
+ 4. Subagent Dispatches (each Agent() / Task() with input + duration)
46
+ 5. Subagent Cost Breakdown (nested table with tokens + cost per agent)
47
+
48
+ Exit codes: 0 success, 3 session not found.
49
+
50
+ ### `map [<session-id>|--last] [--top N=20] [--simulate-compact] [--target-pct N=50]`
51
+
52
+ Context window heatmap by category.
53
+
54
+ **Categories:** `tool:<Name>`, `assistant`, `user`, `system_prompt`, `memory`, `skill_load`, `unknown`
55
+
56
+ Each row: ASCII bar + percentage + token count + item count.
57
+
58
+ **`--simulate-compact`:** projects which items survive next auto-compact based on documented heuristic.
59
+
60
+ **Sub-commands:**
61
+ - `ckforensics map --save NAME` — persist snapshot
62
+ - `ckforensics map list` — list saved snapshots
63
+ - `ckforensics map diff <A> <B>` — token movement between snapshots
64
+ - `ckforensics map --pin ITEM_ID --emit-manifest [FILE]` — pinned items → paste-ready markdown
65
+
66
+ ### `suggest [<session-id>|--last|--days N=7] [--min-confidence N=70] [--top N=3] [--format text|md|json]`
67
+
68
+ Detect repeated tool patterns and recommend skills.
69
+
70
+ **Patterns detected:**
71
+ - `read-fanout`: ≥5 Reads within 3 adjacent turns on same dir
72
+ - `test-loop`: ≥3 Bash test runs
73
+ - `manual-diff-cycle`: read→edit→read ≥2 cycles
74
+ - `grep-walk`: ≥4 Grep+Read pairs
75
+ - `subagent-skip`: ≥20 main-thread tool calls, no Agent/Task
76
+
77
+ **Output per rec:** invocation hint (`/ck:scout`), confidence %, est savings (tokens + USD), evidence turns.
78
+
79
+ ### `skills [--unused|--used] [--search QUERY] [--refresh] [--format text|md|csv|json]`
80
+
81
+ List indexed skills from `~/.claude/skills/`.
82
+
83
+ - `--refresh` — re-scan SKILL.md frontmatter
84
+ - `--unused` — show skills you've never invoked
85
+ - `--used` — show skills you've activated, with usage count
86
+ - `--search "pattern"` — keyword search
87
+
88
+ ### `ingest [--watch]`
89
+
90
+ Parse `~/.claude/projects/**/*.jsonl` → SQLite. Idempotent + incremental.
91
+
92
+ - `--watch` polls every 5s (for cron alternative)
93
+
94
+ ### `redact <file> [--in-place] [--force]`
95
+
96
+ Apply 9 redaction rules (sk-ant, GH tokens, AWS, JWT, etc.) to a markdown/text file. Use before sharing audit exports.
97
+
98
+ ### `export <view> --format md|json|csv [--out FILE]`
99
+
100
+ Pipe-friendly export: `summary`, `sessions`, `audit`.
101
+
102
+ ### `doctor`
103
+
104
+ Health check: DB exists + version, JSONL dir readable, last ingest mtime, log dir writeable, Bun version.
105
+
106
+ ### `path`
107
+
108
+ Print resolved paths (DB, data dir, JSONL source, log dir, config dir).
@@ -0,0 +1,81 @@
1
+ # ck:forensics — Output Interpretation Guide
2
+
3
+ How to read what ckforensics tells you, and when to act on it.
4
+
5
+ ## Cost interpretation
6
+
7
+ | Display | Meaning |
8
+ |---------|---------|
9
+ | `$X.XX` (green) | <$1 — typical small session |
10
+ | `$X.XX` (yellow) | $1-10 — substantive work |
11
+ | `$X.XX` (red) | >$10 — high-value session, worth saving manifest |
12
+ | `unknown` / `—` | Cost not estimable (missing model in DB, pre-pricing-fix) |
13
+ | `*` footnote | API-rate equivalent, not actual subscription bill |
14
+
15
+ **Two cost numbers compared:**
16
+ - ckforensics `Estimated Cost`: token count × Anthropic published rates
17
+ - CC live statusline: real-time `cost.total_cost_usd` from CC's internal calc
18
+
19
+ Discrepancy expected (CC may exclude some cache pricing). Within 30% = normal.
20
+
21
+ **For subscription users:** the cost number = "value extracted from your $X/mo plan", not a bill.
22
+
23
+ ## Map heatmap thresholds
24
+
25
+ | Pattern | Diagnostic | Action |
26
+ |---------|-----------|--------|
27
+ | `tool:Bash` >40% | Heavy shell output | Pipe to `head`/`tail`, redirect logs, or limit verbose flags |
28
+ | `tool:Read` >30% | Excessive file reads | Use `/ck:scout` for batched discovery |
29
+ | `tool:Edit` >30% | Lots of edits | Normal for code-heavy session; check for thrashing |
30
+ | `assistant` >40% | Very long replies | Verbose mode, summarisation overhead |
31
+ | `unknown` >10% | Attribution failure | Schema drift; report to ckforensics issues |
32
+
33
+ ## Suggest confidence brackets
34
+
35
+ | Confidence | Meaning | Action |
36
+ |------------|---------|--------|
37
+ | 80-100% | Strong signal, multi-pattern match | Try the skill next session |
38
+ | 60-80% | Plausible, single pattern | Worth reading description |
39
+ | 40-60% | Weak — likely keyword coincidence | Skip unless desperate |
40
+ | <40% | Noise | Ignore |
41
+
42
+ Default threshold = 70. Lower with `--min-confidence 30` if seeing no recs.
43
+
44
+ ## Audit manifest sections
45
+
46
+ ### Files changed
47
+
48
+ Each file shows chronological edits with reasoning quote. **Read the reasoning** — it's the assistant's intent text before the tool call, not post-hoc explanation. Useful for:
49
+ - Understanding *why* an edit was made
50
+ - Catching scope creep (intent vs action mismatch)
51
+ - Composing PR descriptions (reasoning often is the PR body)
52
+
53
+ ### Subagent Cost Breakdown
54
+
55
+ Nested table. Top-level rows = direct Agent()/Task() calls from main thread. Indented rows = nested (subagent inside subagent).
56
+
57
+ **Red flags:**
58
+ - Single subagent with >$5 cost in <10 tool calls = runaway
59
+ - "open" duration → subagent still running (session paused?)
60
+ - Many small subagents (≤2 calls each) = excessive fanout
61
+
62
+ ### Reasoning correlator
63
+
64
+ Each tool call gets a "Reasoning:" quote. If reasoning is empty/unhelpful:
65
+ - Assistant didn't narrate (rare)
66
+ - Tool fired in middle of multi-block message (correlator picks last text block)
67
+ - Subagent invocation (reasoning belongs to parent dispatch)
68
+
69
+ ## Sessions list signals
70
+
71
+ - Same project, multiple short sessions same day → context flushing too often
72
+ - Single 10+ hour session → consider checkpointing via context map
73
+ - Cost trending up week-over-week → instrument with `summary --days N`
74
+
75
+ ## When ingest finds nothing
76
+
77
+ If `ckforensics ingest` reports 0 new events:
78
+ 1. Check `ckforensics doctor` — last ingest mtime
79
+ 2. Verify `~/.claude/projects/` has recent jsonl: `ls -lt ~/.claude/projects/*/*.jsonl | head`
80
+ 3. CC may be on different config dir (CLAUDE_CONFIG_DIR env var) — set `--db` accordingly
81
+ 4. Force re-ingest from scratch: `rm ~/.local/share/ckforensics/store.db && ckforensics ingest`
@@ -0,0 +1,56 @@
1
+ # End-of-Day Session Review Workflow
2
+
3
+ Pattern: after a substantial Claude Code session, run forensics to know what shipped, what burned, what to remember.
4
+
5
+ ## Flow
6
+
7
+ ```
8
+ 1. ckforensics ingest # refresh DB
9
+ 2. ckforensics summary --days 1 # today's totals
10
+ 3. ckforensics audit --last --out eod.md # capture manifest
11
+ 4. ckforensics suggest --last # skills that would have helped
12
+ 5. ckforensics map --last --top 15 # what ate the context
13
+ ```
14
+
15
+ ## When Claude runs this skill
16
+
17
+ User says one of:
18
+ - "wrap up this session"
19
+ - "what did I do today"
20
+ - "end of day review"
21
+ - "summary of last session"
22
+ - "did Claude do anything weird"
23
+
24
+ ## What Claude should do
25
+
26
+ 1. Run the 5 commands above (or relevant subset).
27
+ 2. **Summarise**, don't paste raw output to user. Surface:
28
+ - Total cost (API-rate) + duration
29
+ - Top 3 files changed (by lines or by importance from reasoning quotes)
30
+ - Any subagent that cost >$1 (flag for review)
31
+ - Top 1-2 skill recommendations with confidence ≥70
32
+ - Context map insight: what ate most tokens
33
+ 3. **Offer next actions:**
34
+ - "Save audit manifest as PR description?" → use `eod.md`
35
+ - "Dismiss low-value skill recs?" → `~/.config/ckforensics/dismissed.json`
36
+ - "Schedule cron for daily ingest?" → crontab snippet
37
+
38
+ ## Example response template
39
+
40
+ ```
41
+ Today's session burned $X.XX over Y hours. Modified Z files (top: A, B, C).
42
+
43
+ Notable:
44
+ - Subagent "P11 log infra" cost $28 — runaway, worth reviewing
45
+ - Skill /ck:scout would have replaced 23× Read on src/audit/* (saves ~12k tokens)
46
+ - Context map: tool:Bash 40%, tool:Edit 16% — heavy shell + editing
47
+
48
+ Manifest saved to eod.md. Want me to draft a commit message from it?
49
+ ```
50
+
51
+ ## Anti-patterns
52
+
53
+ - ❌ Paste full audit markdown (1000+ lines) to user
54
+ - ❌ Run all 5 commands when user only asked "cost today"
55
+ - ❌ Recommend skills with confidence <70 without flagging confidence
56
+ - ❌ Skip subagent cost breakdown — that's the highest-signal section
@@ -0,0 +1,63 @@
1
+ # Pre-Commit Audit Workflow
2
+
3
+ Pattern: before user runs `git commit`, generate a manifest of what Claude touched and use it as commit/PR body draft.
4
+
5
+ ## Flow
6
+
7
+ ```
8
+ 1. ckforensics ingest # ensure DB current
9
+ 2. ckforensics audit --last --out review.md # capture this session's manifest
10
+ 3. ckforensics redact review.md --in-place # strip secrets before sharing
11
+ 4. (user opens review.md, copies relevant sections to commit body)
12
+ ```
13
+
14
+ ## When Claude runs this skill
15
+
16
+ User says one of:
17
+ - "ready to commit"
18
+ - "draft a commit message from this session"
19
+ - "what should the PR description say"
20
+ - "review what I just did before committing"
21
+
22
+ ## What Claude should do
23
+
24
+ 1. Run `audit --last` to get the manifest.
25
+ 2. Pipe through `redact` (always, never skip — secrets risk).
26
+ 3. Extract from manifest:
27
+ - **Files changed** + line counts (for `git diff --stat` equivalent)
28
+ - **Reasoning quotes** per file (often makes the PR body)
29
+ - **Subagent contributions** (mention if subagents did significant work)
30
+ 4. **Draft conventional commit**:
31
+ ```
32
+ <type>(<scope>): <subject>
33
+
34
+ <body — TLDR of what changed and why, from reasoning>
35
+
36
+ <body — files affected, key decisions>
37
+ ```
38
+ 5. **Surface anything suspicious:**
39
+ - Files touched in unexpected directories
40
+ - Reasoning that doesn't match the actions (intent drift)
41
+ - Subagents with high cost (worth mentioning in PR)
42
+
43
+ ## Integration with ck:git
44
+
45
+ After draft, hand off to `/ck:git cm` for execution:
46
+ ```
47
+ ckforensics audit --last --out review.md
48
+ ckforensics redact review.md --in-place
49
+ # Claude reads review.md, drafts commit message
50
+ # Hand to /ck:git cm — user reviews + executes
51
+ ```
52
+
53
+ Or pipe directly (v0.5 phase 12 will support this):
54
+ ```
55
+ ckforensics commit --phase last | ck:git cm --message-stdin
56
+ ```
57
+
58
+ ## Anti-patterns
59
+
60
+ - ❌ Skip redaction — manifests can contain edited file contents = secrets risk
61
+ - ❌ Paste raw manifest as commit body (too long, unstructured)
62
+ - ❌ Auto-commit — always show draft, let user approve via /ck:git
63
+ - ❌ Forget to mention subagents — they did work that deserves credit/audit
@@ -0,0 +1,72 @@
1
+ # Weekly Retro Workflow
2
+
3
+ Pattern: every Sunday (or Monday morning), look back at the week — cost trends, skill discovery, runaway sessions.
4
+
5
+ ## Flow
6
+
7
+ ```
8
+ 1. ckforensics ingest # ensure DB current
9
+ 2. ckforensics summary --days 7 # weekly rollup
10
+ 3. ckforensics sessions --limit 20 # week's sessions
11
+ 4. ckforensics suggest --days 7 --min-confidence 50 # patterns to fix
12
+ 5. ckforensics skills --unused | head -20 # discovery
13
+ ```
14
+
15
+ ## When Claude runs this skill
16
+
17
+ User says one of:
18
+ - "weekly retro"
19
+ - "what did I spend on Claude Code this week"
20
+ - "any patterns I should fix in my workflow"
21
+ - "show me sessions ranked by cost"
22
+ - "what skills should I learn"
23
+
24
+ ## What Claude should do
25
+
26
+ 1. **Summary numbers first** — cost, session count, vs previous week if possible (`--days 14` then compute delta).
27
+ 2. **Top 5 most expensive sessions** with project + duration. Flag anything over $50.
28
+ 3. **Recurring patterns** from `suggest --days 7`:
29
+ - List top 3 skill recommendations
30
+ - Group by pattern type (e.g. "read-fanout detected 4× this week")
31
+ 4. **Skill discovery**:
32
+ - From `skills --unused`, pick 3-5 that match user's project work (filter by keyword overlap with recent session topics)
33
+ - Format as "consider trying: /ck:xyz — <description>"
34
+ 5. **Anomaly check**:
35
+ - Any single session >$100? Flag for review.
36
+ - Any subagent that ran >1h? Worth investigating.
37
+ 6. **Optional: write retro to docs/**:
38
+ - `docs/retros/YYYY-MM-DD-week-N.md`
39
+ - Auto-fill summary + recommendations sections
40
+ - User edits notes manually after
41
+
42
+ ## Example response template
43
+
44
+ ```
45
+ Weekly retro (Mon 2026-05-04 → Sun 2026-05-10):
46
+
47
+ 📊 Totals: $733 API-equivalent across 19 sessions, 967M tokens
48
+ vs prev week: +180% (last week $260 / 12 sessions)
49
+
50
+ 🔥 Top sessions:
51
+ 1. project-noname 18h56m $1102 (Tue, 4082 events)
52
+ 2. MQL5 2h21m $29 (Tue)
53
+ 3. career-launchpad 19h $32 (Wed)
54
+
55
+ 📚 Skill recommendations:
56
+ - /ck:scout (4× read-fanout patterns this week — 50k tok save)
57
+ - /ck:test (3× test-loop patterns — 15k tok save)
58
+
59
+ 💡 Try these unused skills:
60
+ - /ck:retro — auto-generate this report (would replace this manual flow)
61
+ - /ck:journal — capture session reflections automatically
62
+ - /ck:debug — systematic debugging when stuck
63
+
64
+ ⚠️ Notable: session #1 was 18h Opus — consider checkpointing context mid-way.
65
+ ```
66
+
67
+ ## Anti-patterns
68
+
69
+ - ❌ Compare cost to subscription price as if it's the bill — it's API-equivalent, frame as "value extracted"
70
+ - ❌ Recommend ALL unused skills (150+) — filter to relevant per project context
71
+ - ❌ Skip anomaly check — outliers are the highest-signal items
72
+ - ❌ Long bullet lists — keep tight, 3-5 items per category max
@@ -0,0 +1,165 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ session-overview.py — One-shot session report for ck:forensics skill.
4
+
5
+ Runs multiple `ckforensics` CLI commands and stitches a single JSON
6
+ report. Saves Claude from chaining 4-5 Bash calls when answering
7
+ "summarize this session" prompts.
8
+
9
+ Usage:
10
+ python3 session-overview.py [--session-id ID] [--days N]
11
+ python3 session-overview.py --last # default — most recent session
12
+
13
+ Output: JSON on stdout with shape:
14
+ {
15
+ "schema": "ck-forensics-overview-v1",
16
+ "generatedAt": "ISO8601",
17
+ "scope": {"sessionId": "...", "days": 7, "lastOnly": true},
18
+ "summary": { ... }, # `ckforensics summary --json` data
19
+ "session": { ... }, # one row from `ckforensics sessions --json`
20
+ "audit": { ... }, # `ckforensics audit --json` (manifest)
21
+ "suggest": [ ... ], # top recs from `ckforensics suggest --json`
22
+ "map": { ... } # context map heatmap
23
+ }
24
+
25
+ Errors are reported as {"schema": "error", "error": "..."} with exit 1.
26
+
27
+ Stdlib only — no third-party deps required. Compatible with Python 3.8+.
28
+ """
29
+
30
+ import argparse
31
+ import json
32
+ import shutil
33
+ import subprocess
34
+ import sys
35
+ from datetime import datetime, timezone
36
+
37
+
38
+ def check_cli_installed() -> None:
39
+ """Verify ckforensics CLI is on PATH; exit 1 with clear error if not."""
40
+ if shutil.which("ckforensics") is None:
41
+ emit_error(
42
+ "ckforensics CLI not installed. "
43
+ "Install with: npm i -g ckforensics"
44
+ )
45
+ sys.exit(1)
46
+
47
+
48
+ def run_cli(args: list) -> dict:
49
+ """
50
+ Run `ckforensics <args>` with --json and return parsed output.
51
+ Raises CalledProcessError on non-zero exit (caller decides whether to ignore).
52
+ """
53
+ cmd = ["ckforensics", *args, "--json"]
54
+ result = subprocess.run(
55
+ cmd,
56
+ capture_output=True,
57
+ text=True,
58
+ check=False,
59
+ timeout=30,
60
+ )
61
+ if result.returncode != 0:
62
+ # Many subcommands exit 3 when no data — return empty rather than fail
63
+ if result.returncode == 3:
64
+ return {}
65
+ raise subprocess.CalledProcessError(
66
+ result.returncode, cmd, result.stdout, result.stderr
67
+ )
68
+ return json.loads(result.stdout) if result.stdout.strip() else {}
69
+
70
+
71
+ def emit_error(msg: str) -> None:
72
+ """Write error envelope to stdout."""
73
+ print(json.dumps({"schema": "error", "error": msg}), flush=True)
74
+
75
+
76
+ def collect_overview(session_id: str | None, days: int, last: bool) -> dict:
77
+ """Gather all sections; failures in individual sections become null."""
78
+ overview = {
79
+ "schema": "ck-forensics-overview-v1",
80
+ "generatedAt": datetime.now(timezone.utc).isoformat(),
81
+ "scope": {"sessionId": session_id, "days": days, "lastOnly": last},
82
+ "summary": None,
83
+ "session": None,
84
+ "audit": None,
85
+ "suggest": None,
86
+ "map": None,
87
+ }
88
+
89
+ # 1. Summary — rolling window
90
+ try:
91
+ overview["summary"] = run_cli(["summary", "--days", str(days)]).get("data")
92
+ except Exception as e:
93
+ overview["summary"] = {"error": str(e)}
94
+
95
+ # 2. Session metadata — pick from list or by id
96
+ try:
97
+ sessions_envelope = run_cli(["sessions", "--limit", "1"])
98
+ sessions = sessions_envelope.get("data", [])
99
+ if session_id:
100
+ # Filter to specific session if requested
101
+ sessions = [s for s in sessions if s.get("id") == session_id]
102
+ overview["session"] = sessions[0] if sessions else None
103
+ except Exception as e:
104
+ overview["session"] = {"error": str(e)}
105
+
106
+ # 3. Audit manifest — uses --last unless explicit id given
107
+ audit_args = ["audit", "--last"] if last or not session_id else ["audit", session_id]
108
+ try:
109
+ overview["audit"] = run_cli(audit_args)
110
+ except Exception as e:
111
+ overview["audit"] = {"error": str(e)}
112
+
113
+ # 4. Suggest — same scope as audit
114
+ suggest_args = ["suggest", "--last", "--min-confidence", "30", "--top", "3"]
115
+ if session_id and not last:
116
+ suggest_args = ["suggest", "--session", session_id, "--min-confidence", "30", "--top", "3"]
117
+ try:
118
+ overview["suggest"] = run_cli(suggest_args).get("data", [])
119
+ except Exception as e:
120
+ overview["suggest"] = {"error": str(e)}
121
+
122
+ # 5. Map — top-10 heatmap categories
123
+ map_args = ["map", "--last", "--top", "10"]
124
+ if session_id and not last:
125
+ map_args = ["map", session_id, "--top", "10"]
126
+ try:
127
+ overview["map"] = run_cli(map_args).get("data")
128
+ except Exception as e:
129
+ overview["map"] = {"error": str(e)}
130
+
131
+ return overview
132
+
133
+
134
+ def parse_args() -> argparse.Namespace:
135
+ p = argparse.ArgumentParser(
136
+ prog="session-overview",
137
+ description="Unified session report — runs multiple ckforensics commands and merges output.",
138
+ )
139
+ p.add_argument("--session-id", help="Explicit session UUID (defaults to --last)")
140
+ p.add_argument("--days", type=int, default=7, help="Summary window in days (default 7)")
141
+ p.add_argument(
142
+ "--last",
143
+ action="store_true",
144
+ default=True,
145
+ help="Use most recent session (default behavior)",
146
+ )
147
+ return p.parse_args()
148
+
149
+
150
+ def main() -> int:
151
+ check_cli_installed()
152
+ args = parse_args()
153
+ last = args.last and not args.session_id
154
+
155
+ try:
156
+ overview = collect_overview(args.session_id, args.days, last)
157
+ print(json.dumps(overview, indent=2, default=str))
158
+ return 0
159
+ except Exception as e:
160
+ emit_error(f"unexpected error: {e}")
161
+ return 1
162
+
163
+
164
+ if __name__ == "__main__":
165
+ sys.exit(main())
package/README.md CHANGED
@@ -1,25 +1,93 @@
1
1
  # ckforensics
2
2
 
3
- **Forensic CLI for Claude Code sessions — audit, redact, export your transcripts.**
3
+ > 🔍 **Forensic CLI for Claude Code sessions**see where your tokens went, what Claude touched, and which skills you missed.
4
4
 
5
5
  [![CI](https://github.com/phong28zk/ckforensics/actions/workflows/ci.yml/badge.svg)](https://github.com/phong28zk/ckforensics/actions/workflows/ci.yml)
6
6
  [![npm version](https://img.shields.io/npm/v/ckforensics)](https://www.npmjs.com/package/ckforensics)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
8
8
  [![Bun](https://img.shields.io/badge/runtime-Bun-f472b6)](https://bun.sh)
9
+ [![ClaudeKit Skill](https://img.shields.io/badge/ClaudeKit-/ck:forensics-9333ea)](#claudekit-integration)
10
+
11
+ **One install. Two interfaces.** Standalone CLI **and** ClaudeKit `/ck:forensics` skill — bundled together.
12
+
13
+ ```bash
14
+ npm i -g ckforensics
15
+ ```
9
16
 
10
17
  ---
11
18
 
12
- ## Why ckforensics
19
+ ## What does it do?
13
20
 
14
- **Pain:**
15
- - Claude Code transcripts stored as raw JSONL — no way to summarize or audit them
16
- - Sensitive keys / tokens leak into `.jsonl` files that get committed or shared
17
- - No visibility into token usage, tool calls, or subagent orchestration patterns
21
+ After Claude Code finishes a session, ckforensics parses `~/.claude/projects/**/*.jsonl` and tells you:
18
22
 
19
- **Solution:**
20
- - Ingest all sessions into a local SQLite DB — queryable, indexed, stays on disk
21
- - Redact 9 secret patterns (API keys, AWS creds, JWTs, PEM blocks) before any export
22
- - CLI commands for summary, audit, session diff, and export — no cloud, no telemetry
23
+ ```
24
+ ╭─ ckforensics summary --days 7 ──────────────────────────────────╮
25
+ │ Sessions 19 │
26
+ │ Input tokens 69,190 │
27
+ │ Output tokens 3,088,275 │
28
+ │ Cache read 934,429,934 │
29
+ │ Total tokens 967,848,242 │
30
+ │ Estimated cost* $733.8981 ← value extracted from $100 Max │
31
+ │ Files touched 149 │
32
+ │ Edit operations 488 │
33
+ ╰──────────────────────────────────────────────────────────────────╯
34
+ ```
35
+
36
+ ```
37
+ ╭─ ckforensics map --last (where do my tokens go?) ──────────────╮
38
+ │ tool:Bash ████████ 40.5% 30,444 tok (293 calls) │
39
+ │ tool:Edit ███ 16.1% 12,396 tok (98) │
40
+ │ assistant ██ 11.9% 9,197 tok (563) │
41
+ │ tool:Read ██ 10.8% 8,327 tok (70) │
42
+ │ tool:Write ██ 9.3% 7,179 tok (42) │
43
+ │ │
44
+ │ Total: 77,204 tokens (±20% attribution margin) │
45
+ ╰──────────────────────────────────────────────────────────────────╯
46
+ ```
47
+
48
+ ```
49
+ ╭─ ckforensics suggest --last (what skills would have helped?) ──╮
50
+ │ #1 /ck:scout confidence: 85% │
51
+ │ You ran 23× Read on src/audit/* in turns 47-89 │
52
+ │ /ck:scout fans out file discovery in parallel │
53
+ │ Est. savings: 12k tokens ($0.14) │
54
+ │ │
55
+ │ #2 /ck:test confidence: 72% │
56
+ │ 8× `bun test` Bash calls in retry loop │
57
+ ╰──────────────────────────────────────────────────────────────────╯
58
+ ```
59
+
60
+ ```
61
+ ╭─ ckforensics audit --last (session change manifest) ──────────╮
62
+ │ ## Subagent Cost Breakdown │
63
+ │ │
64
+ │ │ Subagent │ Tokens │ Cost │ Tool calls │ Duration ││
65
+ │ ├────────────────────┼────────┼────────┼────────────┼──────────┤│
66
+ │ │ Agent: P11 log infra│ 28.9M │ $28.42 │ 20 │ open ││
67
+ │ │ └── nested forensics│ 28.2M │ $27.91 │ 19 │ open ││
68
+ │ │ Agent: P06 build │ 646k │ $0.61 │ 2 │ 3h0m ││
69
+ │ │ Agent: P07 ctx map │ 751k │ $0.47 │ 1 │ 12m28s ││
70
+ │ └────────────────────┴────────┴────────┴────────────┴──────────┘│
71
+ │ │
72
+ │ ↑ Identifies runaway subagents in long sessions │
73
+ ╰──────────────────────────────────────────────────────────────────╯
74
+ ```
75
+
76
+ \* API-rate equivalent (Anthropic Nov 2025 pricing). Subscription users (Pro/Max/Team) pay flat fee — treat as "value extracted from your plan", not actual billing.
77
+
78
+ ---
79
+
80
+ ## Why does this exist?
81
+
82
+ | Pain | ckforensics |
83
+ |------|-------------|
84
+ | Claude Code stores transcripts as opaque JSONL | Parses into queryable SQLite |
85
+ | You can't see what subagents cost vs the parent | Recursive cost tree per Agent()/Task() |
86
+ | You don't know which skills you skipped using | Pattern detection → ranked recommendations |
87
+ | Auto-compact is opaque, drops context invisibly | `map` shows what eats your window |
88
+ | Sensitive keys leak into committed jsonl logs | 9 built-in redaction rules |
89
+ | "How much did Claude cost me this week?" | `summary` gives token + USD totals |
90
+ | "What did Claude actually change in that 14h session?" | `audit` produces signed-off manifest |
23
91
 
24
92
  ---
25
93
 
@@ -29,7 +97,15 @@
29
97
  npm i -g ckforensics
30
98
  ```
31
99
 
32
- Or download a prebuilt binary from [Releases](https://github.com/phong28zk/ckforensics/releases):
100
+ Single command installs:
101
+ 1. **Cross-platform binary** (Linux x64/arm64, macOS Apple Silicon, Windows x64) via npm postinstall download
102
+ 2. **ClaudeKit skill** at `~/.claude/skills/ckforensics/` — auto-activates in next Claude Code session
103
+
104
+ > **Intel Mac:** build from source — `bun build --compile --target=bun-darwin-x64 src/cli/index.ts --outfile ckforensics`
105
+ >
106
+ > **Opt out of skill copy:** `CKFORENSICS_SKIP_SKILL_INSTALL=1 npm i -g ckforensics`
107
+
108
+ Or grab a binary directly:
33
109
 
34
110
  ```bash
35
111
  # Linux x64
@@ -37,116 +113,146 @@ curl -L https://github.com/phong28zk/ckforensics/releases/latest/download/ckfore
37
113
  -o /usr/local/bin/ckforensics && chmod +x /usr/local/bin/ckforensics
38
114
  ```
39
115
 
40
- Platforms: `linux-x64`, `linux-arm64`, `macos-arm64` (Apple Silicon), `windows-x64`
41
-
42
- > Intel Mac users: build from source — `bun build --compile --target=bun-darwin-x64 src/cli/index.ts --outfile ckforensics`
43
-
44
116
  ---
45
117
 
46
118
  ## Quick Start
47
119
 
48
120
  ```bash
49
- # 1. Ingest all sessions from ~/.claude/projects/
50
- ckforensics ingest
121
+ ckforensics ingest # populate DB (~20s for 1000+ jsonl)
122
+ ckforensics summary # weekly totals
123
+ ckforensics audit --last # last session manifest
124
+ ckforensics map --last --top 10 # context heatmap
125
+ ckforensics suggest --last # skill recommendations
126
+ ckforensics doctor # health check
127
+ ```
51
128
 
52
- # 2. Summarize recent sessions (default 7 days)
53
- ckforensics summary
54
- ckforensics summary --days 1 # today
55
- ckforensics summary --days 30 # month
129
+ **Recommended cron** (hourly auto-ingest):
56
130
 
57
- # 3. List recent sessions
58
- ckforensics sessions --limit 10
131
+ ```bash
132
+ (crontab -l 2>/dev/null; echo "0 * * * * $(which ckforensics) ingest >> ~/.local/state/ckforensics/logs/ingest.log 2>&1") | crontab -
133
+ ```
59
134
 
60
- # 4. Audit the most recent session (markdown manifest)
61
- ckforensics audit --last
62
- ckforensics audit <session-id> --out review.md
135
+ ---
63
136
 
64
- # 5. Redact secrets from a file before sharing
65
- ckforensics redact review.md --in-place
137
+ ## ClaudeKit integration
66
138
 
67
- # 6. Export for scripting
68
- ckforensics export summary --format json | jq
69
- ckforensics export sessions --format csv --out sessions.csv
139
+ When installed, `/ck:forensics` is available inside Claude Code:
70
140
 
71
- # 7. Health check
72
- ckforensics doctor
141
+ ```
142
+ You: "show me last session cost"
143
+ Claude: [auto-invokes /ck:forensics → reads SKILL.md → runs ckforensics audit --last]
144
+ Claude: "Last session was 18h, $1102 API-equivalent. Top files: ..."
73
145
  ```
74
146
 
75
- > DB stored at XDG-compliant path (mode `0600`):
76
- > - Linux: `~/.local/share/ckforensics/store.db`
77
- > - macOS: `~/Library/Application Support/ckforensics/store.db`
78
- > - Windows: `%APPDATA%\ckforensics\store.db`
79
- >
80
- > Nothing leaves your machine. Run `ckforensics path` to see resolved paths.
147
+ **Triggers** (skill description picks these up):
148
+ - "what did Claude touch this session"
149
+ - "show me last session cost"
150
+ - "where did my tokens go"
151
+ - "audit last session"
152
+ - "what skill should I have used"
153
+ - `/ck:forensics summary` / `/ck:forensics audit` / etc
81
154
 
82
- ### About cost numbers
155
+ The skill ships with 3 workflows:
156
+ - **`workflow-eod.md`** — end-of-day session review
157
+ - **`workflow-pre-commit.md`** — generate commit message + redact before commit
158
+ - **`workflow-weekly-retro.md`** — Sunday retrospective
83
159
 
84
- Cost shown is **API-rate equivalent** computed from token counts × Anthropic published prices ([Nov 2025 snapshot](https://platform.claude.com/docs/en/about-claude/pricing)).
160
+ ---
85
161
 
86
- - **API users:** approximates your actual bill (±10-30% for cache-pricing edge cases)
87
- - **Subscription users (Pro / Max / Team):** flat plan fee covers this; treat the number as **"value extracted"** from your subscription
162
+ ## Storage
88
163
 
89
- Example: a 14h Opus 4.7 session showing `$166` means you'd pay ~$166 at API rates — your $100/mo Max plan covers it with positive ROI.
164
+ DB at XDG-compliant path (mode `0600`):
90
165
 
91
- ---
166
+ | OS | Path |
167
+ |----|------|
168
+ | Linux | `~/.local/share/ckforensics/store.db` |
169
+ | macOS | `~/Library/Application Support/ckforensics/store.db` |
170
+ | Windows | `%APPDATA%\ckforensics\store.db` |
92
171
 
93
- ## Screenshots
172
+ Logs (daily-rotated):
94
173
 
95
- ```
96
- [ terminal recording placeholder — see docs/demo.gif once available ]
97
- ```
174
+ | OS | Path |
175
+ |----|------|
176
+ | Linux | `~/.local/state/ckforensics/logs/` |
177
+ | macOS | `~/Library/Logs/ckforensics/` |
178
+ | Windows | `%LOCALAPPDATA%\ckforensics\Logs\` |
179
+
180
+ **Nothing leaves your machine.** No telemetry. No cloud sync. Run `ckforensics path` to see resolved paths.
98
181
 
99
182
  ---
100
183
 
101
184
  ## Feature Matrix
102
185
 
103
- | Feature | ckforensics | ccusage | Native CC |
104
- |---------|:-----------:|:-------:|:---------:|
186
+ | Feature | ckforensics | ccusage | Native CC `/usage` |
187
+ |---------|:-----------:|:-------:|:--------------------:|
105
188
  | Local SQLite storage | ✅ | ✅ | ❌ |
106
- | Version-aware cost pricing | ✅ | 🟡 | ✅ (live only) |
107
- | Token usage analytics | ✅ | | |
108
- | Secret redaction (9 rules) | ✅ | ❌ | ❌ |
189
+ | Token usage analytics | ✅ | | ✅ (live only) |
190
+ | Version-aware cost pricing | ✅ | 🟡 | |
191
+ | Subagent cost forensics (recursive) | ✅ | ❌ | ❌ |
192
+ | Context window heatmap | ✅ | ❌ | ❌ |
193
+ | Pre-compact simulation | ✅ | ❌ | ❌ |
194
+ | Skill recommendation engine | ✅ | ❌ | ❌ |
109
195
  | Session change manifest (diff + reasoning) | ✅ | ❌ | ❌ |
110
- | Subagent attribution | ✅ | ❌ | ❌ |
111
- | Markdown / JSON / CSV export | ✅ | | ❌ |
112
- | Offline / no telemetry | ✅ | ✅ | ✅ |
196
+ | Secret redaction (9 rules) | ✅ | ❌ | ❌ |
197
+ | Markdown / JSON / CSV export | ✅ | 🟡 | ❌ |
198
+ | Offline, zero telemetry | ✅ | ✅ | ✅ |
113
199
  | Cross-platform binaries | ✅ | ❌ | ✅ |
200
+ | ClaudeKit skill bundled | ✅ | ❌ | ❌ |
114
201
 
115
202
  ---
116
203
 
117
204
  ## Commands
118
205
 
119
- | Command | Description |
120
- |---------|-------------|
121
- | `ingest` | Parse JSONL files → SQLite |
122
- | `summary` | Token + cost summary for a time range |
123
- | `audit` | Detect secrets / anomalies in a session |
124
- | `export` | Output session as Markdown or JSON |
125
- | `redact` | Strip secrets from JSONL in-place |
126
- | `sessions` | List sessions with metadata |
127
- | `path` | Show DB path and stats |
128
- | `doctor` | Verify DB integrity and schema version |
206
+ | Command | Purpose |
207
+ |---------|---------|
208
+ | `ingest` | Parse JSONL → SQLite (idempotent + incremental, optional `--watch`) |
209
+ | `summary` | Token + cost rollup over rolling window (default 7d) |
210
+ | `sessions` | List sessions with cost, duration, model |
211
+ | `audit` | Per-session manifest: diffs + reasoning + subagent breakdown |
212
+ | `map` | Context-window heatmap by category, snapshot/diff/pin |
213
+ | `suggest` | Skill recommendations from detected tool patterns |
214
+ | `skills` | Browse ClaudeKit skill catalog with usage stats |
215
+ | `export` | Pipe-friendly export (markdown, JSON, CSV) |
216
+ | `redact` | Strip 9 secret patterns from a file |
217
+ | `doctor` | Health check (DB, paths, schema version, log activity) |
218
+ | `path` | Show all resolved file system paths |
219
+
220
+ Run `ckforensics <cmd> --help` for flags.
129
221
 
130
222
  ---
131
223
 
132
- ## Architecture
133
-
134
- See [docs/architecture.md](docs/architecture.md) — module overview and data-flow diagram.
224
+ ## About cost numbers
135
225
 
136
- ## Threat Model
226
+ Cost is **API-rate equivalent** computed from token counts × Anthropic's published prices ([Nov 2025 snapshot](https://platform.claude.com/docs/en/about-claude/pricing)).
137
227
 
138
- See [docs/threat-model.md](docs/threat-model.md) privacy stance, redaction guarantees, and known gaps.
228
+ - **API users:** approximates your actual bill (±10-30% for cache-pricing edge cases)
229
+ - **Subscription users (Pro / Max / Team):** flat plan fee covers this — treat the number as **"value extracted"** from your subscription
139
230
 
140
- ## Schema
231
+ Example: a 14h Opus 4.7 session showing `$166` means you'd pay ~$166 at API rates — your $100/mo Max plan covers it with positive ROI.
141
232
 
142
- See [docs/jsonl-schema-v1.md](docs/jsonl-schema-v1.md) — reverse-engineered Claude Code JSONL event types.
233
+ ---
143
234
 
144
- ## Contributing
235
+ ## Documentation
145
236
 
146
- See [CONTRIBUTING.md](CONTRIBUTING.md) dev setup, PR checklist, fixture contribution flow.
237
+ | Doc | Topic |
238
+ |-----|-------|
239
+ | [docs/architecture.md](docs/architecture.md) | Module overview, data flow |
240
+ | [docs/threat-model.md](docs/threat-model.md) | Privacy stance, redaction guarantees |
241
+ | [docs/jsonl-schema-v1.md](docs/jsonl-schema-v1.md) | Reverse-engineered JSONL event types |
242
+ | [CONTRIBUTING.md](CONTRIBUTING.md) | Dev setup, PR checklist, fixture rules |
243
+ | [ROADMAP.md](ROADMAP.md) | v0.1.x → v0.6+ feature plans |
244
+ | [CHANGELOG.md](CHANGELOG.md) | Version history |
147
245
 
148
246
  ---
149
247
 
150
248
  ## License
151
249
 
152
250
  MIT — [LICENSE](LICENSE) — Copyright (c) 2026 phong28zk
251
+
252
+ ---
253
+
254
+ ## Acknowledgements
255
+
256
+ - [ClaudeKit](https://github.com/phong28zk) ecosystem for the `/ck:*` skill pattern
257
+ - [Anthropic](https://anthropic.com) for Claude Code + the public JSONL transcript format
258
+ - [Bun](https://bun.sh) for single-binary compilation that makes cross-platform distribution painless
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ckforensics",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,6 +16,8 @@
16
16
  "files": [
17
17
  "bin/",
18
18
  "scripts/postinstall.js",
19
+ "scripts/install-claudekit-skill.js",
20
+ ".claude/skills/",
19
21
  "README.md",
20
22
  "LICENSE"
21
23
  ],
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * install-claudekit-skill.js — Install the bundled `/ck:forensics` skill into
4
+ * the user's ClaudeKit skill directory (`~/.claude/skills/ckforensics/`).
5
+ *
6
+ * Called from postinstall.js. Designed to be silent on success and never
7
+ * fail the parent install — skill is a nice-to-have, not a hard dependency.
8
+ *
9
+ * Behavior:
10
+ * - Copies `<pkg>/.claude/skills/ckforensics/` to `~/.claude/skills/ckforensics/`.
11
+ * - Skip when source dir missing (e.g. dev install without the bundle).
12
+ * - Skip on opt-out: `CKFORENSICS_SKIP_SKILL_INSTALL=1`.
13
+ * - Existing skill dir is overwritten (idempotent re-install / version upgrade).
14
+ * - Warnings to stderr only; never exits non-zero.
15
+ */
16
+
17
+ import { existsSync, mkdirSync, cpSync, statSync } from "node:fs";
18
+ import { homedir } from "node:os";
19
+ import { join, dirname } from "node:path";
20
+ import { fileURLToPath } from "node:url";
21
+
22
+ const __dirname = dirname(fileURLToPath(import.meta.url));
23
+ const PKG_ROOT = join(__dirname, "..");
24
+ const SKILL_SOURCE = join(PKG_ROOT, ".claude", "skills", "ckforensics");
25
+ const SKILL_TARGET = join(homedir(), ".claude", "skills", "ckforensics");
26
+
27
+ function log(msg) {
28
+ // Single-line dim format to fit cleanly in npm install output
29
+ process.stderr.write(`[ckforensics:skill] ${msg}\n`);
30
+ }
31
+
32
+ function shouldSkip() {
33
+ // Explicit opt-out
34
+ if (process.env.CKFORENSICS_SKIP_SKILL_INSTALL === "1") {
35
+ log("skipped via CKFORENSICS_SKIP_SKILL_INSTALL=1");
36
+ return true;
37
+ }
38
+ // Source missing — dev install or trimmed tarball
39
+ if (!existsSync(SKILL_SOURCE)) {
40
+ log(`skill source not bundled (${SKILL_SOURCE}); skipping`);
41
+ return true;
42
+ }
43
+ return false;
44
+ }
45
+
46
+ function copySkill() {
47
+ // Ensure parent dir exists; cpSync recursive handles the rest.
48
+ mkdirSync(dirname(SKILL_TARGET), { recursive: true });
49
+
50
+ // Detect upgrade vs first install for friendlier message
51
+ const existing = existsSync(SKILL_TARGET);
52
+ cpSync(SKILL_SOURCE, SKILL_TARGET, {
53
+ recursive: true,
54
+ force: true,
55
+ // Don't overwrite if user has customised it (mtime-based heuristic)
56
+ // — but that's risky and confusing. For now: always overwrite, matches
57
+ // CLI versioning semantics (skill version pinned to CLI version).
58
+ });
59
+
60
+ const action = existing ? "updated" : "installed";
61
+ log(`${action} skill at ${SKILL_TARGET}`);
62
+ log("activate next Claude Code session: /ck:forensics");
63
+ }
64
+
65
+ try {
66
+ if (shouldSkip()) {
67
+ process.exit(0);
68
+ }
69
+ copySkill();
70
+ } catch (err) {
71
+ // Never fail parent install over skill copy
72
+ log(`warning: skill install failed (${err.message}); continuing`);
73
+ process.exit(0);
74
+ }
@@ -234,4 +234,19 @@ async function main() {
234
234
  console.log(`[ckforensics] Run: ckforensics --help`);
235
235
  }
236
236
 
237
- main().catch((e) => fatal(String(e)));
237
+ async function installSkill() {
238
+ // Best-effort: invoke the dedicated skill installer module. Failures here
239
+ // never block the binary install. Module handles its own opt-out + missing-
240
+ // source cases.
241
+ try {
242
+ await import("./install-claudekit-skill.js");
243
+ } catch (err) {
244
+ process.stderr.write(
245
+ `[ckforensics:skill] warning: failed to load skill installer (${err.message})\n`
246
+ );
247
+ }
248
+ }
249
+
250
+ main()
251
+ .then(installSkill)
252
+ .catch((e) => fatal(String(e)));