Skip to content

feat: pi agent integration#760

Merged
ryoppippi merged 14 commits intoryoppippi:mainfrom
nicobailon:feat/pi-agent-integration
Jan 9, 2026
Merged

feat: pi agent integration#760
ryoppippi merged 14 commits intoryoppippi:mainfrom
nicobailon:feat/pi-agent-integration

Conversation

@nicobailon
Copy link
Copy Markdown
Contributor

@nicobailon nicobailon commented Dec 20, 2025

Add support for pi-agent session data as a separate @ccusage/pi package, enabling unified Claude Max usage tracking across both Claude Code and pi-agent clients without increasing the main ccusage bundle size.

Changes

  • Create new @ccusage/pi package (apps/pi/)
  • CLI binary: ccusage-pi
  • Commands: daily, monthly, session
  • Imports from ccusage for Claude Code data loading
  • Self-contained pi-agent data loading from ~/.pi/agent/sessions
  • Combines usage data from both sources with separate rows per source
  • Source labels: [cc] for Claude Code, [pi] for pi-agent
  • Supports --pi-path option and PI_AGENT_DIR environment variable

Usage

# Install separately
npm install -g @ccusage/pi

# Show combined daily usage
ccusage-pi daily

# Show combined monthly usage
ccusage-pi monthly

# Show combined session usage
ccusage-pi session

# Custom pi-agent path
ccusage-pi daily --pi-path /path/to/sessions

# JSON output
ccusage-pi daily --json

Summary by CodeRabbit

  • New Features

    • New Pi usage-tracking CLI with daily, monthly, and session reports
    • Combined Claude Code + pi-agent data, per-entry source labels ([cc], [pi]) and colored output
    • JSON or formatted table output, optional per-entry model breakdowns, totals, sorting, date-range and timezone support, and custom pi-agent path/env var
  • Documentation

    • Added README, guide, and CLAUDE reference with install, usage examples, options, and data-source details

✏️ Tip: You can customize this high-level summary in your review settings.

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.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Dec 20, 2025

📝 Walkthrough

Walkthrough

Adds a new CLI app @ccusage/pi under apps/pi to ingest and merge usage from Claude Code and Pi-Agent, providing commands (daily, monthly, session), data loaders/parsers for Pi-Agent JSONL, packaging/build configs, docs, and terminal model-name formatting updates.

Changes

Cohort / File(s) Summary
Project scaffold & metadata
apps/pi/README.md, apps/pi/package.json, apps/pi/tsconfig.json, apps/pi/tsdown.config.ts, apps/pi/vitest.config.ts, apps/pi/eslint.config.js
Adds package manifest, build/test/lint configs, README, TypeScript and tsdown build configs, Vitest and ESLint setup, and CLI bin wiring (ccusage-pi).
Core constants & types
apps/pi/src/_consts.ts, apps/pi/src/_types.ts
Introduces runtime constants for Pi-Agent paths/dirs and an ISO timestamp Valibot schema/type.
Pi-Agent parsing & transforms
apps/pi/src/_pi-agent.ts
Adds Valibot schema for Pi-Agent messages, type guards, path/session/project extractors, transform logic to normalize usage entries, and inline tests.
Data loading & aggregation
apps/pi/src/data-loader.ts
New loader that reads Pi-Agent JSONL, validates/transforms entries, deduplicates, filters by date/timezone, and aggregates by day, session, and month with model breakdowns and totals; exports loader APIs/types.
CLI commands
apps/pi/src/commands/daily.ts, apps/pi/src/commands/monthly.ts, apps/pi/src/commands/session.ts, apps/pi/src/commands/index.ts
Adds three Gunshi commands that load combined Claude Code + Pi-Agent data, sort/filter/aggregate, and output JSON or formatted tables with optional breakdowns and source labels.
CLI entrypoint
apps/pi/src/index.ts
Adds executable entrypoint wiring subcommands and invoking the CLI.
Terminal formatting
packages/terminal/src/table.ts
Extends model-name formatting to handle [pi] prefixes, anthropic/claude dot-notation and no-date Claude patterns; adds tests.
Docs
apps/pi/CLAUDE.md, docs/guide/pi/index.md
Adds package and user-facing documentation describing installation, commands, data sources, examples, and integration notes.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I hopped through logs at break of day,
Merging Claude and Pi along the way,
Tokens tallied, sessions bright,
Daily, monthly, by candlelight,
ccusage-pi digs up the play ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: pi agent integration' accurately and clearly summarizes the main change: adding a new pi-agent integration package to the codebase.

