feat: pi agent integration#760
Conversation
Add support for pi-agent session data, enabling unified Claude Max usage tracking across both Claude Code and pi-agent clients. - Add --pi-agent flag to include pi-agent data from ~/.pi/agent/sessions - Add --pi-agent-path option for custom pi-agent sessions directory - Add PI_AGENT_DIR environment variable support - Create _pi-agent.ts with schema validation and data transformation - Update loadDailyUsageData, loadSessionData, loadSessionBlockData - Pi-agent costs are pre-calculated, no LiteLLM lookup needed - Use pi: prefix for deduplication to avoid collision with Claude Code
Prefix pi-agent model names with [pi-agent] so users can easily distinguish which usage data comes from Claude Code vs pi-agent in the combined reports.
- Rename --pi-agent to --pi and --pi-agent-path to --pi-path - Rename PI_AGENT_DIR env to PI_AGENT_DIR (unchanged) - Add source grouping when --pi is used (separate rows for cc vs pi) - Add 'source' field to DailyUsage and BucketUsage schemas - Change model prefix from [pi-agent] to [pi] for brevity - Works with daily, monthly, weekly, session, blocks commands
Extend formatModelName to handle additional model name patterns: - [pi] prefix: preserve prefix, format the rest - anthropic/claude-* prefix with dot notation - claude-* without date suffix Existing behavior for date-suffixed models unchanged.
Per maintainer feedback, pi-agent support is now a separate package to avoid increasing bundle size for users who don't need it. Changes: - Revert pi-agent changes from main ccusage package - Create new apps/pi package (@ccusage/pi) - CLI binary: ccusage-pi - Commands: daily, monthly, session - Imports from ccusage for Claude Code data loading - Self-contained pi-agent data loading The package combines usage data from both Claude Code and pi-agent, showing separate rows per source with [cc] and [pi] labels.
- Fix timestamp regex to accept timezone offsets (+00:00) - Fix isPiAgentUsageEntry to treat missing type as message - Fix date filtering to normalize YYYYMMDD and YYYY-MM-DD formats - Strengthen dedup key with file, session, and all usage fields - Use path.basename for cross-platform path handling in session - Fix display: show [pi]/[cc] labels clearly without truncation - Add tests for new formatModelName patterns in terminal
Pi-agent produces duplicate entries across session files (same timestamp and token counts appear up to 19 times). The simpler dedup key correctly filters these duplicates. The more specific key from code review caused overcounting by ~$2,100.
📝 WalkthroughWalkthroughAdds a new CLI app Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant CLI as ccusage-pi (CLI)
participant Loader as Data Loader
participant FS as File System
participant CC as Claude Code loader
User->>CLI: run "daily|monthly|session" options
CLI->>Loader: loadPiAgent... (piPath,since,until,timezone)
CLI->>CC: loadClaudeCodeData(since,until)
Loader->>FS: read JSONL files (sessions/*.jsonl)
FS-->>Loader: stream lines
Loader->>Loader: validate & transform entries (Valibot)
Loader->>Loader: dedupe, aggregate, compute breakdowns
Loader-->>CLI: return aggregated data
CC-->>CLI: return Claude Code data
CLI->>CLI: merge sources, sort, compute totals
CLI-->>User: render JSON or formatted table
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (5)
apps/pi/src/_types.ts (1)
3-10: Consider adding tests for ISO timestamp validation.The ISO timestamp regex and schema look correct, but following the in-source testing pattern, consider adding validation tests to ensure edge cases are handled properly (e.g., with/without milliseconds, different timezone formats).
Example test structure
export type ISOTimestamp = v.InferOutput<typeof isoTimestampSchema>; + +if (import.meta.vitest != null) { + const { describe, it, expect } = import.meta.vitest; + + describe('isoTimestampSchema', () => { + it('should validate ISO timestamps with Z timezone', () => { + const result = v.safeParse(isoTimestampSchema, '2025-12-20T13:52:51Z'); + expect(result.success).toBe(true); + }); + + it('should validate ISO timestamps with milliseconds', () => { + const result = v.safeParse(isoTimestampSchema, '2025-12-20T13:52:51.123Z'); + expect(result.success).toBe(true); + }); + + it('should validate ISO timestamps with timezone offset', () => { + const result = v.safeParse(isoTimestampSchema, '2025-12-20T13:52:51+09:00'); + expect(result.success).toBe(true); + }); + + it('should reject invalid timestamps', () => { + const result = v.safeParse(isoTimestampSchema, '2025-12-20'); + expect(result.success).toBe(false); + }); + }); +}apps/pi/src/commands/daily.ts (1)
139-139: Consider extracting the column count constant.The hardcoded
8matches the currentcreateUsageReportTableheader count, but this coupling could cause issues if the table structure changes.🔎 Optional: Extract column count
You could define a constant or derive it from the table configuration to avoid this coupling:
// At module level or derive from table headers const TABLE_COLUMN_COUNT = 8; // ... addEmptySeparatorRow(table, TABLE_COLUMN_COUNT);apps/pi/src/commands/monthly.ts (1)
9-153: Optional: Consider extracting shared command logic.Both
daily.tsandmonthly.tsshare substantial code patterns:
- Identical args definitions
- Same options construction
- Same totals calculation loop
- Same table rendering structure
This is acceptable for a small number of commands, but if a third similar command is added (e.g., weekly), consider extracting shared utilities for args definitions and the rendering pipeline.
apps/pi/src/_pi-agent.ts (1)
129-148: Consider using compliant model names in tests.Per coding guidelines, test model names should match the LiteLLM pricing database format (e.g.,
claude-opus-4-20250514). However, since this is testing Pi Agent data transformation rather than pricing lookups,claude-opus-4-5may be acceptable as it represents the format used by Pi Agent itself.Please verify whether Pi Agent actually uses model names like
claude-opus-4-5or follows the standard format with dates.apps/pi/src/commands/session.ts (1)
109-112: EnableincludeLastActivityto show last activity timestamps in session table.The session data has a
lastActivityfield available (used for sorting on line 80) andformatUsageDataRowaccepts an optionallastActivityparameter. Including this column would provide useful context about when each session was last active.To enable this, pass
includeLastActivity: truetocreateUsageReportTable(line 109), passdata.lastActivitytoformatUsageDataRow(line 120), update the separator row column count from 8 to 9 (line 135), and passincludeLastActivity: truetoformatTotalsRow(line 137).
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (16)
apps/pi/README.md(1 hunks)apps/pi/eslint.config.js(1 hunks)apps/pi/package.json(1 hunks)apps/pi/src/_consts.ts(1 hunks)apps/pi/src/_pi-agent.ts(1 hunks)apps/pi/src/_types.ts(1 hunks)apps/pi/src/commands/daily.ts(1 hunks)apps/pi/src/commands/index.ts(1 hunks)apps/pi/src/commands/monthly.ts(1 hunks)apps/pi/src/commands/session.ts(1 hunks)apps/pi/src/data-loader.ts(1 hunks)apps/pi/src/index.ts(1 hunks)apps/pi/tsconfig.json(1 hunks)apps/pi/tsdown.config.ts(1 hunks)apps/pi/vitest.config.ts(1 hunks)packages/terminal/src/table.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{ts,tsx,json}
📄 CodeRabbit inference engine (CLAUDE.md)
Claude model naming convention:
claude-{model-type}-{generation}-{date}(e.g.,claude-sonnet-4-20250514, NOTclaude-4-sonnet-20250514)
Files:
apps/pi/tsconfig.jsonapps/pi/src/index.tsapps/pi/vitest.config.tsapps/pi/src/_types.tsapps/pi/src/commands/daily.tsapps/pi/src/commands/index.tsapps/pi/src/commands/session.tsapps/pi/src/_pi-agent.tsapps/pi/src/commands/monthly.tsapps/pi/src/_consts.tsapps/pi/package.jsonpackages/terminal/src/table.tsapps/pi/tsdown.config.tsapps/pi/src/data-loader.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx}: Use ESLint for linting and formatting with tab indentation and double quotes
No console.log allowed except where explicitly disabled with eslint-disable; use logger.ts instead
Use file paths with Node.js path utilities for cross-platform compatibility
Use variables starting with lowercase (camelCase) for variable names
Can use UPPER_SNAKE_CASE for constants
Files:
apps/pi/src/index.tsapps/pi/vitest.config.tsapps/pi/src/_types.tsapps/pi/src/commands/daily.tsapps/pi/src/commands/index.tsapps/pi/src/commands/session.tsapps/pi/eslint.config.jsapps/pi/src/_pi-agent.tsapps/pi/src/commands/monthly.tsapps/pi/src/_consts.tspackages/terminal/src/table.tsapps/pi/tsdown.config.tsapps/pi/src/data-loader.ts
**/*.ts{,x}
📄 CodeRabbit inference engine (CLAUDE.md)
Use TypeScript with strict mode and bundler module resolution
Files:
apps/pi/src/index.tsapps/pi/vitest.config.tsapps/pi/src/_types.tsapps/pi/src/commands/daily.tsapps/pi/src/commands/index.tsapps/pi/src/commands/session.tsapps/pi/src/_pi-agent.tsapps/pi/src/commands/monthly.tsapps/pi/src/_consts.tspackages/terminal/src/table.tsapps/pi/tsdown.config.tsapps/pi/src/data-loader.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use.tsextensions for local file imports (e.g.,import { foo } from './utils.ts')
Prefer @praha/byethrow Result type over traditional try-catch for functional error handling
UseResult.try()for wrapping operations that may throw (JSON parsing, etc.)
UseResult.isFailure()for checking errors (more readable than!Result.isSuccess())
Use early return pattern (if (Result.isFailure(result)) continue;) instead of ternary operators when checking Results
Keep traditional try-catch only for file I/O with complex error handling or legacy code that's hard to refactor
Always useResult.isFailure()andResult.isSuccess()type guards for better code clarity
Use uppercase (PascalCase) for type names
Only export constants, functions, and types that are actually used by other modules - internal constants used only within the same file should NOT be exported
In-source testing pattern: write tests directly in source files usingif (import.meta.vitest != null)blocks
CRITICAL: DO NOT useawait import()dynamic imports anywhere in the codebase - this causes tree-shaking issues
CRITICAL: Never use dynamic imports withawait import()in vitest test blocks - this is particularly problematic for test execution
Vitest globals (describe,it,expect) are enabled and available without imports since globals are configured
Create mock data usingfs-fixturewithcreateFixture()for Claude data directory simulation in tests
All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models
Model names in tests must exactly match LiteLLM's pricing database entries
Files:
apps/pi/src/index.tsapps/pi/vitest.config.tsapps/pi/src/_types.tsapps/pi/src/commands/daily.tsapps/pi/src/commands/index.tsapps/pi/src/commands/session.tsapps/pi/src/_pi-agent.tsapps/pi/src/commands/monthly.tsapps/pi/src/_consts.tspackages/terminal/src/table.tsapps/pi/tsdown.config.tsapps/pi/src/data-loader.ts
**/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.md: Place screenshots immediately after the main heading (H1) in documentation pages for immediate visual context
Use relative image paths like/screenshot.pngfor images stored in/docs/public/in documentation
Always include descriptive alt text for images in documentation for accessibility
Files:
apps/pi/README.md
apps/*/package.json
📄 CodeRabbit inference engine (CLAUDE.md)
All projects under
apps/ship as bundled CLIs/binaries - treat runtime dependencies as bundled assets by listing everything in each app'sdevDependencies(neverdependencies)
Files:
apps/pi/package.json
**/package.json
📄 CodeRabbit inference engine (CLAUDE.md)
Dependencies should always be added as devDependencies unless explicitly requested otherwise
Files:
apps/pi/package.json
**/data-loader.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Silently skip malformed JSONL lines during parsing in data loading operations
Files:
apps/pi/src/data-loader.ts
🧠 Learnings (31)
📓 Common learnings
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Refer to individual CLAUDE.md files in apps/ccusage/CLAUDE.md, apps/mcp/CLAUDE.md, and docs/CLAUDE.md for package-specific guidance
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use `fs-fixture` with `createFixture()` to simulate Claude data in tests
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : In tests, use current Claude 4 models (sonnet-4, opus-4)
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Do not use console.log; use the logger utilities from `src/logger.ts` instead
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/**/*.ts : Use `.ts` extensions for local imports (e.g., `import { foo } from './utils.ts'`)
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.ts{,x} : Use TypeScript with strict mode and bundler module resolution
Applied to files:
apps/pi/tsconfig.jsonapps/pi/tsdown.config.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Vitest globals (`describe`, `it`, `expect`) are enabled and available without imports since globals are configured
Applied to files:
apps/pi/tsconfig.jsonapps/pi/vitest.config.tsapps/pi/eslint.config.jsapps/pi/src/_pi-agent.tsapps/pi/tsdown.config.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Use `.ts` extensions for local file imports (e.g., `import { foo } from './utils.ts'`)
Applied to files:
apps/pi/tsconfig.json
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Use uppercase (PascalCase) for type names
Applied to files:
apps/pi/tsconfig.jsonapps/pi/tsdown.config.ts
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/**/*.ts : Use `.ts` extensions for local imports (e.g., `import { foo } from './utils.ts'`)
Applied to files:
apps/pi/tsconfig.jsonapps/pi/src/index.tsapps/pi/package.json
📚 Learning: 2025-09-17T18:29:15.764Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/mcp/CLAUDE.md:0-0
Timestamp: 2025-09-17T18:29:15.764Z
Learning: Applies to apps/mcp/**/*.ts : Use `.ts` extensions for local (relative) imports
Applied to files:
apps/pi/tsconfig.json
📚 Learning: 2025-09-17T18:29:15.764Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/mcp/CLAUDE.md:0-0
Timestamp: 2025-09-17T18:29:15.764Z
Learning: Applies to apps/mcp/**/*.{test,spec}.ts : Vitest globals enabled: use `describe`, `it`, `expect` directly without importing them
Applied to files:
apps/pi/tsconfig.jsonapps/pi/vitest.config.tsapps/pi/eslint.config.jsapps/pi/src/_pi-agent.ts
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use Vitest globals (`describe`, `it`, `expect`) without imports in test blocks
Applied to files:
apps/pi/tsconfig.jsonapps/pi/vitest.config.tsapps/pi/eslint.config.jsapps/pi/src/_pi-agent.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx,js,jsx} : Use ESLint for linting and formatting with tab indentation and double quotes
Applied to files:
apps/pi/tsconfig.jsonapps/pi/eslint.config.js
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Write tests in-source using `if (import.meta.vitest != null)` blocks instead of separate test files
Applied to files:
apps/pi/tsconfig.jsonapps/pi/vitest.config.tsapps/pi/eslint.config.jsapps/pi/src/_pi-agent.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : In-source testing pattern: write tests directly in source files using `if (import.meta.vitest != null)` blocks
Applied to files:
apps/pi/tsconfig.jsonapps/pi/vitest.config.tsapps/pi/eslint.config.jsapps/pi/src/_pi-agent.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Only export constants, functions, and types that are actually used by other modules - internal constants used only within the same file should NOT be exported
Applied to files:
apps/pi/tsconfig.jsonapps/pi/src/commands/index.tsapps/pi/tsdown.config.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : CRITICAL: Never use dynamic imports with `await import()` in vitest test blocks - this is particularly problematic for test execution
Applied to files:
apps/pi/tsconfig.jsonapps/pi/vitest.config.ts
📚 Learning: 2025-09-18T16:07:16.293Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.293Z
Learning: Entry point remains Gunshi-based; only the daily subcommand is wired for now
Applied to files:
apps/pi/src/index.tsapps/pi/src/commands/index.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Run `pnpm run test` to execute all tests using vitest with watch mode disabled
Applied to files:
apps/pi/vitest.config.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Refer to individual CLAUDE.md files in apps/ccusage/CLAUDE.md, apps/mcp/CLAUDE.md, and docs/CLAUDE.md for package-specific guidance
Applied to files:
apps/pi/README.md
📚 Learning: 2025-09-17T18:29:15.764Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/mcp/CLAUDE.md:0-0
Timestamp: 2025-09-17T18:29:15.764Z
Learning: Applies to apps/mcp/**/*.ts : Only export what is actually used
Applied to files:
apps/pi/src/commands/index.ts
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Only export symbols that are actually used by other modules
Applied to files:
apps/pi/src/commands/index.tsapps/pi/package.json
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use `fs-fixture` with `createFixture()` to simulate Claude data in tests
Applied to files:
apps/pi/src/_pi-agent.tsapps/pi/package.json
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/**/package.json : Add dependencies as devDependencies unless explicitly required otherwise
Applied to files:
apps/pi/package.json
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to apps/*/package.json : All projects under `apps/` ship as bundled CLIs/binaries - treat runtime dependencies as bundled assets by listing everything in each app's `devDependencies` (never `dependencies`)
Applied to files:
apps/pi/package.json
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/**/package.json : Because the CLI is bundled, keep all runtime libraries in devDependencies so the bundler captures them
Applied to files:
apps/pi/package.json
📚 Learning: 2025-09-18T16:07:16.293Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.293Z
Learning: Applies to apps/codex/**/package.json : Package Codex as a bundled CLI and keep every runtime dependency in devDependencies so the bundle includes shipped code
Applied to files:
apps/pi/package.json
📚 Learning: 2025-09-17T18:29:15.764Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/mcp/CLAUDE.md:0-0
Timestamp: 2025-09-17T18:29:15.764Z
Learning: Applies to apps/mcp/**/package.json : Add new dependencies as `devDependencies` unless explicitly requested otherwise
Applied to files:
apps/pi/package.json
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx,json} : Claude model naming convention: `claude-{model-type}-{generation}-{date}` (e.g., `claude-sonnet-4-20250514`, NOT `claude-4-sonnet-20250514`)
Applied to files:
packages/terminal/src/table.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : All test files must use current Claude 4 models (claude-sonnet-4-20250514, claude-opus-4-20250514), not outdated Claude 3 models
Applied to files:
packages/terminal/src/table.ts
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : In tests, use current Claude 4 models (sonnet-4, opus-4)
Applied to files:
packages/terminal/src/table.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/*.{ts,tsx} : Model names in tests must exactly match LiteLLM's pricing database entries
Applied to files:
packages/terminal/src/table.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Test coverage should include both Sonnet and Opus models for comprehensive validation
Applied to files:
packages/terminal/src/table.ts
📚 Learning: 2025-11-25T14:42:34.734Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: Applies to **/data-loader.ts : Silently skip malformed JSONL lines during parsing in data loading operations
Applied to files:
apps/pi/src/data-loader.ts
🧬 Code graph analysis (6)
apps/pi/src/index.ts (3)
apps/pi/src/commands/daily.ts (2)
dailyCommand(9-153)run(47-152)apps/pi/src/commands/monthly.ts (2)
monthlyCommand(9-153)run(47-152)apps/pi/src/commands/session.ts (2)
sessionCommand(10-149)run(48-148)
apps/pi/src/commands/daily.ts (3)
apps/ccusage/src/data-loader.ts (1)
loadDailyUsageData(746-880)apps/pi/src/data-loader.ts (1)
loadPiAgentDailyData(292-327)packages/terminal/src/table.ts (5)
createUsageReportTable(462-519)formatUsageDataRow(528-551)pushBreakdownRows(388-429)addEmptySeparatorRow(585-588)formatTotalsRow(559-578)
apps/pi/src/commands/session.ts (3)
apps/pi/src/commands/index.ts (1)
sessionCommand(3-3)apps/pi/src/data-loader.ts (1)
loadPiAgentSessionData(329-374)packages/terminal/src/table.ts (5)
createUsageReportTable(462-519)formatUsageDataRow(528-551)pushBreakdownRows(388-429)addEmptySeparatorRow(585-588)formatTotalsRow(559-578)
apps/pi/src/_pi-agent.ts (2)
apps/pi/src/_types.ts (1)
isoTimestampSchema(4-8)apps/pi/src/_consts.ts (4)
PI_AGENT_DIR_ENV(6-6)USER_HOME_DIR(4-4)DEFAULT_PI_AGENT_PATH(8-8)PI_AGENT_SESSIONS_DIR_NAME(7-7)
apps/pi/src/commands/monthly.ts (4)
apps/pi/src/commands/index.ts (1)
monthlyCommand(2-2)apps/ccusage/src/data-loader.ts (1)
loadMonthlyUsageData(1065-1073)apps/pi/src/data-loader.ts (1)
loadPiAgentMonthlyData(376-412)packages/terminal/src/table.ts (5)
createUsageReportTable(462-519)formatUsageDataRow(528-551)pushBreakdownRows(388-429)addEmptySeparatorRow(585-588)formatTotalsRow(559-578)
apps/pi/src/_consts.ts (1)
apps/ccusage/src/_consts.ts (1)
USER_HOME_DIR(38-38)
🔇 Additional comments (43)
apps/pi/README.md (1)
1-62: Documentation looks good!The README provides clear installation instructions, usage examples, and explains the integration between Claude Code and pi-agent data sources. The structure is well-organized and user-friendly.
apps/pi/eslint.config.js (1)
1-12: ESLint configuration is correct.The config properly enforces the
test/no-importing-vitest-globalsrule, which aligns with the project's use of vitest globals being available without imports.apps/pi/vitest.config.ts (1)
1-9: Vitest configuration is correct.The config properly enables globals and includes source files for in-source testing, which aligns with the project's testing patterns.
apps/pi/tsconfig.json (1)
1-33: TypeScript configuration is correct.The config properly enables strict mode, bundler module resolution, and vitest types, all of which align with the project's coding standards.
apps/pi/src/commands/index.ts (1)
1-3: Exports are correct.The barrel export pattern is appropriate here, and the use of
.tsextensions aligns with the project's coding guidelines.apps/pi/src/index.ts (1)
1-34: CLI entrypoint structure is well-designed.The Gunshi-based CLI setup with subcommands and a default main command follows good patterns. The shebang, imports, and top-level await are all correctly implemented.
apps/pi/src/_consts.ts (1)
1-8: Constants are correctly defined.The path and environment variable constants follow the project's naming conventions and align with the similar pattern used in
apps/ccusage/src/_consts.ts. The use ofhomedir()andpath.join()ensures cross-platform compatibility.apps/pi/package.json (1)
1-89: Package configuration looks good.All runtime dependencies are correctly placed in
devDependenciesas required for bundled CLIs. ThepublishConfigproperly overrides the entry points for distribution. The workspace references and catalog usage are consistent with the monorepo patterns.One observation:
enginesspecifies>=20.19.4for users whiledevEnginesspecifies^24.11.0for contributors. This is a reasonable setup where the package supports a broader Node range for consumers while development requires a newer version.packages/terminal/src/table.ts (2)
325-350: Well-structured model name formatting extensions.The recursive handling for
[pi]prefix and the new regex patterns foranthropic/prefix and date-suffix-less models are correctly implemented. The ordering of pattern checks is appropriate:
- Check for
[pi]prefix first and recursively format- Check
anthropic/prefix with dot notation- Check claude with date suffix (existing)
- Fallback to claude without date suffix (new)
1003-1018: Good test coverage for new formatting patterns.The tests comprehensively cover the new model name formats: pi-agent prefix, anthropic/ prefix with dot notation, models without date suffix, and the combined case. All assertions are correct.
apps/pi/src/commands/daily.ts (2)
1-7: Imports follow project conventions.Correct use of
.tsextension for local imports and proper use ofccusage/loggerinstead ofconsole.log. Based on learnings.
56-84: Clean data loading and merging implementation.Good use of
Promise.allfor concurrent loading. The sorting logic correctly handles primary ordering by date and secondary ordering by source. The source labeling approach is clear.apps/pi/tsdown.config.ts (1)
1-25: Build configuration is well-structured.The tsdown configuration follows monorepo conventions:
- ESM output with tree-shaking and DCE-only minification
- Type declarations generated via tsgo
- Test code stripped via
import.meta.vitestdefinition- Package.json sorted on successful build
apps/pi/src/commands/monthly.ts (2)
1-7: Imports follow project conventions.Consistent with
daily.ts- uses.tsextension for local imports and proper logger usage.
47-153: Implementation is correct and consistent with daily command.The monthly command follows the same well-structured pattern as the daily command. The logic for loading, merging, sorting, and rendering is sound.
apps/pi/src/_pi-agent.ts (10)
1-11: LGTM!Imports are well-organized and correctly use
.tsextensions for local imports as per coding guidelines.
13-36: LGTM!Schema definitions using valibot are well-structured with proper optional field handling. The nested usage schema correctly models the Pi Agent message format.
38-47: LGTM!The type guard correctly validates all required conditions for a valid usage entry, including the null/undefined type check allowing both
nulland'message'types.
49-53: LGTM!Session ID extraction handles both formats (with and without timestamp prefix) correctly.
55-63: LGTM!Cross-platform path normalization and safe fallback to 'unknown' when the sessions segment is not found or has no following segment.
65-91: LGTM!The priority order (custom path → env variable → default) is well-implemented with proper directory existence checks. Returns empty array when no valid path is found.
93-127: LGTM!Transform function correctly normalizes Pi Agent usage data to the expected format. The totalTokens fallback calculation properly includes all token types, and the
[pi]prefix on model names provides clear source identification.
151-214: LGTM!Good coverage of edge cases: user messages, non-message types, missing usage, and undefined type with valid assistant usage.
217-243: LGTM!Tests properly cover session ID extraction and project extraction with appropriate edge cases.
245-315: LGTM!Comprehensive tests for
transformPiAgentUsagecovering the happy path, totalTokens calculation fallback, and invalid entry handling.apps/pi/src/commands/session.ts (7)
1-8: LGTM!Imports are well-organized with proper
.tsextension for the local import. Good use of the terminal table utilities from the shared package.
10-47: LGTM!Command definition is well-structured with clear descriptions and sensible defaults. The args align with the other commands (daily, monthly) for consistency.
48-60: LGTM!Good use of
Promise.allfor parallel data loading. The type assertion fororderis appropriate given the CLI validation.
62-77: LGTM!Source tagging and empty data handling are correctly implemented. The early exit with
process.exit(0)is appropriate for CLI behavior.
79-98: LGTM!Sorting and totals accumulation are correctly implemented. The comparison function properly respects the order option.
114-133: LGTM!Good implementation of row formatting with source labels and project name truncation. The breakdown rows are conditionally added based on the
--breakdownflag.
135-146: Replace hardcoded column count with a constant or derive it from the table structure.The value
8is correct for the current configuration, but hardcoding it is fragile. IfincludeLastActivityis added to this command's config later, the count must be updated to9or the separator row will be misaligned. Use a constant likeTABLE_COLUMN_COUNT(as seen inapps/codex) or derive the count from the table object to maintain consistency with future changes.apps/pi/src/data-loader.ts (11)
1-11: LGTM!Imports are well-organized with correct
.tsextension for local imports. Good choice ofnode:readlinefor streaming JSONL processing.
13-80: LGTM!Type definitions are comprehensive and well-structured. The
Sourcetype and the*WithSourcetypes provide clear contracts for the data shapes.
82-98: LGTM!Good streaming implementation using
readline.createInterfacewithcrlfDelay: Infinityfor proper line ending handling. The processor callback pattern is flexible.
100-110: LGTM!Simple and effective glob wrapper that collects files from multiple base paths.
112-138: LGTM!Date utilities are well-implemented with proper timezone handling using
Intl.DateTimeFormat. Theen-CAlocale gives ISO-like date format (YYYY-MM-DD).
152-209: LGTM!Core data loading function correctly implements:
- Early return for empty paths/files
- Deduplication via hash set
- Silent skipping of invalid/malformed lines (per coding guidelines)
- Proper validation with valibot
safeParse
211-290: LGTM!Aggregation and totals calculation helpers are well-factored with clear separation of concerns.
292-327: LGTM!Daily data loader correctly filters by date range before grouping and sorts results according to the order option.
329-374: LGTM!Session data loader correctly:
- Uses null byte separator for composite key (safe for typical paths/IDs)
- Computes lastActivity from timestamps
- Filters by date range based on lastActivity
- Sorts results by lastActivity
348-350: Unreachable edge case, but consider adding a guard.The
sessionEntriesarray is guaranteed to have at least one element when this code is reached (since entries are grouped by key and only non-empty groups are iterated). However, TypeScript can't infer this, hence thesessionEntries[0]?.timestamp ?? ''fallback. The current implementation is safe.
376-412: LGTM!Monthly data loader correctly aggregates by month (YYYY-MM format) with proper date range filtering and sorting.
| async function run(): Promise<void> { | ||
| let args = process.argv.slice(2); | ||
| if (args[0] === 'ccusage-pi') { | ||
| args = args.slice(1); | ||
| } | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Add safety check before accessing args[0].
The code accesses args[0] without first checking if the array is non-empty. While unlikely in practice, this could cause issues if the CLI is invoked without arguments.
Suggested fix
async function run(): Promise<void> {
let args = process.argv.slice(2);
- if (args[0] === 'ccusage-pi') {
+ if (args.length > 0 && args[0] === 'ccusage-pi') {
args = args.slice(1);
}🤖 Prompt for AI Agents
In apps/pi/src/index.ts around lines 18 to 23, the code reads args[0] without
ensuring the args array has at least one element; add a guard to check
args.length > 0 before accessing args[0] (e.g., if (args.length > 0 && args[0]
=== 'ccusage-pi') { args = args.slice(1); }) so the branch only runs when an
argument exists and avoids runtime issues when the CLI is invoked with no args.
|
@nicobailon thanks for your contribution. |
ccusage
@ccusage/codex
@ccusage/mcp
@ccusage/opencode
@ccusage/pi
commit: |
- Add VitePress documentation for @ccusage/pi package (overview, daily, monthly, session reports) - Add Pi-Agent section to VitePress sidebar - Create CLAUDE.md for the pi package - Add @types/bun to tsconfig.json types
- Change author from nicobailon to ryoppippi - Add nicobailon as contributor
748ac4f to
3d72df1
Compare
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
ccusage-guide | 3d72df1 | Commit Preview URL Branch Preview URL |
Jan 09 2026, 11:21 AM |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
docs/guide/pi/index.md (1)
117-126: Consider adding language specification to terminal output blocks.Three fenced code blocks displaying terminal output lack language specifications (lines 117-126, 214-225, 312-322). Adding
```textor```consoleimproves consistency with markdown best practices.📝 Proposed fix for terminal output blocks
For line 117:
-``` +```text ┌────────────────────┬────────────┬─────────────┬───────────┬───────────┬────────┬─────────┐Apply similar changes to lines 214 and 312.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (4)
apps/pi/CLAUDE.mdapps/pi/package.jsonapps/pi/tsconfig.jsondocs/guide/pi/index.md
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/pi/tsconfig.json
🧰 Additional context used
📓 Path-based instructions (2)
docs/guide/**/*.md
📄 CodeRabbit inference engine (docs/CLAUDE.md)
docs/guide/**/*.md: Place screenshots immediately after the main heading (H1) on guide pages that include screenshots
User-facing guides should live under the docs/guide/ directory
Files:
docs/guide/pi/index.md
docs/**/*.md
📄 CodeRabbit inference engine (docs/CLAUDE.md)
docs/**/*.md: Use image paths relative to the docs public root (e.g., /screenshot.png for assets in /docs/public/)
Always include descriptive alt text for images and screenshots
For code blocks that should skip ESLint parsing (e.g., containing ...), add immediately before the code block
docs/**/*.md: Screenshot placement: Always place screenshots immediately after the main heading (H1) in documentation pages
Always include descriptive alt text for accessibility on all images in documentation
Use relative paths like/screenshot.pngfor images stored in/docs/public/
Files:
docs/guide/pi/index.md
🧠 Learnings (13)
📓 Common learnings
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/opencode/CLAUDE.md:0-0
Timestamp: 2026-01-09T11:07:17.610Z
Learning: Applies to apps/opencode/**/*.{ts,tsx,js,jsx} : Reuse shared packages (`ccusage/terminal`, `ccusage/internal`) wherever possible
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.293Z
Learning: Treat Codex as a sibling to apps/ccusage; reuse shared packages, command names, and flag semantics; diverge only when Codex-specific data requires it and document inline
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : In tests, use current Claude 4 models (sonnet-4, opus-4)
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-09T11:07:06.346Z
Learning: All projects under `apps/` ship as bundled CLIs/binaries. Treat runtime dependencies as bundled assets: list everything in each app's `devDependencies` (never `dependencies`) so the bundler owns the runtime payload.
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/**/package.json : Add dependencies as devDependencies unless explicitly required otherwise
Applied to files:
apps/pi/package.json
📚 Learning: 2026-01-09T11:07:17.610Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/opencode/CLAUDE.md:0-0
Timestamp: 2026-01-09T11:07:17.610Z
Learning: Applies to apps/opencode/**/*.{ts,tsx,js,jsx} : Reuse shared packages (`ccusage/terminal`, `ccusage/internal`) wherever possible
Applied to files:
apps/pi/package.jsonapps/pi/CLAUDE.md
📚 Learning: 2025-09-17T18:29:15.764Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/mcp/CLAUDE.md:0-0
Timestamp: 2025-09-17T18:29:15.764Z
Learning: Applies to apps/mcp/**/package.json : Add new dependencies as `devDependencies` unless explicitly requested otherwise
Applied to files:
apps/pi/package.json
📚 Learning: 2025-09-18T16:07:16.293Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/codex/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:07:16.293Z
Learning: Applies to apps/codex/**/package.json : Package Codex as a bundled CLI and keep every runtime dependency in devDependencies so the bundle includes shipped code
Applied to files:
apps/pi/package.json
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/**/package.json : Because the CLI is bundled, keep all runtime libraries in devDependencies so the bundler captures them
Applied to files:
apps/pi/package.json
📚 Learning: 2026-01-09T11:07:17.610Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/opencode/CLAUDE.md:0-0
Timestamp: 2026-01-09T11:07:17.610Z
Learning: Applies to apps/opencode/**/package.json : Keep every runtime dependency in `devDependencies` because OpenCode is packaged as a bundled CLI
Applied to files:
apps/pi/package.json
📚 Learning: 2026-01-09T11:07:06.346Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-09T11:07:06.346Z
Learning: For package scope commits, use the package directory name (e.g., `feat(terminal):`, `fix(ui):`)
Applied to files:
apps/pi/package.json
📚 Learning: 2026-01-09T11:07:06.346Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-09T11:07:06.346Z
Learning: All projects under `apps/` ship as bundled CLIs/binaries. Treat runtime dependencies as bundled assets: list everything in each app's `devDependencies` (never `dependencies`) so the bundler owns the runtime payload.
Applied to files:
apps/pi/package.json
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Only export symbols that are actually used by other modules
Applied to files:
apps/pi/package.json
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : Use `fs-fixture` with `createFixture()` to simulate Claude data in tests
Applied to files:
apps/pi/package.jsonapps/pi/CLAUDE.md
📚 Learning: 2026-01-09T11:07:06.346Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-09T11:07:06.346Z
Learning: For package-specific guidance when working within a package directory, check the relevant package's CLAUDE.md file
Applied to files:
apps/pi/CLAUDE.md
📚 Learning: 2025-09-18T16:06:37.474Z
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: apps/ccusage/CLAUDE.md:0-0
Timestamp: 2025-09-18T16:06:37.474Z
Learning: Applies to apps/ccusage/src/**/*.ts : In tests, use current Claude 4 models (sonnet-4, opus-4)
Applied to files:
apps/pi/CLAUDE.md
🪛 LanguageTool
apps/pi/CLAUDE.md
[grammar] ~69-~69: Ensure spelling is correct
Context: ...ime Dependencies:** - ccusage - Main ccusage package (workspace dependency) - `@ccus...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
docs/guide/pi/index.md
[grammar] ~21-~21: Ensure spelling is correct
Context: ...--help ``` ::: warning
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🪛 markdownlint-cli2 (0.18.1)
docs/guide/pi/index.md
117-117: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
214-214: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
312-312: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: lint-check
🔇 Additional comments (3)
apps/pi/package.json (1)
1-92: LGTM! Package structure follows established patterns.The package manifest correctly follows the project's conventions:
- All runtime dependencies are in
devDependencies(as required for bundled CLIs)- Proper separation between dev (
src/index.ts) and published (dist/index.js) entry pointspublishConfigappropriately overrides paths for distributionBased on learnings, this follows the established pattern where bundled CLI apps under
apps/list all dependencies indevDependenciesso the bundler controls the runtime payload.apps/pi/CLAUDE.md (1)
1-121: LGTM! Clear and comprehensive package documentation.The documentation effectively covers:
- Package overview and command usage
- Architecture and data source integration
- Testing approach and code style guidelines
- Environment variables and exports
The reference to reusing shared packages (
@ccusage/terminal,@ccusage/internal) aligns with established learnings.docs/guide/pi/index.md (1)
1-395: LGTM! Comprehensive and well-structured user guide.The documentation provides:
- Clear installation and usage instructions
- Detailed command examples with options
- Sample outputs in both table and JSON formats
- Environment variable configuration
- Source labeling explanation for combined data
The guide effectively communicates the Pi-Agent integration features to users.
* chore(deps/mcp): add tsgo * chore(deps): update dependency @praha/byethrow-mcp to ^0.1.7 (ryoppippi#707) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @hono/mcp to ^0.1.5 (ryoppippi#711) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @types/bun to ^1.3.1 (ryoppippi#708) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251104.1 (ryoppippi#712) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * ci: use slim for check pr title (ryoppippi#713) * ci: use slim for spell-check/release (ryoppippi#714) * fix(terminal): increase minimum width for numeric columns to prevent truncation (ryoppippi#701) Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> * fix(ccusage): use streaming to handle large JSONL files (ryoppippi#706) Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> * fix(ccusage): resolve ESLint violations in data-loader.ts (ryoppippi#715) * chore: release v17.1.4 * ci: remove npm upgrade (ryoppippi#716) * chore(deps): update dependency @hono/node-server to ^1.19.6 (ryoppippi#719) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Revert "fix(terminal): increase minimum width for numeric columns to prevent …" (ryoppippi#722) This reverts commit 2235f2a. * chore: release v17.1.5 * docs: dy -> dt * docs(ccusage): remove ClaudeLog badge from README The ClaudeLog badge link has been removed from the repository badges section in the README. This simplifies the badge collection to focus on the most relevant project information. * chore: release v17.1.6 * chore: update runtime versions (node ^24.11.0, bun ^1.3.2) * chore(deps): update @types/bun to ^1.3.2 and add @types/node ^24.10.1 * chore: fix build config to keep usin .js ext (ryoppippi#734) * chore(deps): update dependency eslint-plugin-format to ^1.0.2 (ryoppippi#731) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update actions/checkout action to v5.0.1 (ryoppippi#730) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * ci: migrate GitHub Actions to ubuntu-slim and ubuntu-24.04-arm runners (ryoppippi#733) * chore: remove lsmcp integration (ryoppippi#728) * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251125.1 (ryoppippi#720) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @types/bun to ^1.3.3 (ryoppippi#736) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251128.1 (ryoppippi#737) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore: update pnpm * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251204.1 (ryoppippi#741) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency nano-spawn to ^1.0.3 (ryoppippi#742) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(ccusage): support Opus 4.5 pricing from Bedrock-prefixed models (ryoppippi#743) * fix(ccusage): support Opus 4.5 pricing from Bedrock-prefixed models LiteLLM lists Opus 4.5 models with anthropic.claude- prefix (e.g., anthropic.claude-opus-4-5-20251101-v1:0) but the isClaudeModel filter only kept models starting with claude-. This adds support for anthropic.claude- and anthropic/claude- prefixes to include Bedrock-format models in the pricing dataset. * chore: remove unnecessary tests * chore: release v17.1.7 * chore(deps): update MCP SDK to v1.24.3 and Zod to v4 (ryoppippi#744) * chore(deps): update @modelcontextprotocol/sdk to v1.24.3 and zod to v4.1.13 Update MCP SDK from v1.18.1 to v1.24.3 and Zod from v3.25.67 to v4.1.13. The MCP SDK update introduces a breaking change in error handling behaviour: invalid arguments and unknown tool calls now return `{ isError: true }` responses instead of rejecting the Promise. * chore(mcp): reformat package.json with spaces and add README.md to files Reformatted package.json from tabs to spaces and added README.md to the files array for npm distribution. * test(mcp): update error handling tests for MCP SDK v1.24.3 The MCP SDK v1.24.3 changed error handling behaviour: invalid arguments, invalid date formats, and unknown tool names now return a response with `{ isError: true, content: [...] }`. Updated three error handling tests to check for isError response: - should handle tool call with invalid arguments - should handle tool call with invalid date format - should handle tool call with unknown tool name * fix(mcp): update z.record() calls for Zod v4 API Zod v4 requires z.record() to take two arguments: key schema and value schema. Updated codexDailyRowSchema and codexMonthlyRowSchema to use z.record(z.string(), codexModelUsageSchema). * test(mcp): use assert for type error * chore: release v17.1.8 * refactor: use oxfmt for JSON schema formatting and remove OFFLINE env var (ryoppippi#746) * build: migrate CI/CD to Nix-based development environment (ryoppippi#747) * chore: update vitest to 4.0.15 (ryoppippi#748) * chore(renovate): enable nix * feat(ccusage): support context_window field from Claude Code statusline hook (ryoppippi#749) * feat(ccusage): support context_window field from Claude Code statusline hook Claude Code now provides context_window data in its statusline hook JSON, containing total_input_tokens, total_output_tokens, and context_window_size. This change: - Adds context_window field to statuslineHookJsonSchema in _types.ts - Updates statusline command to prefer context_window data when available - Falls back to existing transcript-based calculation when not provided - Refactors context info formatting into reusable helper function - Uses Result type pattern for consistent functional error handling The context_window data from Claude Code is more accurate than parsing the transcript file, as it reflects the actual token counts used by the API. * docs: add context_window reference to statusline guide Add note about Claude Code's context_window data being used for accurate token counts, with link to official documentation. * chore(ccusage): fix typo colour to color * chore: release v17.2.0 * chore(nix): add typos-lsp * chore(nix): update * chore(deps): update dependency @hono/node-server to ^1.19.7 (ryoppippi#751) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(nix): migrate from flake-utils to flake-parts (ryoppippi#753) Replace flake-utils with flake-parts for Nix flake configuration. flake-parts provides a more modular and extensible approach using the NixOS module system, enabling better composition and reusability for future enhancements such as package definitions or NixOS modules. Key changes: - Replace eachDefaultSystem pattern with perSystem module - Explicitly define supported systems (x86_64/aarch64 linux/darwin) - Use mkFlake entry point with inputs binding pattern - Update flake.lock with new dependencies * chore(deps): update dependency @types/bun to ^1.3.4 (ryoppippi#752) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(typos): enable hidden (ryoppippi#756) * chore(deps): update dependency @types/bun to ^1.3.5 (ryoppippi#761) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251219.1 (ryoppippi#762) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251225.1 (ryoppippi#772) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency changelogithub to ^13.16.1 (ryoppippi#773) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore: release v17.2.1 * chore: format * feat(opencode): add OpenCode CLI package (ryoppippi#758) Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> * chore: update pnpm-lock.yaml * feat: pi agent integration (ryoppippi#760) Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> * chore(opencode): add PR contributor to package.json (ryoppippi#781) * feat(ccusage)!: remove deprecated blocks --live monitor (ryoppippi#782) * docs(pi): add @ccusage/pi to README and overhaul pi package docs (ryoppippi#783) * refactor(pi): remove Claude Code integration from pi package (ryoppippi#784) * chore: migrate MCP servers for docs to docs packages (ryoppippi#786) * feat(amp): add Amp CLI usage analysis package (ryoppippi#785) * refactor: migrate formatting from ESLint stylistic to oxfmt (ryoppippi#787) * chore: release v18.0.0 * Revert "chore: release v18.0.0" This reverts commit 8f4afe8. * chore: release v18.0.1 * fix(amp,opencode): add fixedExtension option to output .js extension Both amp and opencode were missing the fixedExtension: false option, causing tsdown to output .mjs files instead of .js files expected by package.json main/module fields. * chore: git checkout after release * chore: release v18.0.2 * fix(opencode): add logger to LiteLLMPricingFetcher (ryoppippi#789) * fix(amp,opencode,codex,pi): add dateFormatter to prevent date truncation (ryoppippi#788) * refactor(pi): remove ccusage dependency (ryoppippi#790) * chore: update lockfile to match package.json Sync pnpm-lock.yaml with removal of ccusage@workspace:* dependency from apps/pi that was made in refactor(pi): remove ccusage dependency (ryoppippi#790). * chore: release v18.0.3 * docs: add @ccusage/amp to README Add Amp Usage Analyzer to the ccusage Family section and Related Tools installation commands. * docs: update @ccusage/pi description Update pi-agent description to reflect current functionality - now tracks pi-agent sessions only, not unified Claude Code + pi-agent. Also fix the pi-agent repository URL. * docs: fix outdated README descriptions - Remove "live monitoring" reference (blocks --live was removed) - Update pi-agent comment to match new description * docs: update outdated documentation - apps/pi/README.md: Update to reflect pi-agent only tracking (Claude Code integration was removed in ryoppippi#784) - docs/guide/index.md: Replace Live Monitoring with Statusline Integration (blocks --live was removed in v18) - docs/guide/getting-started.md: Update references from blocks --live to statusline command * docs(guide): improve statusline setup example Use jq command to show how to add statusline to Claude Code settings, rather than showing an unusable standalone command. * docs: fix British English spellings to American English * chore: release v18.0.4 * docs: fix OpenCode description - not a Claude Code fork * chore: release v18.0.5 * chore: remove flake-parts dependency (ryoppippi#793) Simplify flake.nix by removing flake-parts and using plain Nix. The project only defines a single devShell, which doesn't require the complexity of flake-parts. Multi-system support is achieved with a simple forAllSystems helper using nixpkgs.lib.genAttrs. This reduces dependencies and makes the flake more straightforward. * chore: add repository directory field to app packages (ryoppippi#794) Add the 'directory' field to the repository object in each app's package.json. This helps npm and GitHub generate correct links to the source code location within the monorepo structure. Affected packages: - apps/amp - apps/ccusage - apps/codex - apps/mcp - apps/opencode - apps/pi * chore: use mkShellNoCC for lighter dev shell (ryoppippi#796) * docs: fix OpenCode description in documentation (ryoppippi#808) OpenCode is a terminal-based AI coding assistant, not a fork of Claude Code. This corrects the description in the documentation guide that was missed in the previous README fixes. * docs: add BUN_BE_BUN=1 claude x / opencode x execution method (ryoppippi#814) Add documentation for running ccusage and @ccusage/opencode via the native Claude Code and OpenCode CLIs using the BUN_BE_BUN=1 environment variable. This leverages Bun's standalone executable feature to expose the full Bun CLI capabilities. Changes: - installation.md: Add detailed explanation with links to Bun and Claude Code documentation - getting-started.md: Add claude x option to Quick Start - index.md: Mention claude x in Ultra-Small Bundle Size section - statusline.md: Add claude x option to settings.json examples - opencode/index.md: Add opencode x option with native version note * docs(pi): fix pi-agent repository link (ryoppippi#800) The link was incorrectly changed to a non-existent repository (nicobailon/pi-agent) in f86d0f3. Restore the correct link to badlogic/pi-mono. * chore: add pnpm security settings for supply chain attack prevention (ryoppippi#828) * chore(deps): update actions/checkout action to v6.0.2 (ryoppippi#837) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore: watch pnpm lockfiles * chore: migrate to standard engines field and upgrade Bun (ryoppippi#851) Moved runtime requirements from non-standard `devEngines` field to the standard npm `engines` field across all package.json files (root, apps, and docs). This aligns with npm conventions and makes runtime dependencies more discoverable by package managers. Also upgraded Bun runtime from ^1.3.2 to ^1.3.9 across all packages for improved performance and bug fixes. Updated pnpm-lock.yaml to reflect the new engines field structure and Bun version bump. * chore(deps): update cachix/install-nix-action action to v31.9.1 (ryoppippi#859) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(codex): fallback when direct model pricing is zero (ryoppippi#854) * chore: release v18.0.6 * fix: replace non-standard engines.runtime array with standard engines fields (ryoppippi#863) The dc83c23 commit migrated from `devEngines` to `engines` but kept the devEngines array-of-objects format inside `engines.runtime`, which is not a valid npm/pnpm/bun field. No package manager reads or validates it. Replace with the standard engines format across all packages: "engines": { "node": ">=20.19.4", "bun": ">=1.3.9" } Fixes: ryoppippi#862 * Revert "chore: migrate to standard engines field and upgrade Bun (ryoppippi#851)" This reverts commit dc83c23. * chore: release v18.0.7 * chore: remove devEngines from each packages * chore: update pnpm tp 10.30.1 * chore: update node and bun * fix(amp): fallback missing model pricing to zero-cost in codex/amp (ryoppippi#858) * fix: fallback missing model pricing to zero-cost in codex/amp * refactor(codex,amp): use `as const satisfies` for zero-cost pricing constants Replace explicit type annotations with `as const satisfies ModelPricing` for FREE_MODEL_PRICING (codex) and ZERO_MODEL_PRICING (amp) to get narrower literal types while maintaining type safety. --------- Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> * chore: release v18.0.8 * fix: use os.homedir() and path.join() for Windows path compatibility (ryoppippi#874) * fix: use os.homedir() and path.join() for Windows path compatibility - Replace process.env.HOME with os.homedir() in amp and opencode - Use path.join() instead of template literal path concatenation in ccusage _consts.ts - Fix test assertions to use cross-platform path separators * chore: remove .claude from .gitignore * chore: release v18.0.9 * feat(ccusage): support Claude Code fast mode with separate tracking and 6x pricing (ryoppippi#886) * feat(internal): support fast mode pricing multiplier in LiteLLM pricing Claude Code's fast mode (toggled with /fast) records a "speed" field in the usage object of JSONL log entries. Fast mode tokens are charged at a higher rate defined by LiteLLM's provider_specific_entry.fast multiplier (currently 6x for claude-opus-4-6). Changes to the pricing infrastructure: - Add provider_specific_entry schema to liteLLMModelPricingSchema to parse the fast multiplier from LiteLLM's pricing data - Extend calculateCostFromTokens with an optional speed parameter that applies the fast multiplier when speed is "fast" - When provider_specific_entry.fast is absent, default to 1x (no change) Add tests for fast multiplier application, fallback to 1x, and standard speed passthrough. * feat(ccusage): separate fast mode usage from standard in all reports Parse the "speed" field from Claude Code JSONL log entries (message.usage.speed) and treat fast mode as a distinct model variant for aggregation and reporting. When speed is "fast", the model name is suffixed with "-fast" (e.g., claude-opus-4-6-fast) so that fast mode tokens and costs are tracked separately from standard mode across all report types: daily, session, monthly, weekly, and blocks. Cost calculation for fast mode entries uses the 6x pricing multiplier from LiteLLM's provider_specific_entry.fast field, ensuring accurate cost reporting for the higher-priced fast tier. Entries without a speed field are treated as standard mode, maintaining backward compatibility with older log formats. Add tests for getDisplayModelName, fast mode cost calculation with 6x multiplier, and loadDailyUsageData integration with fast/standard separation. * chore: release v18.0.10 * chore(oxfmt): use unpkg.com for configuration schema * chore(pnpm): enable enableGlobalVirtualStore * docs(guide): remove broken `claude x` installation method (ryoppippi#889) * chore: guard direnv flake usage with nix availability check Wrap `use flake` in `if has nix` conditional so that contributors without Nix installed do not get errors when direnv loads the .envrc. * chore(ci): add cache-nix-action * chore(docs): upgrade VitePress to 2.0.0-alpha.17 and update docs dependencies - VitePress: ^1.6.4 → 2.0.0-alpha.17 - vitepress-plugin-group-icons: ^1.6.3 → ^1.7.2 - vitepress-plugin-llms: ^1.7.3 → ^1.12.0 - typedoc: ^0.28.10 → ^0.28.18 - typedoc-plugin-markdown: ^4.8.1 → ^4.11.0 - @ryoppippi/vite-plugin-cloudflare-redirect: ^1.1.2 → ^1.1.3 (adds Vite 8 support) - Remove enableGlobalVirtualStore (broke typedoc plugin resolution) - Add minimumReleaseAgeExclude for newly published packages * fix(docs): resolve markdown-it type mismatch in VitePress config VitePress 2.0.0-alpha.17 introduced a type incompatibility between its bundled @types/markdown-it and the types expected by vitepress-plugin-group-icons. Cast groupIconMdPlugin to `any` with an eslint-disable to fix the CI typecheck failure. * chore(ccusage): sync codex and claude direnv environment settings * chore: upgrade vitest to v4.1 and add workspace config with GitHub integration (ryoppippi#911) - Bump vitest from ^4.0.15 to ^4.1.2 in pnpm-workspace.yaml catalog - Add root vitest.config.ts with `projects` globs to discover all sub-package configs (apps/*/vitest.config.ts, packages/*/vitest.config.ts) - Enable `github-actions` reporter automatically when running in CI for inline test failure annotations on PRs - Update root test script from per-package `pnpm run --filter '*' test` to unified `TZ=UTC vitest run` via the workspace - Add vitest as root devDependency for the workspace runner --------- Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Tyson Cung <45380903+tysoncung@users.noreply.github.com> Co-authored-by: mkusaka <hinoshita1992@gmail.com> Co-authored-by: Bas Nijholt <basnijholt@gmail.com> Co-authored-by: Anish De <63192115+AnishDe12020@users.noreply.github.com> Co-authored-by: Nico Bailon <nico.bailon@gmail.com> Co-authored-by: Jack Cheng <96861406+jackcpku@users.noreply.github.com> Co-authored-by: Pavel Borobov <blvp.me@gmail.com> Co-authored-by: Ivan <34831957+gulivan@users.noreply.github.com> Co-authored-by: mattn <mattn.jp@gmail.com> Co-authored-by: Omar Yusuf Abdi <s2305975@student.hb.se> Co-authored-by: Claude Code <claude@anthropic.com>
* chore(deps/mcp): add tsgo * chore(deps): update dependency @praha/byethrow-mcp to ^0.1.7 (ryoppippi#707) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @hono/mcp to ^0.1.5 (ryoppippi#711) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @types/bun to ^1.3.1 (ryoppippi#708) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251104.1 (ryoppippi#712) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * ci: use slim for check pr title (ryoppippi#713) * ci: use slim for spell-check/release (ryoppippi#714) * fix(terminal): increase minimum width for numeric columns to prevent truncation (ryoppippi#701) Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> * fix(ccusage): use streaming to handle large JSONL files (ryoppippi#706) Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> * fix(ccusage): resolve ESLint violations in data-loader.ts (ryoppippi#715) * chore: release v17.1.4 * ci: remove npm upgrade (ryoppippi#716) * chore(deps): update dependency @hono/node-server to ^1.19.6 (ryoppippi#719) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Revert "fix(terminal): increase minimum width for numeric columns to prevent …" (ryoppippi#722) This reverts commit 2235f2a. * chore: release v17.1.5 * docs: dy -> dt * docs(ccusage): remove ClaudeLog badge from README The ClaudeLog badge link has been removed from the repository badges section in the README. This simplifies the badge collection to focus on the most relevant project information. * chore: release v17.1.6 * chore: update runtime versions (node ^24.11.0, bun ^1.3.2) * chore(deps): update @types/bun to ^1.3.2 and add @types/node ^24.10.1 * chore: fix build config to keep usin .js ext (ryoppippi#734) * chore(deps): update dependency eslint-plugin-format to ^1.0.2 (ryoppippi#731) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update actions/checkout action to v5.0.1 (ryoppippi#730) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * ci: migrate GitHub Actions to ubuntu-slim and ubuntu-24.04-arm runners (ryoppippi#733) * chore: remove lsmcp integration (ryoppippi#728) * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251125.1 (ryoppippi#720) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @types/bun to ^1.3.3 (ryoppippi#736) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251128.1 (ryoppippi#737) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore: update pnpm * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251204.1 (ryoppippi#741) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency nano-spawn to ^1.0.3 (ryoppippi#742) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(ccusage): support Opus 4.5 pricing from Bedrock-prefixed models (ryoppippi#743) * fix(ccusage): support Opus 4.5 pricing from Bedrock-prefixed models LiteLLM lists Opus 4.5 models with anthropic.claude- prefix (e.g., anthropic.claude-opus-4-5-20251101-v1:0) but the isClaudeModel filter only kept models starting with claude-. This adds support for anthropic.claude- and anthropic/claude- prefixes to include Bedrock-format models in the pricing dataset. * chore: remove unnecessary tests * chore: release v17.1.7 * chore(deps): update MCP SDK to v1.24.3 and Zod to v4 (ryoppippi#744) * chore(deps): update @modelcontextprotocol/sdk to v1.24.3 and zod to v4.1.13 Update MCP SDK from v1.18.1 to v1.24.3 and Zod from v3.25.67 to v4.1.13. The MCP SDK update introduces a breaking change in error handling behaviour: invalid arguments and unknown tool calls now return `{ isError: true }` responses instead of rejecting the Promise. * chore(mcp): reformat package.json with spaces and add README.md to files Reformatted package.json from tabs to spaces and added README.md to the files array for npm distribution. * test(mcp): update error handling tests for MCP SDK v1.24.3 The MCP SDK v1.24.3 changed error handling behaviour: invalid arguments, invalid date formats, and unknown tool names now return a response with `{ isError: true, content: [...] }`. Updated three error handling tests to check for isError response: - should handle tool call with invalid arguments - should handle tool call with invalid date format - should handle tool call with unknown tool name * fix(mcp): update z.record() calls for Zod v4 API Zod v4 requires z.record() to take two arguments: key schema and value schema. Updated codexDailyRowSchema and codexMonthlyRowSchema to use z.record(z.string(), codexModelUsageSchema). * test(mcp): use assert for type error * chore: release v17.1.8 * refactor: use oxfmt for JSON schema formatting and remove OFFLINE env var (ryoppippi#746) * build: migrate CI/CD to Nix-based development environment (ryoppippi#747) * chore: update vitest to 4.0.15 (ryoppippi#748) * chore(renovate): enable nix * feat(ccusage): support context_window field from Claude Code statusline hook (ryoppippi#749) * feat(ccusage): support context_window field from Claude Code statusline hook Claude Code now provides context_window data in its statusline hook JSON, containing total_input_tokens, total_output_tokens, and context_window_size. This change: - Adds context_window field to statuslineHookJsonSchema in _types.ts - Updates statusline command to prefer context_window data when available - Falls back to existing transcript-based calculation when not provided - Refactors context info formatting into reusable helper function - Uses Result type pattern for consistent functional error handling The context_window data from Claude Code is more accurate than parsing the transcript file, as it reflects the actual token counts used by the API. * docs: add context_window reference to statusline guide Add note about Claude Code's context_window data being used for accurate token counts, with link to official documentation. * chore(ccusage): fix typo colour to color * chore: release v17.2.0 * chore(nix): add typos-lsp * chore(nix): update * chore(deps): update dependency @hono/node-server to ^1.19.7 (ryoppippi#751) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(nix): migrate from flake-utils to flake-parts (ryoppippi#753) Replace flake-utils with flake-parts for Nix flake configuration. flake-parts provides a more modular and extensible approach using the NixOS module system, enabling better composition and reusability for future enhancements such as package definitions or NixOS modules. Key changes: - Replace eachDefaultSystem pattern with perSystem module - Explicitly define supported systems (x86_64/aarch64 linux/darwin) - Use mkFlake entry point with inputs binding pattern - Update flake.lock with new dependencies * chore(deps): update dependency @types/bun to ^1.3.4 (ryoppippi#752) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(typos): enable hidden (ryoppippi#756) * chore(deps): update dependency @types/bun to ^1.3.5 (ryoppippi#761) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251219.1 (ryoppippi#762) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @typescript/native-preview to ^7.0.0-dev.20251225.1 (ryoppippi#772) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency changelogithub to ^13.16.1 (ryoppippi#773) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore: release v17.2.1 * chore: format * feat(opencode): add OpenCode CLI package (ryoppippi#758) Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> * chore: update pnpm-lock.yaml * feat: pi agent integration (ryoppippi#760) Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> * chore(opencode): add PR contributor to package.json (ryoppippi#781) * feat(ccusage)!: remove deprecated blocks --live monitor (ryoppippi#782) * docs(pi): add @ccusage/pi to README and overhaul pi package docs (ryoppippi#783) * refactor(pi): remove Claude Code integration from pi package (ryoppippi#784) * chore: migrate MCP servers for docs to docs packages (ryoppippi#786) * feat(amp): add Amp CLI usage analysis package (ryoppippi#785) * refactor: migrate formatting from ESLint stylistic to oxfmt (ryoppippi#787) * chore: release v18.0.0 * Revert "chore: release v18.0.0" This reverts commit 8f4afe8. * chore: release v18.0.1 * fix(amp,opencode): add fixedExtension option to output .js extension Both amp and opencode were missing the fixedExtension: false option, causing tsdown to output .mjs files instead of .js files expected by package.json main/module fields. * chore: git checkout after release * chore: release v18.0.2 * fix(opencode): add logger to LiteLLMPricingFetcher (ryoppippi#789) * fix(amp,opencode,codex,pi): add dateFormatter to prevent date truncation (ryoppippi#788) * refactor(pi): remove ccusage dependency (ryoppippi#790) * chore: update lockfile to match package.json Sync pnpm-lock.yaml with removal of ccusage@workspace:* dependency from apps/pi that was made in refactor(pi): remove ccusage dependency (ryoppippi#790). * chore: release v18.0.3 * docs: add @ccusage/amp to README Add Amp Usage Analyzer to the ccusage Family section and Related Tools installation commands. * docs: update @ccusage/pi description Update pi-agent description to reflect current functionality - now tracks pi-agent sessions only, not unified Claude Code + pi-agent. Also fix the pi-agent repository URL. * docs: fix outdated README descriptions - Remove "live monitoring" reference (blocks --live was removed) - Update pi-agent comment to match new description * docs: update outdated documentation - apps/pi/README.md: Update to reflect pi-agent only tracking (Claude Code integration was removed in ryoppippi#784) - docs/guide/index.md: Replace Live Monitoring with Statusline Integration (blocks --live was removed in v18) - docs/guide/getting-started.md: Update references from blocks --live to statusline command * docs(guide): improve statusline setup example Use jq command to show how to add statusline to Claude Code settings, rather than showing an unusable standalone command. * docs: fix British English spellings to American English * chore: release v18.0.4 * docs: fix OpenCode description - not a Claude Code fork * chore: release v18.0.5 * chore: remove flake-parts dependency (ryoppippi#793) Simplify flake.nix by removing flake-parts and using plain Nix. The project only defines a single devShell, which doesn't require the complexity of flake-parts. Multi-system support is achieved with a simple forAllSystems helper using nixpkgs.lib.genAttrs. This reduces dependencies and makes the flake more straightforward. * chore: add repository directory field to app packages (ryoppippi#794) Add the 'directory' field to the repository object in each app's package.json. This helps npm and GitHub generate correct links to the source code location within the monorepo structure. Affected packages: - apps/amp - apps/ccusage - apps/codex - apps/mcp - apps/opencode - apps/pi * chore: use mkShellNoCC for lighter dev shell (ryoppippi#796) * docs: fix OpenCode description in documentation (ryoppippi#808) OpenCode is a terminal-based AI coding assistant, not a fork of Claude Code. This corrects the description in the documentation guide that was missed in the previous README fixes. * docs: add BUN_BE_BUN=1 claude x / opencode x execution method (ryoppippi#814) Add documentation for running ccusage and @ccusage/opencode via the native Claude Code and OpenCode CLIs using the BUN_BE_BUN=1 environment variable. This leverages Bun's standalone executable feature to expose the full Bun CLI capabilities. Changes: - installation.md: Add detailed explanation with links to Bun and Claude Code documentation - getting-started.md: Add claude x option to Quick Start - index.md: Mention claude x in Ultra-Small Bundle Size section - statusline.md: Add claude x option to settings.json examples - opencode/index.md: Add opencode x option with native version note * docs(pi): fix pi-agent repository link (ryoppippi#800) The link was incorrectly changed to a non-existent repository (nicobailon/pi-agent) in f86d0f3. Restore the correct link to badlogic/pi-mono. * chore: add pnpm security settings for supply chain attack prevention (ryoppippi#828) * chore(deps): update actions/checkout action to v6.0.2 (ryoppippi#837) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore: watch pnpm lockfiles * chore: migrate to standard engines field and upgrade Bun (ryoppippi#851) Moved runtime requirements from non-standard `devEngines` field to the standard npm `engines` field across all package.json files (root, apps, and docs). This aligns with npm conventions and makes runtime dependencies more discoverable by package managers. Also upgraded Bun runtime from ^1.3.2 to ^1.3.9 across all packages for improved performance and bug fixes. Updated pnpm-lock.yaml to reflect the new engines field structure and Bun version bump. * chore(deps): update cachix/install-nix-action action to v31.9.1 (ryoppippi#859) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(codex): fallback when direct model pricing is zero (ryoppippi#854) * chore: release v18.0.6 * fix: replace non-standard engines.runtime array with standard engines fields (ryoppippi#863) The dc83c23 commit migrated from `devEngines` to `engines` but kept the devEngines array-of-objects format inside `engines.runtime`, which is not a valid npm/pnpm/bun field. No package manager reads or validates it. Replace with the standard engines format across all packages: "engines": { "node": ">=20.19.4", "bun": ">=1.3.9" } Fixes: ryoppippi#862 * Revert "chore: migrate to standard engines field and upgrade Bun (ryoppippi#851)" This reverts commit dc83c23. * chore: release v18.0.7 * chore: remove devEngines from each packages * chore: update pnpm tp 10.30.1 * chore: update node and bun * fix(amp): fallback missing model pricing to zero-cost in codex/amp (ryoppippi#858) * fix: fallback missing model pricing to zero-cost in codex/amp * refactor(codex,amp): use `as const satisfies` for zero-cost pricing constants Replace explicit type annotations with `as const satisfies ModelPricing` for FREE_MODEL_PRICING (codex) and ZERO_MODEL_PRICING (amp) to get narrower literal types while maintaining type safety. --------- Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> * chore: release v18.0.8 * fix: use os.homedir() and path.join() for Windows path compatibility (ryoppippi#874) * fix: use os.homedir() and path.join() for Windows path compatibility - Replace process.env.HOME with os.homedir() in amp and opencode - Use path.join() instead of template literal path concatenation in ccusage _consts.ts - Fix test assertions to use cross-platform path separators * chore: remove .claude from .gitignore * chore: release v18.0.9 * feat(ccusage): support Claude Code fast mode with separate tracking and 6x pricing (ryoppippi#886) * feat(internal): support fast mode pricing multiplier in LiteLLM pricing Claude Code's fast mode (toggled with /fast) records a "speed" field in the usage object of JSONL log entries. Fast mode tokens are charged at a higher rate defined by LiteLLM's provider_specific_entry.fast multiplier (currently 6x for claude-opus-4-6). Changes to the pricing infrastructure: - Add provider_specific_entry schema to liteLLMModelPricingSchema to parse the fast multiplier from LiteLLM's pricing data - Extend calculateCostFromTokens with an optional speed parameter that applies the fast multiplier when speed is "fast" - When provider_specific_entry.fast is absent, default to 1x (no change) Add tests for fast multiplier application, fallback to 1x, and standard speed passthrough. * feat(ccusage): separate fast mode usage from standard in all reports Parse the "speed" field from Claude Code JSONL log entries (message.usage.speed) and treat fast mode as a distinct model variant for aggregation and reporting. When speed is "fast", the model name is suffixed with "-fast" (e.g., claude-opus-4-6-fast) so that fast mode tokens and costs are tracked separately from standard mode across all report types: daily, session, monthly, weekly, and blocks. Cost calculation for fast mode entries uses the 6x pricing multiplier from LiteLLM's provider_specific_entry.fast field, ensuring accurate cost reporting for the higher-priced fast tier. Entries without a speed field are treated as standard mode, maintaining backward compatibility with older log formats. Add tests for getDisplayModelName, fast mode cost calculation with 6x multiplier, and loadDailyUsageData integration with fast/standard separation. * chore: release v18.0.10 * chore(oxfmt): use unpkg.com for configuration schema * chore(pnpm): enable enableGlobalVirtualStore * docs(guide): remove broken `claude x` installation method (ryoppippi#889) * chore: guard direnv flake usage with nix availability check Wrap `use flake` in `if has nix` conditional so that contributors without Nix installed do not get errors when direnv loads the .envrc. * chore(ci): add cache-nix-action * chore(docs): upgrade VitePress to 2.0.0-alpha.17 and update docs dependencies - VitePress: ^1.6.4 → 2.0.0-alpha.17 - vitepress-plugin-group-icons: ^1.6.3 → ^1.7.2 - vitepress-plugin-llms: ^1.7.3 → ^1.12.0 - typedoc: ^0.28.10 → ^0.28.18 - typedoc-plugin-markdown: ^4.8.1 → ^4.11.0 - @ryoppippi/vite-plugin-cloudflare-redirect: ^1.1.2 → ^1.1.3 (adds Vite 8 support) - Remove enableGlobalVirtualStore (broke typedoc plugin resolution) - Add minimumReleaseAgeExclude for newly published packages * fix(docs): resolve markdown-it type mismatch in VitePress config VitePress 2.0.0-alpha.17 introduced a type incompatibility between its bundled @types/markdown-it and the types expected by vitepress-plugin-group-icons. Cast groupIconMdPlugin to `any` with an eslint-disable to fix the CI typecheck failure. * chore(ccusage): sync codex and claude direnv environment settings * chore: upgrade vitest to v4.1 and add workspace config with GitHub integration (ryoppippi#911) - Bump vitest from ^4.0.15 to ^4.1.2 in pnpm-workspace.yaml catalog - Add root vitest.config.ts with `projects` globs to discover all sub-package configs (apps/*/vitest.config.ts, packages/*/vitest.config.ts) - Enable `github-actions` reporter automatically when running in CI for inline test failure annotations on PRs - Update root test script from per-package `pnpm run --filter '*' test` to unified `TZ=UTC vitest run` via the workspace - Add vitest as root devDependency for the workspace runner --------- Co-authored-by: ryoppippi <1560508+ryoppippi@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Tyson Cung <45380903+tysoncung@users.noreply.github.com> Co-authored-by: mkusaka <hinoshita1992@gmail.com> Co-authored-by: Bas Nijholt <basnijholt@gmail.com> Co-authored-by: Anish De <63192115+AnishDe12020@users.noreply.github.com> Co-authored-by: Nico Bailon <nico.bailon@gmail.com> Co-authored-by: Jack Cheng <96861406+jackcpku@users.noreply.github.com> Co-authored-by: Pavel Borobov <blvp.me@gmail.com> Co-authored-by: Ivan <34831957+gulivan@users.noreply.github.com> Co-authored-by: mattn <mattn.jp@gmail.com> Co-authored-by: Omar Yusuf Abdi <s2305975@student.hb.se> Co-authored-by: Claude Code <claude@anthropic.com>
Add support for pi-agent session data as a separate
@ccusage/pipackage, enabling unified Claude Max usage tracking across both Claude Code and pi-agent clients without increasing the main ccusage bundle size.Changes
@ccusage/pipackage (apps/pi/)ccusage-pidaily,monthly,sessionccusagefor Claude Code data loading~/.pi/agent/sessions[cc]for Claude Code,[pi]for pi-agent--pi-pathoption andPI_AGENT_DIRenvironment variableUsage
Summary by CodeRabbit
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.