Skip to content

Conversation

@AnishDe12020
Copy link

@AnishDe12020 AnishDe12020 commented Dec 19, 2025

Summary

Adds a complete standalone CLI package @ccusage/opencode for analyzing OpenCode (Claude Code fork) usage logs, following the same architecture as the existing apps/codex package.

Features

Four CLI Commands

  • daily - Aggregate usage by date (YYYY-MM-DD)
  • weekly - Aggregate usage by ISO week (YYYY-Www)
  • monthly - Aggregate usage by month (YYYY-MM)
  • session - Per-session breakdown with parent/subagent hierarchy

Session Hierarchy Support

  • Parent sessions displayed with bold titles
  • Subagent sessions indented with prefix
  • Subtotal rows showing "Total (with subagents)" combining parent + all subagents
  • Visual clarity for complex session workflows

Cost Calculation

  • OpenCode stores cost: 0 in message files
  • Calculates actual costs from token counts using PricingFetcher from @ccusage/internal/pricing
  • Uses LiteLLM pricing database for model pricing
  • Supports Claude models (opus, sonnet, haiku)

Data Sources

OpenCode Storage (default: ~/.local/share/opencode):

  • Messages: storage/message/{sessionID}/msg_{messageID}.json (individual JSON files)
  • Sessions: storage/session/{projectHash}/{sessionID}.json (session metadata)
  • Override via OPENCODE_DATA_DIR environment variable

Package Structure

```
apps/opencode/
├── src/
│ ├── index.ts # CLI entry point using Gunshi framework
│ ├── data-loader.ts # Load OpenCode messages & session metadata
│ └── commands/
│ ├── daily.ts # Daily usage report
│ ├── weekly.ts # Weekly usage report
│ ├── monthly.ts # Monthly usage report
│ └── session.ts # Session report with hierarchy
├── package.json # @ccusage/opencode@0.1.0
├── README.md # Usage documentation
└── tsconfig.json
```

Testing

  • ✅ 6 new tests added (data-loader.ts, weekly.ts)
  • ✅ All 331 tests passing
  • ✅ TypeScript strict mode
  • ✅ ESLint passing

Commits

  1. Extract OpenCode into separate package
  2. Add session, monthly, and weekly commands
  3. Improve markdown formatting in README
  4. Group subagents under parent sessions with proper titles
  5. Add subtotal rows for parent sessions with subagents
  6. Fix duplicate bullet formatting in model names
  7. Fix duplicate bullet formatting in daily, monthly, weekly commands

Usage Example

```bash

Install

pnpm add @ccusage/opencode

Run commands

npx opencode daily
npx opencode weekly
npx opencode monthly
npx opencode session
```

Related

This package complements the existing ecosystem:

  • @ccusage/ccusage - Analyze Claude Code usage
  • @ccusage/codex - Analyze OpenAI Codex usage
  • @ccusage/opencode - ✨ NEW: Analyze OpenCode usage

Summary by CodeRabbit

  • New Features

    • Added an OpenCode CLI with daily/weekly/monthly/session reports, JSON and compact table output, and automatic cost calculation when missing.
  • Documentation

    • New user/developer docs covering installation, commands, flags, data locations, cost rules, and testing guidance.
  • Tests & Tooling

    • Added test config, lint/build scripts, packaging/CLI metadata, and unit tests.
  • Other

    • New data-loading and cost-calculation utilities to support reporting and model aliasing.

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

closes #757

refactor opencode integration by creating standalone apps/opencode package following the same architecture as apps/codex. this separates opencode-specific code from ccusage for better maintainability.

changes:
- create @ccusage/opencode package with daily command
- integrate pricingfetcher for accurate cost calculation from token data
- move opencode data loader and utilities to dedicated package
- remove opencode commands from apps/ccusage
- update root documentation to list opencode in ccusage family

the package currently supports daily usage reports with accurate cost calculation for claude models. costs are calculated from token data using litellm pricing database since opencode stores cost: 0 in message files.

binary: ccusage-opencode
available commands: daily (session, weekly, monthly, blocks to be added)
implement remaining usage reporting commands for opencode package following the same patterns as ccusage and codex packages.

changes:
- add session command: groups usage by conversation sessions with accurate cost calculation
- add monthly command: aggregates usage by month (yyyy-mm format)
- add weekly command: aggregates usage by iso week (yyyy-www format) with in-source tests
- update data-loader to include sessionid in loadedusageentry type
- update cli routing to include all commands (daily, session, monthly, weekly)
- add readme.md with comprehensive usage documentation and examples

all commands use pricingfetcher for accurate cost calculation from token data since opencode stores cost: 0 in message files. commands support --json and --compact flags for flexible output formatting.

test coverage: 331 tests passing (including 4 new weekly command tests)
@coderabbitai
Copy link

coderabbitai bot commented Dec 19, 2025

Walkthrough

Adds a new CLI package @ccusage/opencode: package manifest, docs, ESLint/TS/test configs, data loader with Valibot schemas, cost utilities, four report commands (daily/weekly/monthly/session), CLI wiring, and output formatting (JSON/table) using LiteLLM pricing when needed.

Changes