✏️ 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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 8 matches the current createUsageReportTable header 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.ts and monthly.ts share 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-5 may 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-5 or follows the standard format with dates.

apps/pi/src/commands/session.ts (1)

109-112: Enable includeLastActivity to show last activity timestamps in session table.

The session data has a lastActivity field available (used for sorting on line 80) and formatUsageDataRow accepts an optional lastActivity parameter. Including this column would provide useful context about when each session was last active.

To enable this, pass includeLastActivity: true to createUsageReportTable (line 109), pass data.lastActivity to formatUsageDataRow (line 120), update the separator row column count from 8 to 9 (line 135), and pass includeLastActivity: true to formatTotalsRow (line 137).

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 46f0aec and 0f8890f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is 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, NOT claude-4-sonnet-20250514)

Files:

  • apps/pi/tsconfig.json
  • apps/pi/src/index.ts
  • apps/pi/vitest.config.ts
  • apps/pi/src/_types.ts
  • apps/pi/src/commands/daily.ts
  • apps/pi/src/commands/index.ts
  • apps/pi/src/commands/session.ts
  • apps/pi/src/_pi-agent.ts
  • apps/pi/src/commands/monthly.ts
  • apps/pi/src/_consts.ts
  • apps/pi/package.json
  • packages/terminal/src/table.ts
  • apps/pi/tsdown.config.ts
  • apps/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.ts
  • apps/pi/vitest.config.ts
  • apps/pi/src/_types.ts
  • apps/pi/src/commands/daily.ts
  • apps/pi/src/commands/index.ts
  • apps/pi/src/commands/session.ts
  • apps/pi/eslint.config.js
  • apps/pi/src/_pi-agent.ts
  • apps/pi/src/commands/monthly.ts
  • apps/pi/src/_consts.ts
  • packages/terminal/src/table.ts
  • apps/pi/tsdown.config.ts
  • apps/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.ts
  • apps/pi/vitest.config.ts
  • apps/pi/src/_types.ts
  • apps/pi/src/commands/daily.ts
  • apps/pi/src/commands/index.ts
  • apps/pi/src/commands/session.ts
  • apps/pi/src/_pi-agent.ts
  • apps/pi/src/commands/monthly.ts
  • apps/pi/src/_consts.ts
  • packages/terminal/src/table.ts
  • apps/pi/tsdown.config.ts
  • apps/pi/src/data-loader.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use .ts extensions for local file imports (e.g., import { foo } from './utils.ts')
Prefer @praha/byethrow Result type over traditional try-catch for functional error handling
Use Result.try() for wrapping operations that may throw (JSON parsing, etc.)
Use Result.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 use Result.isFailure() and Result.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 using if (import.meta.vitest != null) blocks
CRITICAL: DO NOT use await import() dynamic imports anywhere in the codebase - this causes tree-shaking issues
CRITICAL: Never use dynamic imports with await 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 using fs-fixture with createFixture() 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.ts
  • apps/pi/vitest.config.ts
  • apps/pi/src/_types.ts
  • apps/pi/src/commands/daily.ts
  • apps/pi/src/commands/index.ts
  • apps/pi/src/commands/session.ts
  • apps/pi/src/_pi-agent.ts
  • apps/pi/src/commands/monthly.ts
  • apps/pi/src/_consts.ts
  • packages/terminal/src/table.ts
  • apps/pi/tsdown.config.ts
  • apps/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.png for 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's devDependencies (never dependencies)

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.json
  • apps/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.json
  • apps/pi/vitest.config.ts
  • apps/pi/eslint.config.js
  • apps/pi/src/_pi-agent.ts
  • apps/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.json
  • apps/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.json
  • apps/pi/src/index.ts
  • 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/**/*.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.json
  • apps/pi/vitest.config.ts
  • apps/pi/eslint.config.js
  • apps/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.json
  • apps/pi/vitest.config.ts
  • apps/pi/eslint.config.js
  • apps/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.json
  • apps/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.json
  • apps/pi/vitest.config.ts
  • apps/pi/eslint.config.js
  • apps/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.json
  • apps/pi/vitest.config.ts
  • apps/pi/eslint.config.js
  • apps/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.json
  • apps/pi/src/commands/index.ts
  • apps/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.json
  • apps/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.ts
  • apps/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.ts
  • 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/src/_pi-agent.ts
  • 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 : 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-globals rule, 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 .ts extensions 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 of homedir() and path.join() ensures cross-platform compatibility.

