agent-optic 0.2.0

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.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +337 -0
  3. package/examples/commit-tracker.ts +389 -0
  4. package/examples/cost-per-feature.ts +182 -0
  5. package/examples/match-git-commits.ts +171 -0
  6. package/examples/model-costs.ts +131 -0
  7. package/examples/pipe-match.ts +177 -0
  8. package/examples/prompt-history.ts +119 -0
  9. package/examples/session-digest.ts +89 -0
  10. package/examples/timesheet.ts +127 -0
  11. package/examples/work-patterns.ts +124 -0
  12. package/package.json +41 -0
  13. package/src/agent-optic.ts +325 -0
  14. package/src/aggregations/daily.ts +90 -0
  15. package/src/aggregations/project.ts +71 -0
  16. package/src/aggregations/time.ts +44 -0
  17. package/src/aggregations/tools.ts +60 -0
  18. package/src/claude-optic.ts +7 -0
  19. package/src/cli/index.ts +407 -0
  20. package/src/index.ts +69 -0
  21. package/src/parsers/content-blocks.ts +58 -0
  22. package/src/parsers/session-detail.ts +323 -0
  23. package/src/parsers/tool-categories.ts +86 -0
  24. package/src/pricing.ts +62 -0
  25. package/src/privacy/config.ts +67 -0
  26. package/src/privacy/redact.ts +99 -0
  27. package/src/readers/codex-rollout-reader.ts +145 -0
  28. package/src/readers/history-reader.ts +205 -0
  29. package/src/readers/plan-reader.ts +60 -0
  30. package/src/readers/project-reader.ts +101 -0
  31. package/src/readers/session-reader.ts +280 -0
  32. package/src/readers/skill-reader.ts +28 -0
  33. package/src/readers/stats-reader.ts +12 -0
  34. package/src/readers/task-reader.ts +117 -0
  35. package/src/types/aggregations.ts +47 -0
  36. package/src/types/plan.ts +6 -0
  37. package/src/types/privacy.ts +18 -0
  38. package/src/types/project.ts +13 -0
  39. package/src/types/provider.ts +9 -0
  40. package/src/types/session.ts +56 -0
  41. package/src/types/stats.ts +15 -0
  42. package/src/types/task.ts +16 -0
  43. package/src/types/transcript.ts +36 -0
  44. package/src/utils/dates.ts +40 -0
  45. package/src/utils/jsonl.ts +83 -0
  46. package/src/utils/paths.ts +57 -0
  47. package/src/utils/providers.ts +30 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kristoffer
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.
package/README.md ADDED
@@ -0,0 +1,337 @@
1
+ # agent-optic
2
+
3
+ > Reads local assistant history directories and returns structured JSON — sessions, costs, timesheets, work patterns.
4
+
5
+ Zero-dependency, local-first TypeScript library for reading session data from provider directories such as `~/.claude/`, `~/.codex/`, `~/.cursor/`, and `~/.windsurf/`.
6
+
7
+ > **Security Warning**: Provider home directories contain highly sensitive data — API keys, source code, credentials, and personal information may be present in plaintext session files. This library is designed with privacy as the primary concern. See [SECURITY.md](./SECURITY.md).
8
+
9
+ ## Try it
10
+
11
+ ```bash
12
+ bunx agent-optic sessions
13
+ ```
14
+
15
+ ## Features
16
+
17
+ - **Zero runtime dependencies**
18
+ - **No network access**
19
+ - **Privacy by default** — strips tool results and thinking blocks
20
+ - **Two-tier session loading** — fast (`history.jsonl`) or detailed (full parse)
21
+ - **Bun-native** — `Bun.file()`, `Bun.Glob`
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ bun add agent-optic
27
+ ```
28
+
29
+ ## Examples
30
+
31
+ The `examples/` directory contains standalone scripts that show what your session data unlocks. Run any of them with `bun examples/<name>.ts`.
32
+
33
+ ### Cost per Feature
34
+
35
+ Match sessions to git branches and calculate what each feature costs in tokens and USD.
36
+
37
+ ```bash
38
+ bun examples/cost-per-feature.ts --repo /path/to/repo
39
+ ```
40
+
41
+ ```
42
+ Cost per Feature / Branch
43
+ ==========================================================================================
44
+ Feature/Branch Sessions Tokens Est. Cost Commits
45
+ ------------------------------------------------------------------------------------------
46
+ feat/auth-system 8 2.3M $4.12 5
47
+ fix/memory-leak 3 890K $1.55 2
48
+ refactor/api-client 5 1.1M $2.08 3
49
+ ```
50
+
51
+ ### Match Git Commits
52
+
53
+ Correlate git commits with sessions by timestamp proximity — find which session produced each commit.
54
+
55
+ ```bash
56
+ bun examples/match-git-commits.ts --days 7
57
+ ```
58
+
59
+ ### Timesheet
60
+
61
+ Generate a weekly timesheet grouped by day and project, with gap-capped hours.
62
+
63
+ ```bash
64
+ bun examples/timesheet.ts
65
+ ```
66
+
67
+ ```
68
+ Timesheet: 2026-02-10 → 2026-02-14
69
+ ==========================================================================================
70
+ Day Date Project Hours Sessions Prompts
71
+ ------------------------------------------------------------------------------------------
72
+ Mon 2026-02-10 claude-optic 2.3 4 18
73
+ my-app 1.1 2 8
74
+ Tue 2026-02-11 claude-optic 3.5 6 32
75
+ ------------------------------------------------------------------------------------------
76
+ TOTAL 6.9 12 58
77
+ ```
78
+
79
+ ### Model Costs
80
+
81
+ Compare token usage and costs across model families.
82
+
83
+ ```bash
84
+ bun examples/model-costs.ts
85
+ ```
86
+
87
+ ```
88
+ Model Usage & Costs: 2026-01-13 → 2026-02-12
89
+ ====================================================================================================
90
+ Model Sessions Input Output Cache W Cache R Est. Cost
91
+ ----------------------------------------------------------------------------------------------------
92
+ opus-4-5-20250514 12 4.2M 1.1M 3.8M 2.1M $98.42
93
+ sonnet-4-5-20250929 45 8.1M 2.3M 6.2M 4.5M $42.15
94
+ ```
95
+
96
+ ### Prompt History
97
+
98
+ Export sampled prompts grouped by project as JSON — pipe to an LLM for categorization or analysis.
99
+
100
+ ```bash
101
+ bun examples/prompt-history.ts --from 2026-01-01 | claude "categorize these prompts by intent"
102
+ ```
103
+
104
+ ### Session Digest
105
+
106
+ Compact session summaries as JSON — first prompt, branch, model, token counts, cost, duration.
107
+
108
+ ```bash
109
+ bun examples/session-digest.ts --days 7 | claude "which sessions were the most productive?"
110
+ ```
111
+
112
+ ### Work Patterns
113
+
114
+ Aggregated work pattern metrics as JSON — hour distribution, late-night/weekend counts, longest and most expensive sessions.
115
+
116
+ ```bash
117
+ bun examples/work-patterns.ts | claude "analyze my work patterns and suggest improvements"
118
+ ```
119
+
120
+ ### Commit Tracker
121
+
122
+ Post-commit hook that records AI usage per commit to `.ai-usage.jsonl`.
123
+
124
+ ```bash
125
+ # Install the git hook
126
+ bun examples/commit-tracker.ts install
127
+
128
+ # Or run manually for the latest commit
129
+ bun examples/commit-tracker.ts run
130
+ ```
131
+
132
+ Each commit gets a JSONL record with matched sessions, token counts, and cost:
133
+
134
+ ```json
135
+ {"commit":"7c5a457","timestamp":"2026-02-13T21:12:13.000Z","branch":"main","sessions":2,"tokens":{"input":194,"output":1638,"cache_read":1534390,"cache_write":83203},"cost_usd":1.33,"models":["claude-opus-4-6"],"messages":89,"files_changed":2}
136
+ ```
137
+
138
+ ```bash
139
+ # Uninstall when done
140
+ bun examples/commit-tracker.ts uninstall
141
+ ```
142
+
143
+ ### Pipe Match
144
+
145
+ Generic stdin matcher — pipe in any JSON with timestamps, match against sessions.
146
+
147
+ ```bash
148
+ # Match GitHub PRs to sessions that produced them
149
+ gh pr list --json createdAt,title | bun examples/pipe-match.ts --field createdAt
150
+
151
+ # Match GitHub issues
152
+ gh issue list --json createdAt,title | bun examples/pipe-match.ts --field createdAt
153
+
154
+ # Match any timestamped JSON
155
+ echo '[{"timestamp":"2026-02-10T14:00:00Z","title":"Deploy v2.1"}]' | bun examples/pipe-match.ts
156
+
157
+ # Works with any JSON — work items, calendar events, deploys, etc.
158
+ cat events.json | bun examples/pipe-match.ts
159
+ ```
160
+
161
+ ## Quick Start
162
+
163
+ ```typescript
164
+ import { createHistory } from "agent-optic";
165
+
166
+ const ch = createHistory({ provider: "claude" });
167
+
168
+ // List today's sessions (fast — reads only history.jsonl)
169
+ const sessions = await ch.sessions.list();
170
+
171
+ // List with metadata (slower — peeks session files for branch/model/tokens)
172
+ const withMeta = await ch.sessions.listWithMeta();
173
+
174
+ // Get full session detail
175
+ const detail = await ch.sessions.detail(sessionId, projectPath);
176
+
177
+ // Stream transcript entries
178
+ for await (const entry of ch.sessions.transcript(sessionId, projectPath)) {
179
+ console.log(entry.message?.role, entry.timestamp);
180
+ }
181
+
182
+ // Daily summary (sessions + tasks + plans + todos + project memory)
183
+ const daily = await ch.aggregate.daily("2026-02-09");
184
+
185
+ // Project summaries
186
+ const projects = await ch.aggregate.byProject({ from: "2026-02-01", to: "2026-02-09" });
187
+
188
+ // Estimate cost of a session
189
+ import { estimateCost } from "agent-optic";
190
+ const cost = estimateCost(withMeta[0]); // USD
191
+ ```
192
+
193
+ ## API
194
+
195
+ ### `createHistory(config?)`
196
+
197
+ ```typescript
198
+ const ch = createHistory({
199
+ provider: "claude", // "claude" | "codex" | "openai" | "cursor" | "windsurf"
200
+ providerDir: "~/.claude", // default: provider-specific home directory
201
+ privacy: "local", // "local" | "shareable" | "strict" | Partial<PrivacyConfig>
202
+ cache: true, // default: true
203
+ });
204
+ ```
205
+
206
+ `openai` is currently an alias of Codex-format local history and defaults to `~/.codex`.
207
+
208
+ `createClaudeHistory()` is still exported for backward compatibility and behaves like `createHistory({ provider: "claude" })`.
209
+
210
+ ### Sessions
211
+
212
+ | Method | Speed | Reads | Returns |
213
+ |--------|-------|-------|---------|
214
+ | `sessions.list(filter?)` | Fast | `history.jsonl` only | `SessionInfo[]` |
215
+ | `sessions.listWithMeta(filter?)` | Medium | + peeks session files | `SessionMeta[]` |
216
+ | `sessions.detail(id, project)` | Slow | Full session parse | `SessionDetail` |
217
+ | `sessions.transcript(id, project)` | Streaming | Full session file | `AsyncGenerator<TranscriptEntry>` |
218
+ | `sessions.count(filter?)` | Fast | `history.jsonl` only | `number` |
219
+
220
+ ### Other Data
221
+
222
+ ```typescript
223
+ ch.projects.list() // ProjectInfo[]
224
+ ch.projects.memory(projectPath) // ProjectMemory | null
225
+ ch.tasks.list({ date: "2026-02-09" }) // TaskInfo[]
226
+ ch.todos.list({ date: "2026-02-09" }) // TodoItem[]
227
+ ch.plans.list({ date: "2026-02-09" }) // PlanInfo[]
228
+ ch.skills.list() // string[]
229
+ ch.skills.read("skill-name") // string (SKILL.md content)
230
+ ch.stats.get() // StatsCache | null
231
+ ```
232
+
233
+ ### Aggregations
234
+
235
+ ```typescript
236
+ ch.aggregate.daily("2026-02-09") // DailySummary
237
+ ch.aggregate.dailyRange("2026-02-01", "2026-02-09") // DailySummary[]
238
+ ch.aggregate.byProject({ from: "2026-02-01" }) // ProjectSummary[]
239
+ ch.aggregate.toolUsage({ date: "2026-02-09" }) // ToolUsageReport
240
+ ch.aggregate.estimateHours(sessions) // number (gap-capped)
241
+ ```
242
+
243
+ ### Cost Estimation
244
+
245
+ ```typescript
246
+ import { estimateCost, getModelPricing, MODEL_PRICING } from "agent-optic";
247
+
248
+ // Estimate cost for a session (requires SessionMeta — use listWithMeta)
249
+ const session = (await ch.sessions.listWithMeta())[0];
250
+ const cost = estimateCost(session); // USD
251
+
252
+ // Look up pricing for a model
253
+ const pricing = getModelPricing("claude-opus-4-6");
254
+ // { input: 5, output: 25, cacheWrite: 6.25, cacheRead: 0.5 } per million tokens
255
+ ```
256
+
257
+ ### Filters
258
+
259
+ ```typescript
260
+ // Date filter (all methods)
261
+ { date: "2026-02-09" } // Single day
262
+ { from: "2026-02-01", to: "2026-02-09" } // Range
263
+ { from: "2026-02-01" } // From date to today
264
+
265
+ // Session filter (extends DateFilter)
266
+ { date: "2026-02-09", project: "my-app" } // Filter by project name
267
+ ```
268
+
269
+ ## Privacy Profiles
270
+
271
+ | Profile | Strips |
272
+ |---------|--------|
273
+ | `local` (default) | Tool results, thinking blocks |
274
+ | `shareable` | + absolute paths, home directory |
275
+ | `strict` | + prompt text, emails, credential patterns, IPs |
276
+
277
+ ```typescript
278
+ // Use a built-in profile
279
+ const ch = createHistory({ provider: "claude", privacy: "strict" });
280
+
281
+ // Or customize
282
+ const ch = createHistory({
283
+ provider: "claude",
284
+ privacy: {
285
+ redactPrompts: false,
286
+ stripToolResults: true,
287
+ stripThinking: true,
288
+ excludeProjects: ["/work/secret-project"],
289
+ },
290
+ });
291
+ ```
292
+
293
+ ## CLI
294
+
295
+ ```bash
296
+ # Agent-friendly list (JSONL stream)
297
+ bunx agent-optic sessions --provider codex --format jsonl
298
+
299
+ # Detail for one session
300
+ bunx agent-optic detail 019c9aea-484d-7200-87fd-07a545276ac4 --provider openai
301
+
302
+ # Transcript stream (limit + selected fields)
303
+ bunx agent-optic transcript 019c9aea-484d-7200-87fd-07a545276ac4 --provider openai --format jsonl --limit 50 --fields timestamp,message
304
+
305
+ # Tool usage report
306
+ bunx agent-optic tool-usage --provider codex --from 2026-02-01 --to 2026-02-26
307
+
308
+ # Daily summary
309
+ bunx agent-optic daily --date 2026-02-09
310
+
311
+ # Raw output without envelope
312
+ bunx agent-optic sessions --provider claude --date 2026-02-09 --raw
313
+ ```
314
+
315
+ `--format json` returns a stable envelope (`schemaVersion`, `command`, `provider`, `generatedAt`, `data`) by default.
316
+ Use `--raw` for data-only output and `--format jsonl` for one JSON object per line.
317
+
318
+ ## Architecture
319
+
320
+ ```
321
+ src/
322
+ agent-optic.ts # Main factory: createHistory()
323
+ claude-optic.ts # Backward-compatible Claude aliases
324
+ pricing.ts # Model pricing data and cost estimation
325
+ types/ # Type definitions (one file per domain)
326
+ readers/ # File readers (history, session, tasks, plans, projects, stats)
327
+ parsers/ # Session parsing, tool categorization, content extraction
328
+ aggregations/ # Daily/project/tool summaries, time estimation
329
+ privacy/ # Redaction engine, privacy profiles
330
+ utils/ # Dates, paths, JSONL streaming
331
+ cli/ # CLI entry point
332
+ examples/ # Standalone scripts showing what the data unlocks
333
+ ```
334
+
335
+ ## License
336
+
337
+ MIT