Cohort / File(s) Summary
Monorepo docs
CLAUDE.md, apps/ccusage/README.md
Added entries documenting the new @ccusage/opencode package and an OpenCode usage analyzer listing.
Package docs & agent notes
apps/opencode/CLAUDE.md, apps/opencode/README.md, apps/opencode/AGENTS.md
New README, CLAUDE.md and AGENTS.md describing package usage, data layout, cost calculation, CLI usage, and testing notes.
Package manifest & lint
apps/opencode/package.json, apps/opencode/eslint.config.js
New package.json with CLI bin, scripts, engines and publish config; ESLint flat config export with a test rule override.
TypeScript & build/test configs
apps/opencode/tsconfig.json, apps/opencode/tsdown.config.ts, apps/opencode/vitest.config.ts
Added TS compiler config, tsdown build config, and Vitest config (globals, coverage, includeSource).
CLI entry & wiring
apps/opencode/src/index.ts, apps/opencode/src/run.ts
New CLI entry and run orchestration registering subcommands, normalizing args, and invoking Gunshi CLI (daily as default).
Data loader & types
apps/opencode/src/data-loader.ts
New data-loader: Valibot schemas, types (LoadedUsageEntry, LoadedSessionMetadata), OPENCODE_DATA_DIR resolution, JSON parsing/validation, conversion helpers, and load functions for sessions/messages.
Cost utilities
apps/opencode/src/cost-utils.ts
Model alias mapping and calculateCostForEntry that prefers precomputed cost or calls LiteLLMPricingFetcher to compute cost from tokens.
Report commands
apps/opencode/src/commands/*, apps/opencode/src/commands/index.ts
Added daily, weekly, monthly, and session commands: load entries, group by period/session, aggregate tokens/costs, output JSON or formatted tables; index re-exports commands.
Command tests
apps/opencode/src/commands/weekly.ts (tests included)
Added getISOWeek helper and unit tests for ISO week edge cases.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant CLI as Gunshi CLI
    participant Run as run.ts
    participant Cmd as Command (daily|weekly|monthly|session)
    participant Loader as Data Loader
    participant Pricing as LiteLLM Pricing
    participant Formatter as Table/JSON Formatter
    participant Stdout as stdout

    User->>CLI: invoke ccusage-opencode [command] [flags]
    CLI->>Run: normalized args (strip npx/binary)
    Run->>Cmd: dispatch selected command
    Cmd->>Loader: load messages & sessions
    Loader-->>Cmd: return LoadedUsageEntry[]
    Cmd->>Cmd: group & aggregate tokens/models
    alt entry.costUSD missing
        Cmd->>Pricing: calculateCostFromTokens(model,tokens)
        Pricing-->>Cmd: return costUSD
    else cached cost present
        Cmd-->>Cmd: use entry.costUSD
    end
    Cmd->>Formatter: produce JSON or formatted table (compact optional)
    Formatter->>Stdout: write output
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Pay special attention to apps/opencode/src/commands/weekly.ts and session.ts for stray using keyword and test placement.
  • Review apps/opencode/src/data-loader.ts for Valibot schemas, parsing error paths, deduplication, and OPENCODE_DATA_DIR fallback.
  • Verify cost calculation integration (cost-utils.ts) and consistency across commands when LiteLLMPricingFetcher fails.

Possibly related PRs

Suggested reviewers

  • ryoppippi

"🐇
I nibble logs and numbers bright,
I hop through days and weeks at night.
Tokens counted, costs unfurled —
A carrot CLI to light the world.
Hooray from the burrow, code takes flight!"

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding a new OpenCode CLI package to the project.
Linked Issues check ✅ Passed The PR fully implements the objective from issue #757 by adding OpenCode support with daily, weekly, monthly, and session-based usage reporting commands.
Out of Scope Changes check ✅ Passed All changes are directly related to adding the OpenCode CLI package; documentation updates (CLAUDE.md in CLAUDE.md and ccusage README) are in-scope as they document the new package.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c82254 and 79afbcb.

📒 Files selected for processing (1)
  • apps/opencode/AGENTS.md (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/opencode/AGENTS.md

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

@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: 5

♻️ Duplicate comments (2)
apps/opencode/src/commands/daily.ts (1)

18-37: Extract duplicated calculateCostForEntry helper.

This function is duplicated identically across daily.ts, monthly.ts, and session.ts. See the refactoring suggestion in monthly.ts (lines 18-37) to extract this to a shared module.

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

18-37: Extract duplicated calculateCostForEntry helper.

This function is duplicated identically across daily.ts, monthly.ts, and session.ts. See the refactoring suggestion in monthly.ts (lines 18-37) to extract this to a shared module.

🧹 Nitpick comments (2)
apps/opencode/src/data-loader.ts (2)

42-42: Consider using homedir() from node:os for consistency.

The apps/ccusage package uses homedir() from node:os for user home directory resolution. Using the same approach here would improve consistency across sibling packages.

🔎 Proposed refactor
+import { homedir } from 'node:os';
 import { readFile } from 'node:fs/promises';
 import path from 'node:path';
 import process from 'node:process';
...
-const USER_HOME_DIR = process.env.HOME ?? process.env.USERPROFILE ?? process.cwd();
+const USER_HOME_DIR = homedir();

Based on learnings: treating OpenCode as a sibling to ccusage means reusing patterns where appropriate.


47-60: Extract shared schemas to avoid duplication.

The modelNameSchema and sessionIdSchema are duplicated from apps/ccusage/src/_types.ts. These branded schemas should be extracted to a shared internal package to ensure consistency across ccusage, codex, and opencode.

Consider moving these schemas to packages/internal/src/types.ts or a similar shared location, then importing them here and in apps/ccusage.

Based on learnings: OpenCode should reuse shared packages like its sibling Codex rather than duplicating code.

📜 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 0ba1d70.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (18)
  • CLAUDE.md (1 hunks)
  • apps/ccusage/README.md (1 hunks)
  • apps/opencode/AGENTS.md (1 hunks)
  • apps/opencode/CLAUDE.md (1 hunks)
  • apps/opencode/README.md (1 hunks)
  • apps/opencode/eslint.config.js (1 hunks)
  • apps/opencode/package.json (1 hunks)
  • apps/opencode/src/commands/daily.ts (1 hunks)
  • apps/opencode/src/commands/index.ts (1 hunks)
  • apps/opencode/src/commands/monthly.ts (1 hunks)
  • apps/opencode/src/commands/session.ts (1 hunks)
  • apps/opencode/src/commands/weekly.ts (1 hunks)
  • apps/opencode/src/data-loader.ts (1 hunks)
  • apps/opencode/src/index.ts (1 hunks)
  • apps/opencode/src/run.ts (1 hunks)
  • apps/opencode/tsconfig.json (1 hunks)
  • apps/opencode/tsdown.config.ts (1 hunks)
  • apps/opencode/vitest.config.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
**/*.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/opencode/CLAUDE.md
  • apps/opencode/AGENTS.md
  • apps/opencode/README.md
  • CLAUDE.md
  • apps/ccusage/README.md