apps/pi/package.json (1)

1-89: Package configuration looks good.

All runtime dependencies are correctly placed in devDependencies as required for bundled CLIs. The publishConfig properly overrides the entry points for distribution. The workspace references and catalog usage are consistent with the monorepo patterns.

One observation: engines specifies >=20.19.4 for users while devEngines specifies ^24.11.0 for 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 for anthropic/ prefix and date-suffix-less models are correctly implemented. The ordering of pattern checks is appropriate:

  1. Check for [pi] prefix first and recursively format
  2. Check anthropic/ prefix with dot notation
  3. Check claude with date suffix (existing)
  4. 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 .ts extension for local imports and proper use of ccusage/logger instead of console.log. Based on learnings.


56-84: Clean data loading and merging implementation.

Good use of Promise.all for 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.vitest definition
  • Package.json sorted on successful build
apps/pi/src/commands/monthly.ts (2)

1-7: Imports follow project conventions.

Consistent with daily.ts - uses .ts extension 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 .ts extensions 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 null and '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 transformPiAgentUsage covering 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 .ts extension 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.all for parallel data loading. The type assertion for order is 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 --breakdown flag.


135-146: Replace hardcoded column count with a constant or derive it from the table structure.

The value 8 is correct for the current configuration, but hardcoding it is fragile. If includeLastActivity is added to this command's config later, the count must be updated to 9 or the separator row will be misaligned. Use a constant like TABLE_COLUMN_COUNT (as seen in apps/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 .ts extension for local imports. Good choice of node:readline for streaming JSONL processing.


13-80: LGTM!

Type definitions are comprehensive and well-structured. The Source type and the *WithSource types provide clear contracts for the data shapes.


82-98: LGTM!

Good streaming implementation using readline.createInterface with crlfDelay: Infinity for 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. The en-CA locale 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 sessionEntries array 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 the sessionEntries[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.

Comment thread apps/pi/src/index.ts
Comment on lines +18 to +23
async function run(): Promise<void> {
let args = process.argv.slice(2);
if (args[0] === 'ccusage-pi') {
args = args.slice(1);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ 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.

@ryoppippi ryoppippi changed the title Feat/pi agent integration feat: pi agent integration Jan 9, 2026
@ryoppippi
Copy link
Copy Markdown
Owner

@nicobailon thanks for your contribution.
i don't use pi, but it looks good so i'll merge it!!

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jan 9, 2026

Open in StackBlitz

ccusage

npm i https://pkg.pr.new/ryoppippi/ccusage@760

@ccusage/codex

npm i https://pkg.pr.new/ryoppippi/ccusage/@ccusage/codex@760

@ccusage/mcp

npm i https://pkg.pr.new/ryoppippi/ccusage/@ccusage/mcp@760

@ccusage/opencode

npm i https://pkg.pr.new/ryoppippi/ccusage/@ccusage/opencode@760

@ccusage/pi

npm i https://pkg.pr.new/ryoppippi/ccusage/@ccusage/pi@760

commit: cf2b06b

- 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
@ryoppippi ryoppippi force-pushed the feat/pi-agent-integration branch from 748ac4f to 3d72df1 Compare January 9, 2026 11:25
@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

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

Copy link
Copy Markdown
Owner

@ryoppippi ryoppippi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@ryoppippi ryoppippi merged commit 907f4ba into ryoppippi:main Jan 9, 2026
3 checks passed
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 ```text or ```console improves 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

📥 Commits

Reviewing files that changed from the base of the PR and between 0f8890f and cf2b06b.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • apps/pi/CLAUDE.md
  • apps/pi/package.json
  • apps/pi/tsconfig.json
  • docs/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.png for 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.json
  • apps/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.json
  • apps/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 ⚠️ Critical for bunx users Bun's bunx prioritises binaries m...

(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 points
  • publishConfig appropriately overrides paths for distribution

Based on learnings, this follows the established pattern where bundled CLI apps under apps/ list all dependencies in devDependencies so 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.

KooshaPari added a commit to KooshaPari/ccusage that referenced this pull request Mar 29, 2026
* 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>
KooshaPari added a commit to KooshaPari/ccusage that referenced this pull request Mar 29, 2026
* 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants