agent-optic
v0.4.0
Published
Zero-dependency, local-first library for reading AI assistant session data from provider home directories
Maintainers
Readme
agent-optic
Reads local assistant history directories and returns structured JSON — sessions, costs, timesheets, work patterns.
Zero-dependency, local-first TypeScript library for reading session data from provider directories such as ~/.claude/, ~/.codex/, ~/.pi/, ~/.cursor/, and ~/.windsurf/.
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.
Try it
bunx --silent agent-optic sessionsFeatures
- Zero runtime dependencies
- No network access
- Privacy by default — strips tool results and thinking blocks
- Multi-tier session loading — index, meta, detail, and transcript streaming
- Agent-first CLI contract — stable JSON envelope + JSONL streaming + machine-readable errors
- Bun-native —
Bun.file(),Bun.Glob
Install
bun add agent-opticExamples
The examples/ directory contains standalone scripts that show what your session data unlocks. Run any of them with bun examples/<name>.ts.
Cost per Feature
Match sessions to git branches and calculate what each feature costs in tokens and USD.
bun examples/cost-per-feature.ts --repo /path/to/repoCost per Feature / Branch
==========================================================================================
Feature/Branch Sessions Tokens Est. Cost Commits
------------------------------------------------------------------------------------------
feat/auth-system 8 2.3M $4.12 5
fix/memory-leak 3 890K $1.55 2
refactor/api-client 5 1.1M $2.08 3Match Git Commits
Correlate git commits with sessions by timestamp proximity — find which session produced each commit.
bun examples/match-git-commits.ts --days 7Timesheet
Generate a weekly timesheet grouped by day and project, with gap-capped hours.
bun examples/timesheet.tsTimesheet: 2026-02-10 → 2026-02-14
==========================================================================================
Day Date Project Hours Sessions Prompts
------------------------------------------------------------------------------------------
Mon 2026-02-10 agent-optic 2.3 4 18
my-app 1.1 2 8
Tue 2026-02-11 agent-optic 3.5 6 32
------------------------------------------------------------------------------------------
TOTAL 6.9 12 58Model Costs
Compare token usage and costs across model families.
bun examples/model-costs.tsModel Usage & Costs: 2026-01-13 → 2026-02-12
====================================================================================================
Model Sessions Input Output Cache W Cache R Est. Cost
----------------------------------------------------------------------------------------------------
opus-4-5-20250514 12 4.2M 1.1M 3.8M 2.1M $98.42
sonnet-4-5-20250929 45 8.1M 2.3M 6.2M 4.5M $42.15Prompt History
Export sampled prompts grouped by project as JSON — pipe to an LLM for categorization or analysis.
# Pipe to your preferred LLM CLI
bun examples/prompt-history.ts --from 2026-01-01 | your-llm-cli "categorize these prompts by intent"Session Digest
Compact session summaries as JSON — first prompt, branch, model, token counts, cost, duration.
# Pipe to your preferred LLM CLI
bun examples/session-digest.ts --days 7 | your-llm-cli "which sessions were the most productive?"Work Patterns
Aggregated work pattern metrics as JSON — hour distribution, late-night/weekend counts, longest and most expensive sessions.
# Pipe to your preferred LLM CLI
bun examples/work-patterns.ts | your-llm-cli "analyze my work patterns and suggest improvements"Commit Tracker
Post-commit hook that records AI usage per commit to .ai-usage.jsonl.
# Install the git hook
bun examples/commit-tracker.ts install
# Or run manually for the latest commit
bun examples/commit-tracker.ts runEach commit gets a JSONL record with matched sessions, token counts, and cost:
{"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}# Uninstall when done
bun examples/commit-tracker.ts uninstallPipe Match
Generic stdin matcher — pipe in any JSON with timestamps, match against sessions.
# Match GitHub PRs to sessions that produced them
gh pr list --json createdAt,title | bun examples/pipe-match.ts --field createdAt
# Match GitHub issues
gh issue list --json createdAt,title | bun examples/pipe-match.ts --field createdAt
# Match any timestamped JSON
echo '[{"timestamp":"2026-02-10T14:00:00Z","title":"Deploy v2.1"}]' | bun examples/pipe-match.ts
# Works with any JSON — work items, calendar events, deploys, etc.
cat events.json | bun examples/pipe-match.tsQuick Start
import { createHistory } from "agent-optic";
const ch = createHistory({ provider: "claude" });
// List today's sessions (fast — reads only history.jsonl)
const sessions = await ch.sessions.list();
// List with metadata (slower — reads session files for branch/model/tokens)
const withMeta = await ch.sessions.listWithMeta();
// Get full session detail (projectPath is optional for codex/openai)
const detail = await ch.sessions.detail(sessionId);
// Stream transcript entries (projectPath is optional for codex/openai)
for await (const entry of ch.sessions.transcript(sessionId)) {
console.log(entry.message?.role, entry.timestamp);
}
// Daily summary (sessions + tasks + plans + todos + project memory)
const daily = await ch.aggregate.daily("2026-02-09");
// Project summaries
const projects = await ch.aggregate.byProject({ from: "2026-02-01", to: "2026-02-09" });
// Estimate cost of a session
import { estimateCost } from "agent-optic";
const cost = estimateCost(withMeta[0]); // USDAPI
The public package surface is intentionally small: createHistory, core types, privacy profiles, pricing helpers, and a few date/project helpers. Low-level readers, parsers, and JSONL utilities remain internal.
createHistory(config?)
const ch = createHistory({
provider: "claude", // "claude" | "codex" | "openai" | "pi" | "cursor" | "windsurf"
providerDir: "~/.claude", // default: provider-specific home directory
privacy: "local", // "local" | "shareable" | "strict" | Partial<PrivacyConfig>
});openai is currently an alias of Codex-format local history and defaults to ~/.codex.
pi reads from ~/.pi/agent/sessions/ — Pi has no history.jsonl, so sessions are discovered by scanning the directory tree. Pi sessions include totalCost from accumulated message costs.
Sessions
| Method | Speed | Reads | Returns |
|--------|-------|-------|---------|
| sessions.list(filter?) | Fast | history.jsonl only | SessionInfo[] |
| sessions.listWithMeta(filter?) | Medium | + reads session files for metadata | SessionMeta[] |
| sessions.detail(id, project?) | Slow | Full session parse | SessionDetail |
| sessions.transcript(id, project?) | Streaming | Full session file | AsyncGenerator<TranscriptEntry> |
| sessions.count(filter?) | Fast | history.jsonl only | number |
For codex, openai, and pi, project is optional because project/cwd is resolved from session metadata.
Other Data
ch.projects.list() // ProjectInfo[]
ch.projects.memory(projectPath) // ProjectMemory | null
ch.tasks.list({ date: "2026-02-09" }) // TaskInfo[]
ch.todos.list({ date: "2026-02-09" }) // TodoItem[]
ch.plans.list({ date: "2026-02-09" }) // PlanInfo[]
ch.skills.list() // string[]
ch.skills.read("skill-name") // string (SKILL.md content)
ch.stats.get() // StatsCache | nullAggregations
ch.aggregate.daily("2026-02-09") // DailySummary
ch.aggregate.dailyRange("2026-02-01", "2026-02-09") // DailySummary[]
ch.aggregate.byProject({ from: "2026-02-01" }) // ProjectSummary[]
ch.aggregate.toolUsage({ date: "2026-02-09" }) // ToolUsageReport
ch.aggregate.estimateHours(sessions) // number (gap-capped)Cost Estimation
import { estimateCost, getModelPricing, MODEL_PRICING } from "agent-optic";
// Estimate cost for a session (requires SessionMeta — use listWithMeta)
const session = (await ch.sessions.listWithMeta())[0];
const cost = estimateCost(session); // USD
// Look up pricing for a model
const pricing = getModelPricing("claude-opus-4-6");
// { input: 5, output: 25, cacheWrite: 6.25, cacheRead: 0.5 } per million tokensFilters
// Date filter (all methods)
{ date: "2026-02-09" } // Single day
{ from: "2026-02-01", to: "2026-02-09" } // Range
{ from: "2026-02-01" } // From date to today
// Session filter (extends DateFilter)
{ date: "2026-02-09", project: "my-app" } // Filter by project namePrivacy Profiles
| Profile | Strips |
|---------|--------|
| local (default) | Tool results, thinking blocks |
| shareable | + absolute paths, home directory |
| strict | + prompt text, emails, credential patterns, IPs |
// Use a built-in profile
const ch = createHistory({ provider: "claude", privacy: "strict" });
// Or customize
const ch = createHistory({
provider: "claude",
privacy: {
redactPrompts: false,
stripToolResults: true,
stripThinking: true,
excludeProjects: ["/work/secret-project"],
},
});CLI
# Agent-friendly list (JSONL stream)
bunx --silent agent-optic sessions --provider codex --format jsonl
# Detail for one session
bunx --silent agent-optic detail 019c9aea-484d-7200-87fd-07a545276ac4 --provider openai
# Transcript stream (limit + selected fields)
bunx --silent agent-optic transcript 019c9aea-484d-7200-87fd-07a545276ac4 --provider openai --format jsonl --limit 50 --fields timestamp,message
# Tool usage report
bunx --silent agent-optic tool-usage --provider codex --from 2026-02-01 --to 2026-02-26
# Daily summary
bunx --silent agent-optic daily --date 2026-02-09
# Raw output without envelope
bunx --silent agent-optic sessions --provider claude --date 2026-02-09 --raw--format json returns a stable envelope (schemaVersion, command, provider, generatedAt, data) by default.
Use --raw for data-only output and --format jsonl for one JSON object per line.
Common agent commands:
sessions [session-id?]list sessions (or filter to one ID)detail <session-id>full parsed sessiontranscript <session-id>transcript stream/outputtool-usageaggregated tool analytics
Architecture
src/
agent-optic.ts # Main factory and runtime API
pricing.ts # Model pricing data and cost estimation
types/ # Type definitions (one file per domain)
readers/ # File readers (history, session, tasks, plans, projects, stats)
parsers/ # Session parsing, tool categorization, content extraction
aggregations/ # Daily/project/tool summaries, time estimation
privacy/ # Redaction engine, privacy profiles
utils/ # Dates, paths, JSONL streaming
cli/ # CLI entry point
examples/ # Standalone scripts showing what the data unlocksLicense
MIT