**/*.{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/opencode/eslint.config.js
  • apps/opencode/src/index.ts
  • apps/opencode/tsdown.config.ts
  • apps/opencode/src/commands/index.ts
  • apps/opencode/src/commands/monthly.ts
  • apps/opencode/src/run.ts
  • apps/opencode/vitest.config.ts
  • apps/opencode/src/data-loader.ts
  • apps/opencode/src/commands/session.ts
  • apps/opencode/src/commands/daily.ts
  • apps/opencode/src/commands/weekly.ts
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/opencode/package.json
**/*.{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/opencode/package.json
  • apps/opencode/src/index.ts
  • apps/opencode/tsconfig.json
  • apps/opencode/tsdown.config.ts
  • apps/opencode/src/commands/index.ts
  • apps/opencode/src/commands/monthly.ts
  • apps/opencode/src/run.ts
  • apps/opencode/vitest.config.ts
  • apps/opencode/src/data-loader.ts
  • apps/opencode/src/commands/session.ts
  • apps/opencode/src/commands/daily.ts
  • apps/opencode/src/commands/weekly.ts
**/package.json

📄 CodeRabbit inference engine (CLAUDE.md)

Dependencies should always be added as devDependencies unless explicitly requested otherwise

Files:

  • apps/opencode/package.json
**/*.ts{,x}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript with strict mode and bundler module resolution

Files:

  • apps/opencode/src/index.ts
  • apps/opencode/tsdown.config.ts
  • apps/opencode/src/commands/index.ts
  • apps/opencode/src/commands/monthly.ts
  • apps/opencode/src/run.ts
  • apps/opencode/vitest.config.ts
  • apps/opencode/src/data-loader.ts
  • apps/opencode/src/commands/session.ts
  • apps/opencode/src/commands/daily.ts
  • apps/opencode/src/commands/weekly.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/opencode/src/index.ts
  • apps/opencode/tsdown.config.ts
  • apps/opencode/src/commands/index.ts
  • apps/opencode/src/commands/monthly.ts
  • apps/opencode/src/run.ts
  • apps/opencode/vitest.config.ts
  • apps/opencode/src/data-loader.ts
  • apps/opencode/src/commands/session.ts
  • apps/opencode/src/commands/daily.ts
  • apps/opencode/src/commands/weekly.ts
**/data-loader.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Silently skip malformed JSONL lines during parsing in data loading operations

Files:

  • apps/opencode/src/data-loader.ts
🧠 Learnings (33)
📓 Common learnings
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: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: For package directories in commits, use the package directory name as scope (e.g., `feat(terminal):`, `fix(ui):`)
📚 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/opencode/CLAUDE.md
  • apps/opencode/README.md
  • CLAUDE.md
  • apps/ccusage/README.md
📚 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: 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

Applied to files:

  • apps/opencode/CLAUDE.md
  • apps/opencode/AGENTS.md
  • apps/opencode/README.md
  • CLAUDE.md
  • apps/ccusage/README.md
📚 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/opencode/CLAUDE.md
  • apps/opencode/package.json
  • 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 : Use `fs-fixture` with `createFixture()` to simulate Claude data in tests

Applied to files:

  • apps/opencode/CLAUDE.md
  • 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/opencode/CLAUDE.md
  • CLAUDE.md
📚 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/opencode/eslint.config.js
  • apps/opencode/tsconfig.json
  • apps/opencode/tsdown.config.ts
  • apps/opencode/vitest.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/src/**/*.ts : Write tests in-source using `if (import.meta.vitest != null)` blocks instead of separate test files

Applied to files:

  • apps/opencode/eslint.config.js
  • apps/opencode/tsconfig.json
  • apps/opencode/vitest.config.ts
📚 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/opencode/eslint.config.js
  • apps/opencode/tsconfig.json
  • apps/opencode/vitest.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/src/**/*.ts : Use Vitest globals (`describe`, `it`, `expect`) without imports in test blocks

Applied to files:

  • apps/opencode/eslint.config.js
  • apps/opencode/tsconfig.json
  • apps/opencode/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: 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/opencode/eslint.config.js
  • apps/opencode/tsconfig.json
  • apps/opencode/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} : In-source testing pattern: write tests directly in source files using `if (import.meta.vitest != null)` blocks

Applied to files:

  • apps/opencode/eslint.config.js
  • apps/opencode/tsconfig.json
  • apps/opencode/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: Applies to **/*.{ts,tsx,js,jsx} : Use ESLint for linting and formatting with tab indentation and double quotes

Applied to files:

  • apps/opencode/eslint.config.js
  • apps/opencode/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 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/opencode/package.json
  • apps/opencode/src/run.ts
  • 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/opencode/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/opencode/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/opencode/package.json
  • CLAUDE.md
📚 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: DO NOT use `await import()` dynamic imports anywhere in the codebase - this causes tree-shaking issues

Applied to files:

  • apps/opencode/src/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: 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/opencode/src/index.ts
  • apps/opencode/tsconfig.json
  • apps/opencode/vitest.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: After any code change, run format, typecheck, and tests in parallel (`pnpm run format`, `pnpm typecheck`, `pnpm run test`)

Applied to files:

  • apps/opencode/src/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 typecheck` to type check code with TypeScript

Applied to files:

  • apps/opencode/src/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: After making any code changes, run `pnpm run format`, `pnpm typecheck`, and `pnpm run test` in parallel

Applied to files:

  • apps/opencode/src/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: Applies to **/*.ts{,x} : Use TypeScript with strict mode and bundler module resolution

Applied to files:

  • apps/opencode/tsconfig.json
  • apps/opencode/tsdown.config.ts
📚 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/opencode/tsconfig.json
  • apps/opencode/tsdown.config.ts
  • apps/opencode/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: Applies to **/*.{ts,tsx} : Use `.ts` extensions for local file imports (e.g., `import { foo } from './utils.ts'`)

Applied to files:

  • apps/opencode/tsconfig.json
  • apps/opencode/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/src/**/*.ts : Only export symbols that are actually used by other modules

Applied to files:

  • apps/opencode/tsconfig.json
  • apps/opencode/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: Applies to **/*.{ts,tsx} : Use uppercase (PascalCase) for type names

Applied to files:

  • apps/opencode/tsconfig.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/**/*.ts : Use `.ts` extensions for local imports (e.g., `import { foo } from './utils.ts'`)

Applied to files:

  • apps/opencode/tsconfig.json
  • apps/opencode/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 src/**/_*.ts{,x} : Use underscore prefix for internal files (e.g., `_types.ts`, `_utils.ts`, `_consts.ts`)

Applied to files:

  • apps/opencode/tsdown.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/opencode/src/run.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: All vitest blocks live alongside implementation files using if (import.meta.vitest != null)

Applied to files:

  • apps/opencode/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: Applies to **/data-loader.ts : Silently skip malformed JSONL lines during parsing in data loading operations

Applied to files:

  • apps/opencode/src/data-loader.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,json} : Claude model naming convention: `claude-{model-type}-{generation}-{date}` (e.g., `claude-sonnet-4-20250514`, NOT `claude-4-sonnet-20250514`)

Applied to files:

  • CLAUDE.md
🧬 Code graph analysis (6)
apps/opencode/src/index.ts (2)
apps/opencode/src/run.ts (1)
  • run (15-30)
apps/ccusage/src/commands/index.ts (1)
  • run (44-59)
apps/opencode/src/commands/monthly.ts (3)
apps/opencode/src/data-loader.ts (2)
  • LoadedUsageEntry (102-113)
  • loadOpenCodeMessages (254-311)
packages/internal/src/pricing.ts (1)
  • LiteLLMPricingFetcher (89-355)
packages/terminal/src/table.ts (4)
  • ResponsiveTable (38-298)
  • formatModelsDisplayMultiline (355-359)
  • formatNumber (305-307)
  • addEmptySeparatorRow (566-569)
apps/opencode/src/data-loader.ts (2)
apps/ccusage/src/_consts.ts (1)
  • USER_HOME_DIR (38-38)
apps/ccusage/src/_types.ts (2)
  • modelNameSchema (9-13)
  • sessionIdSchema (15-19)
apps/opencode/src/commands/session.ts (4)
apps/opencode/src/data-loader.ts (3)
  • LoadedUsageEntry (102-113)
  • loadOpenCodeMessages (254-311)
  • loadOpenCodeSessions (213-248)
packages/internal/src/pricing.ts (1)
  • LiteLLMPricingFetcher (89-355)
apps/opencode/src/commands/index.ts (1)
  • sessionCommand (3-3)
packages/terminal/src/table.ts (3)
  • ResponsiveTable (38-298)
  • formatNumber (305-307)
  • addEmptySeparatorRow (566-569)
apps/opencode/src/commands/daily.ts (4)
apps/ccusage/src/data-loader.ts (1)
  • calculateCostForEntry (633-665)
apps/opencode/src/data-loader.ts (2)
  • LoadedUsageEntry (102-113)
  • loadOpenCodeMessages (254-311)
packages/internal/src/pricing.ts (1)
  • LiteLLMPricingFetcher (89-355)
packages/terminal/src/table.ts (4)
  • ResponsiveTable (38-298)
  • formatModelsDisplayMultiline (355-359)
  • formatNumber (305-307)
  • addEmptySeparatorRow (566-569)
apps/opencode/src/commands/weekly.ts (3)
apps/opencode/src/data-loader.ts (2)
  • LoadedUsageEntry (102-113)
  • loadOpenCodeMessages (254-311)
packages/internal/src/pricing.ts (1)
  • LiteLLMPricingFetcher (89-355)
packages/terminal/src/table.ts (4)
  • ResponsiveTable (38-298)
  • formatModelsDisplayMultiline (355-359)
  • formatNumber (305-307)
  • addEmptySeparatorRow (566-569)
🪛 LanguageTool
apps/opencode/README.md

[grammar] ~71-~71: Ensure spelling is correct
Context: ...hare/opencode) - LOG_LEVEL` – control consola log verbosity (0 silent … 5 trace) ## ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🔇 Additional comments (25)
CLAUDE.md (1)

10-11: LGTM!

The documentation entries for Codex and OpenCode CLI packages follow the established pattern and maintain consistency with the monorepo structure.

apps/ccusage/README.md (1)

32-35: LGTM!

The OpenCode tool entry is well-structured and maintains consistency with the existing ccusage family documentation format.

apps/opencode/tsconfig.json (1)

1-32: LGTM!

The TypeScript configuration properly enables strict mode, bundler module resolution, and Vitest integration, aligning with the project's coding guidelines and sibling package patterns.

apps/opencode/tsdown.config.ts (1)

1-11: LGTM!

The tsdown build configuration is properly set up for a Node.js CLI with ESM format, node20 target, and appropriate entry point matching the package manifest.

apps/opencode/eslint.config.js (1)

1-12: LGTM!

The ESLint configuration properly uses the shared preset with app type and correctly enforces the project's Vitest globals convention.

apps/opencode/AGENTS.md (1)

1-40: LGTM!

The documentation clearly explains OpenCode's data structure, token handling, cost calculation, and testing conventions, maintaining consistency with sibling packages.

apps/opencode/vitest.config.ts (1)

1-15: LGTM!

The Vitest configuration properly enables globals, in-source testing, and V8 coverage, aligning with the project's testing conventions.

apps/opencode/package.json (3)

38-59: LGTM!

All runtime dependencies are correctly placed in devDependencies, following the bundled CLI pattern for apps under apps/. The workspace package references and catalog dependencies are properly configured.

Based on learnings: All projects under apps/ ship as bundled CLIs/binaries - treat runtime dependencies as bundled assets by listing everything in devDependencies.


65-78: [Rewritten review comment]
[Classification tag]


1-79: Package structure is correctly aligned with sibling packages.

Verification confirms that opencode's package.json matches the established patterns: bin entry follows the naming convention, main/module entries point to the compiled output, build script uses tsdown, and all runtime dependencies are correctly listed in devDependencies per project guidelines.

apps/opencode/src/index.ts (1)

1-6: LGTM!

The entry point is clean and follows the established pattern from apps/ccusage. Proper use of .ts extension for imports and appropriate eslint-disable for top-level await.

apps/opencode/CLAUDE.md (1)

1-66: LGTM!

The package documentation is well-structured and aligns with the established patterns from codex and ccusage packages. Clear guidance on architecture, testing, and code style.

Based on learnings, this appropriately treats OpenCode as a sibling to apps/ccusage and apps/codex.

apps/opencode/src/commands/index.ts (1)

1-4: LGTM!

Clean barrel export that follows the guideline to only export symbols that are actually used by other modules. All four commands are consumed by the run.ts CLI wiring.

apps/opencode/src/run.ts (1)

1-30: LGTM!

The CLI wiring follows the established pattern from apps/ccusage. Proper handling of npx binary name normalization and clean subcommands registration with Gunshi.

apps/opencode/src/commands/session.ts (2)

16-16: TABLE_COLUMN_COUNT is correct here.

Unlike daily.ts and monthly.ts which incorrectly use 7, this correctly sets TABLE_COLUMN_COUNT to 8, matching the 8-column table layout.


162-216: Well-implemented parent/subagent hierarchy.

The logic for grouping sessions by parent, rendering parent sessions with bold titles, indenting subsessions with , and computing subtotals is well-structured and readable.

apps/opencode/src/data-loader.ts (3)

151-162: LGTM - Silent error handling is appropriate here.

The try-catch pattern with null return correctly implements the "silently skip malformed data" principle for data loading operations. While the codebase generally prefers Result.try(), the traditional try-catch is acceptable for these internal data loading utilities.

Based on learnings: data-loader files should silently skip malformed data during parsing.


254-311: LGTM - Comprehensive message loading with appropriate filtering.

The implementation correctly:

  • Discovers message files using glob patterns
  • Filters out messages with no tokens or missing provider/model
  • Deduplicates by message ID
  • Converts to the internal LoadedUsageEntry format

The filtering logic aligns with the PR objectives where actual costs are computed from tokens rather than reading the stored cost: 0 values.


313-372: LGTM - Test coverage for conversion logic.

The in-source tests appropriately verify:

  • Conversion of messages with full token and cache data
  • Handling of missing optional fields with proper defaults

Tests follow the coding guidelines for in-source testing pattern using if (import.meta.vitest).

apps/opencode/src/commands/weekly.ts (6)

18-37: LGTM - Cost calculation logic is sound.

The function appropriately:

  • Uses stored costUSD when available and non-zero
  • Falls back to computing cost from tokens using LiteLLMPricingFetcher
  • Handles errors gracefully with Result.unwrap defaulting to 0

This aligns with the PR description where OpenCode stores cost: 0 and actual costs are computed from token counts.


45-62: LGTM - ISO week calculation follows standard algorithm.

The ISO 8601 week date calculation is correctly implemented:

  • Sets to nearest Thursday (as per ISO standard)
  • Handles year boundaries appropriately
  • Returns properly formatted week strings (YYYY-Www)

The comprehensive test coverage at lines 212-239 verifies correctness for various edge cases.


90-90: LGTM - Correct use of explicit resource management.

The using keyword is the correct choice here for TypeScript's explicit resource management (ES2024/TS5.2+). Since LiteLLMPricingFetcher implements the Disposable interface, the using declaration ensures automatic disposal at the end of the scope, properly managing the resource lifecycle.


92-148: LGTM - Data aggregation and totals calculation.

The weekly aggregation correctly:

  • Groups entries by ISO week using groupBy
  • Accumulates all token types (input, output, cache read/write)
  • Computes per-entry costs asynchronously
  • Tracks unique models per week
  • Calculates overall totals across all weeks

The logic is clear and handles all the required metrics.


162-205: LGTM - Table rendering with responsive layout.

The table implementation correctly:

  • Configures 8 columns for full mode, 5 for compact mode
  • Formats numbers and currency appropriately
  • Adds a separator before the totals row
  • Highlights totals in yellow for visibility
  • Shows a helpful compact mode notice when applicable

The responsive table pattern provides a good UX for different terminal widths.


209-240: LGTM - Comprehensive test coverage for ISO week calculation.

The tests appropriately verify:

  • Mid-year date calculation
  • Year boundary handling (Dec 29, 2025 → week 01 of 2026)
  • First week of year
  • Last days of previous year belonging to week 1

These edge cases are critical for ISO 8601 week dates and the tests provide good coverage.


**Supported models**:

- ✅ Claude models (opus-4-5, haiku-4-5, sonnet-4-5, etc.) - Accurate pricing from LiteLLM
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Correct the model naming format.

The model names listed here don't follow the project's naming convention. According to the coding guidelines, Claude models should follow the pattern claude-{model-type}-{generation}-{date} (e.g., claude-sonnet-4-20250514).

🔎 Suggested fix
-- ✅ Claude models (opus-4-5, haiku-4-5, sonnet-4-5, etc.) - Accurate pricing from LiteLLM
+- ✅ Claude models (claude-opus-4, claude-haiku-4, claude-sonnet-4, etc.) - Accurate pricing from LiteLLM
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- ✅ Claude models (opus-4-5, haiku-4-5, sonnet-4-5, etc.) - Accurate pricing from LiteLLM
- ✅ Claude models (claude-opus-4, claude-haiku-4, claude-sonnet-4, etc.) - Accurate pricing from LiteLLM

Comment on lines 1 to 14
import type { LoadedUsageEntry } from '../data-loader';
import { LiteLLMPricingFetcher } from '@ccusage/internal/pricing';
import {
addEmptySeparatorRow,
formatCurrency,
formatModelsDisplayMultiline,
formatNumber,
ResponsiveTable,
} from '@ccusage/terminal/table';
import { Result } from '@praha/byethrow';
import { groupBy } from 'es-toolkit';
import { define } from 'gunshi';
import pc from 'picocolors';
import { loadOpenCodeMessages } from '../data-loader';
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add .ts extensions to local file imports.

Local file imports are missing the required .ts extension. The coding guidelines explicitly require: "Use .ts extensions for local file imports (e.g., import { foo } from './utils.ts')".

🔎 Proposed fix
-import type { LoadedUsageEntry } from '../data-loader';
+import type { LoadedUsageEntry } from '../data-loader.ts';
 import { LiteLLMPricingFetcher } from '@ccusage/internal/pricing';
 import {
 	addEmptySeparatorRow,
 	formatCurrency,
 	formatModelsDisplayMultiline,
 	formatNumber,
 	ResponsiveTable,
 } from '@ccusage/terminal/table';
 import { Result } from '@praha/byethrow';
 import { groupBy } from 'es-toolkit';
 import { define } from 'gunshi';
 import pc from 'picocolors';
-import { loadOpenCodeMessages } from '../data-loader';
+import { loadOpenCodeMessages } from '../data-loader.ts';

As per coding guidelines.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import type { LoadedUsageEntry } from '../data-loader';
import { LiteLLMPricingFetcher } from '@ccusage/internal/pricing';
import {
addEmptySeparatorRow,
formatCurrency,
formatModelsDisplayMultiline,
formatNumber,
ResponsiveTable,
} from '@ccusage/terminal/table';
import { Result } from '@praha/byethrow';
import { groupBy } from 'es-toolkit';
import { define } from 'gunshi';
import pc from 'picocolors';
import { loadOpenCodeMessages } from '../data-loader';
import type { LoadedUsageEntry } from '../data-loader.ts';
import { LiteLLMPricingFetcher } from '@ccusage/internal/pricing';
import {
addEmptySeparatorRow,
formatCurrency,
formatModelsDisplayMultiline,
formatNumber,
ResponsiveTable,
} from '@ccusage/terminal/table';
import { Result } from '@praha/byethrow';
import { groupBy } from 'es-toolkit';
import { define } from 'gunshi';
import pc from 'picocolors';
import { loadOpenCodeMessages } from '../data-loader.ts';
🤖 Prompt for AI Agents
In apps/opencode/src/commands/weekly.ts lines 1-14, local imports from
'../data-loader' are missing the required .ts extension; update all local file
imports (e.g., both "import type { LoadedUsageEntry } from '../data-loader';"
and "import { loadOpenCodeMessages } from '../data-loader';") to include the .ts
extension (../data-loader.ts) so they comply with the coding guideline requiring
.ts extensions for local imports.

Copy link

@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 (1)
apps/opencode/README.md (1)

2-2: Prefer relative paths for images in /docs/public/.

Per the coding guidelines, images stored in /docs/public/ should use relative paths (e.g., /logo.svg) rather than external CDN URLs. Lines 2, 111, and 117 reference images that appear to be in the repository's /docs/public/ directory but use full CDN URLs instead.

🔎 Proposed refactor to use relative paths
- <img src="https://cdn.jsdelivr.net/gh/ryoppippi/ccusage@main/docs/public/logo.svg" alt="ccusage logo" width="256" height="256">
+ <img src="/logo.svg" alt="ccusage logo" width="256" height="256">
- <img src="https://cdn.jsdelivr.net/gh/ryoppippi/ccusage@main/docs/public/ccusage_thumbnail.png" alt="ccusage: The Claude Code cost scorecard that went viral" width="600">
+ <img src="/ccusage_thumbnail.png" alt="ccusage: The Claude Code cost scorecard that went viral" width="600">
- <img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors@main/sponsors.svg">
+ <img src="/sponsors.svg" alt="ryoppippi sponsors">

Note: This refactor depends on the build process or hosting configuration serving these files correctly at the repository root's public directory. If the CDN URLs are intentional for distribution/longevity reasons, this can be deferred.

Also applies to: 111-111, 117-117

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0ba1d70 and 8eddd0d.

📒 Files selected for processing (1)
  • apps/opencode/README.md (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.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/opencode/README.md
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: ryoppippi/ccusage PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T14:42:34.734Z
Learning: For package directories in commits, use the package directory name as scope (e.g., `feat(terminal):`, `fix(ui):`)
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: 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
📚 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:

  • apps/opencode/README.md
📚 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:

  • apps/opencode/README.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/opencode/README.md
📚 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:

  • apps/opencode/README.md
📚 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 **/calculate-cost.ts : Cost calculations require exact model name matches with LiteLLM's database

Applied to files:

  • apps/opencode/README.md
📚 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/opencode/README.md
📚 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: 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

Applied to files:

  • apps/opencode/README.md
🪛 LanguageTool
apps/opencode/README.md

[grammar] ~71-~71: Ensure spelling is correct
Context: ...hare/opencode) - LOG_LEVEL` – control consola log verbosity (0 silent … 5 trace) ## ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.18.1)
apps/opencode/README.md

117-117: Images should have alternate text (alt text)

(MD045, no-alt-text)


<p align="center">
<a href="https://github.com/sponsors/ryoppippi">
<img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors@main/sponsors.svg">
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add missing alt text to the sponsors image.

The image on Line 117 is missing the required alt attribute, which violates accessibility standards and the coding guidelines. All images must include descriptive alt text.

🔎 Proposed fix
     <a href="https://github.com/sponsors/ryoppippi">
-        <img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors@main/sponsors.svg">
+        <img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors@main/sponsors.svg" alt="ryoppippi sponsors">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors@main/sponsors.svg">
<img src="https://cdn.jsdelivr.net/gh/ryoppippi/sponsors@main/sponsors.svg" alt="ryoppippi sponsors">
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

117-117: Images should have alternate text (alt text)

(MD045, no-alt-text)

🤖 Prompt for AI Agents
In apps/opencode/README.md around line 117, the <img> tag for the sponsors SVG
is missing an alt attribute; add a concise, descriptive alt attribute (for
example: alt="OpenCode sponsors logos" or alt="Sponsors") to the image tag so it
meets accessibility guidelines and project coding standards.

@ryoppippi
Copy link
Owner

@AnishDe12020 nice!
can you make AGENTS.md as a symlink of claude.md?

@pkg-pr-new
Copy link

pkg-pr-new bot commented Dec 20, 2025

Open in StackBlitz

npm i https://pkg.pr.new/ryoppippi/ccusage@758
npm i https://pkg.pr.new/ryoppippi/ccusage/@ccusage/codex@758
npm i https://pkg.pr.new/ryoppippi/ccusage/@ccusage/mcp@758
npm i https://pkg.pr.new/ryoppippi/ccusage/@ccusage/opencode@758

commit: faf0f90

@AnishDe12020
Copy link
Author

@AnishDe12020 nice! can you make AGENTS.md as a symlink of claude.md?

done!

Copy link

@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: 2

♻️ Duplicate comments (2)
apps/opencode/src/commands/monthly.ts (1)

15-15: LGTM! TABLE_COLUMN_COUNT now correct.

The TABLE_COLUMN_COUNT constant is now correctly set to 8, matching the 8-column table header defined on line 116. This resolves the issue flagged in previous reviews.

apps/opencode/src/commands/weekly.ts (1)

12-13: Add .ts extensions to local file imports.

Local imports are missing the required .ts extension as specified in the coding guidelines.

🔎 Proposed fix
-import { calculateCostForEntry } from '../cost-utils';
-import { loadOpenCodeMessages } from '../data-loader';
+import { calculateCostForEntry } from '../cost-utils.ts';
+import { loadOpenCodeMessages } from '../data-loader.ts';

As per coding guidelines.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a2fa0f3 and 9c82254.

📒 Files selected for processing (5)
  • apps/opencode/src/commands/daily.ts (1 hunks)
  • apps/opencode/src/commands/monthly.ts (1 hunks)
  • apps/opencode/src/commands/session.ts (1 hunks)
  • apps/opencode/src/commands/weekly.ts (1 hunks)
  • apps/opencode/src/cost-utils.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/opencode/src/commands/daily.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{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/opencode/src/cost-utils.ts
  • apps/opencode/src/commands/monthly.ts
  • apps/opencode/src/commands/weekly.ts
  • apps/opencode/src/commands/session.ts
**/*.ts{,x}

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript with strict mode and bundler module resolution

Files:

  • apps/opencode/src/cost-utils.ts
  • apps/opencode/src/commands/monthly.ts
  • apps/opencode/src/commands/weekly.ts
  • apps/opencode/src/commands/session.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/opencode/src/cost-utils.ts
  • apps/opencode/src/commands/monthly.ts
  • apps/opencode/src/commands/weekly.ts
  • apps/opencode/src/commands/session.ts
**/*.{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/opencode/src/cost-utils.ts
  • apps/opencode/src/commands/monthly.ts
  • apps/opencode/src/commands/weekly.ts
  • apps/opencode/src/commands/session.ts
🧠 Learnings (14)
📓 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/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
📚 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 **/calculate-cost.ts : Cost calculations require exact model name matches with LiteLLM's database

Applied to files:

  • apps/opencode/src/cost-utils.ts
  • apps/opencode/src/commands/monthly.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: Fetch per-model pricing from LiteLLM model_prices_and_context_window.json via LiteLLMPricingFetcher using an offline cache scoped to Codex-prefixed models; handle aliases (e.g., gpt-5-codex → gpt-5) in CodexPricingSource

Applied to files:

  • apps/opencode/src/cost-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,tsx} : Model names in tests must exactly match LiteLLM's pricing database entries

Applied to files:

  • apps/opencode/src/cost-utils.ts
  • apps/opencode/src/commands/weekly.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: Cost calculation per model/date: charge non-cached input, cached input (fallback to input rate if missing), and output using the specified per-million token rates

Applied to files:

  • apps/opencode/src/cost-utils.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 : Do not use console.log; use the logger utilities from `src/logger.ts` instead

Applied to files:

  • apps/opencode/src/commands/monthly.ts
  • apps/opencode/src/commands/weekly.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/opencode/src/commands/weekly.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/opencode/src/commands/weekly.ts
📚 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/opencode/src/commands/weekly.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: DO NOT use `await import()` dynamic imports anywhere in the codebase - this causes tree-shaking issues

Applied to files:

  • apps/opencode/src/commands/weekly.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/opencode/src/commands/weekly.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 : NEVER use `await import()` dynamic imports anywhere (especially in tests)

Applied to files:

  • apps/opencode/src/commands/weekly.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 uppercase (PascalCase) for type names

Applied to files:

  • apps/opencode/src/commands/weekly.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 file paths with Node.js path utilities for cross-platform compatibility

Applied to files:

  • apps/opencode/src/commands/weekly.ts
🧬 Code graph analysis (3)
apps/opencode/src/commands/monthly.ts (4)
apps/opencode/src/data-loader.ts (1)
  • loadOpenCodeMessages (254-311)
packages/internal/src/pricing.ts (1)
  • LiteLLMPricingFetcher (89-355)
apps/opencode/src/cost-utils.ts (1)
  • calculateCostForEntry (22-42)
packages/terminal/src/table.ts (4)
  • ResponsiveTable (38-298)
  • formatModelsDisplayMultiline (355-359)
  • formatNumber (305-307)
  • addEmptySeparatorRow (566-569)
apps/opencode/src/commands/weekly.ts (4)
apps/opencode/src/data-loader.ts (1)
  • loadOpenCodeMessages (254-311)
packages/internal/src/pricing.ts (1)
  • LiteLLMPricingFetcher (89-355)
apps/opencode/src/cost-utils.ts (1)
  • calculateCostForEntry (22-42)
packages/terminal/src/table.ts (4)
  • ResponsiveTable (38-298)
  • formatModelsDisplayMultiline (355-359)
  • formatNumber (305-307)
  • addEmptySeparatorRow (566-569)
apps/opencode/src/commands/session.ts (4)
apps/opencode/src/data-loader.ts (2)
  • loadOpenCodeMessages (254-311)
  • loadOpenCodeSessions (213-248)
packages/internal/src/pricing.ts (1)
  • LiteLLMPricingFetcher (89-355)
apps/opencode/src/cost-utils.ts (1)
  • calculateCostForEntry (22-42)
packages/terminal/src/table.ts (1)
  • ResponsiveTable (38-298)
🔇 Additional comments (5)
apps/opencode/src/cost-utils.ts (2)

22-42: LGTM! Cost calculation extraction resolves duplication.

The extraction of calculateCostForEntry to a shared module successfully addresses the code duplication issue flagged in previous reviews across daily.ts, monthly.ts, and session.ts. The implementation correctly prioritizes pre-calculated costs and falls back to token-based calculation using the pricing fetcher with model name resolution.


9-12: Ensure MODEL_ALIASES covers all custom model name variants used with LiteLLM.

The alias for 'gemini-3-pro-high' → 'gemini-3-pro-preview' is correct, since LiteLLM's pricing database uses 'gemini-3-pro-preview' as the official model name and handles thinking modes via the reasoning_effort parameter. However, if OpenCode's data includes other custom-named variants (e.g., 'gemini-3-pro-low', 'gemini-3-flash-high'), add corresponding aliases before they're used in cost calculations.

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

15-15: LGTM! TABLE_COLUMN_COUNT correctly set.

The TABLE_COLUMN_COUNT constant correctly matches the 8-column table header defined on line 131.

apps/opencode/src/commands/weekly.ts (2)

23-40: LGTM! ISO week calculation correctly implemented.

The getISOWeek function correctly implements the ISO 8601 week date algorithm using the "nearest Thursday" approach. The logic properly handles week boundaries, year transitions, and the ISO week definition (weeks start on Monday, first week contains January 4th).


187-218: LGTM! Comprehensive test coverage for ISO week edge cases.

The test suite covers key scenarios: mid-year dates, year boundary transitions, first week identification, and edge cases where early January dates belong to week 1. This provides good confidence in the getISOWeek implementation.

Comment on lines +12 to +13
import { calculateCostForEntry } from '../cost-utils';
import { loadOpenCodeMessages } from '../data-loader';
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add .ts extensions to local file imports.

Local imports are missing the required .ts extension as specified in the coding guidelines.

🔎 Proposed fix
-import { calculateCostForEntry } from '../cost-utils';
-import { loadOpenCodeMessages } from '../data-loader';
+import { calculateCostForEntry } from '../cost-utils.ts';
+import { loadOpenCodeMessages } from '../data-loader.ts';

As per coding guidelines.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { calculateCostForEntry } from '../cost-utils';
import { loadOpenCodeMessages } from '../data-loader';
import { calculateCostForEntry } from '../cost-utils.ts';
import { loadOpenCodeMessages } from '../data-loader.ts';
🤖 Prompt for AI Agents
In apps/opencode/src/commands/monthly.ts around lines 12 to 13, local imports
are missing the required .ts file extensions; update the import paths to include
the .ts extension for each local module (e.g., '../cost-utils.ts' and
'../data-loader.ts') so they conform to the coding guidelines and the project's
module resolution rules.

Comment on lines +12 to +13
import { calculateCostForEntry } from '../cost-utils';
import { loadOpenCodeMessages, loadOpenCodeSessions } from '../data-loader';
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add .ts extensions to local file imports.

Local imports are missing the required .ts extension as specified in the coding guidelines.

🔎 Proposed fix
-import { calculateCostForEntry } from '../cost-utils';
-import { loadOpenCodeMessages, loadOpenCodeSessions } from '../data-loader';
+import { calculateCostForEntry } from '../cost-utils.ts';
+import { loadOpenCodeMessages, loadOpenCodeSessions } from '../data-loader.ts';

As per coding guidelines.

🤖 Prompt for AI Agents
In apps/opencode/src/commands/session.ts around lines 12 to 13, the two local
imports are missing the required .ts file extensions; update the import
specifiers to include the .ts extension (e.g. '../cost-utils.ts' and
'../data-loader.ts') so they comply with the project's coding guidelines and
resolve module resolution errors.

@ryoppippi
Copy link
Owner

@AnishDe12020 i was back from my vacation.
could you tell me how it works.
also i'd love you to update documentation as well!

thanks

@admdly
Copy link

admdly commented Jan 8, 2026

It would be great to see this merged. @ryoppippi is there anything specific needed to move this along?

@ryoppippi
Copy link
Owner

i think it looks good. i'll merge it in a couple of days

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.

Support for opencode

3 participants