feat(pi): auto-detect oh-my-pi (omp) sessions - #1338
Conversation
oh-my-pi (omp) is a widely used pi fork that writes identical JSONL session files with the same message.usage schema. Auto-detect ~/.omp/agent/sessions alongside ~/.pi/agent/sessions when neither --pi-path nor PI_AGENT_DIR is set, so omp users get usage reports without having to pass --pi-path manually. Both directories are scanned and entries are deduplicated by the loader; setting PI_AGENT_DIR or --pi-path overrides detection and scans only the given paths. Closes ccusage#1193 Signed-off-by: Stefan Giroux <[email protected]>
|
no API key found — this repo is configured to use To fix: add the key as a GitHub Actions secret (referenced from your workflow's Open repo secrets → · Configure model → · Setup docs → · Ask in Discord →
|
📝 WalkthroughWalkthroughAdds ChangesOMP Auto-Detection for Pi Adapter
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
This PR was auto-closed. Only contributors approved with Maintainers review auto-closed issues and reopen worthwhile ones. Issues that do not meet the quality bar in CONTRIBUTING.md may not be reopened or receive a reply. If a maintainer replies See CONTRIBUTING.md. |
|
Bump, would love to see omp support! |
Read the JSONL session files that pi and its widely used fork oh-my-pi (omp) write under ~/.pi/agent/sessions and ~/.omp/agent/sessions, and normalize each billable assistant message into the shared UsageData shape, aggregated alongside the other 6 sources. Both directories are auto-detected when neither PI_AGENT_DIR nor a custom path is set (matches upstream ccusage PR ccusage/ccusage#1338). Entries are deduplicated by the loader's createUniqueHash, so a session file present in both directories is counted once. Token accounting is additive (the Claude model): the four buckets (input/output/cacheRead/cacheWrite) are independent and summed, with NO subtraction of cached tokens from input (unlike Codex). The totalTokens fallback folds the surplus into output_tokens when output is 0 (matches upstream's apply_total_token_fallback). Cost: emits message.usage.cost.total (USD) so the default 'auto' cost mode uses it directly; 'calculate' mode recomputes from tokens. Per upstream omp PR #1338, models are NOT prefixed ([pi]/[omp]): both default directories share the 'pi' source label and pricing lookup. 17 new inline tests (record accept/reject, cache buckets, totalTokens fallback, non-object cost, zero-token/no-model skip, omp vs pi dedup, nested path extraction, path resolution, totalTokens fallback unit). Docs: new guide pi.md, README + env var (PI_AGENT_DIR) + sidebar. Backward compat verified: monthly --compact runs without regression. Ported from upstream ccusage (pi adapter default branch + PR #1338).
* feat(pi): add pi / oh-my-pi usage adapter with omp auto-detection Read the JSONL session files that pi and its widely used fork oh-my-pi (omp) write under ~/.pi/agent/sessions and ~/.omp/agent/sessions, and normalize each billable assistant message into the shared UsageData shape, aggregated alongside the other 6 sources. Both directories are auto-detected when neither PI_AGENT_DIR nor a custom path is set (matches upstream ccusage PR ccusage/ccusage#1338). Entries are deduplicated by the loader's createUniqueHash, so a session file present in both directories is counted once. Token accounting is additive (the Claude model): the four buckets (input/output/cacheRead/cacheWrite) are independent and summed, with NO subtraction of cached tokens from input (unlike Codex). The totalTokens fallback folds the surplus into output_tokens when output is 0 (matches upstream's apply_total_token_fallback). Cost: emits message.usage.cost.total (USD) so the default 'auto' cost mode uses it directly; 'calculate' mode recomputes from tokens. Per upstream omp PR #1338, models are NOT prefixed ([pi]/[omp]): both default directories share the 'pi' source label and pricing lookup. 17 new inline tests (record accept/reject, cache buckets, totalTokens fallback, non-object cost, zero-token/no-model skip, omp vs pi dedup, nested path extraction, path resolution, totalTokens fallback unit). Docs: new guide pi.md, README + env var (PI_AGENT_DIR) + sidebar. Backward compat verified: monthly --compact runs without regression. Ported from upstream ccusage (pi adapter default branch + PR #1338). * fix(pi): correct 'unparseable' typo flagged by typos spell-check ci(spell): unparseable -> unparsable * fix(pi): integrate sourceFilter gate from #51 into pi loader blocks Rebased onto main (which merged #51 adding source filtering via `better-ccusage <source> <report>`). The pi load blocks in the 3 loaders (loadDailyUsageData, loadSessionData, loadSessionBlockData) were added before #51 and lacked the sourceFilter gate, so `better-ccusage pi daily` would not isolate pi. Wrap each pi block in `if (sourceFilter == null || sourceFilter === 'pi')` to match the devin/codex/opencode pattern. Verified e2e: `better-ccusage pi daily` now isolates pi; global `daily` still aggregates all sources (backward compat). * docs: accurate source inventory (7 tools) + fork positioning vs upstream The README 'About'/'Why the Fork' and the docs index/getting-started sections were outdated: they listed only Claude/Droid/ZCode and framed the fork as 'ccusage only supports Claude Code'. Both are now inaccurate — better-ccusage supports 7 sources and upstream ccusage has itself diverged into a Rust workspace with its own source set. - README: new 'Supported data sources' table (7 tools + data locations), rewritten 'Why the fork' covering multi-source AND multi-provider, explicit divergence note (TS monorepo vs Rust workspace), pi added to tagline + source-filter examples. - docs/index.md: intro mentions all 7 tools; 'Why better-ccusage' rewritten with the same multi-source + multi-provider framing and the upstream-divergence callout. - getting-started.md: prerequisites list all 7 tools and the SQLite runtime requirement (Node 22.13+ for zcode/opencode/devin). * fix(pi): dedup multi-dir entries in adapter + correct doc links Address CodeRabbit major review (2x): loadSessionData and loadSessionBlockData don't run the createUniqueHash gate on non-Claude source loops, so pi (which scans BOTH ~/.pi and ~/.omp) could double-count sessions present in both directories. Fix at the adapter boundary: processPiSessions now deduplicates by message.id (which encodes sessionId + timestamp + model + token buckets) before returning, so no entry set is counted twice regardless of the loader. Test 'deduplicates omp vs pi' updated: same content in both dirs now yields 1 entry (was 2, relying on downstream dedup that doesn't exist for these loaders). New test 'keeps distinct sessions that share a timestamp' verifies genuinely different sessions are preserved. Also drop speculative pi/omp GitHub links from docs/guide/pi.md (the repos are not verified; pi is a product, not an open CLI repo) and add pi to the devin.md source list.
|
@pullfrog review it |
|
@pullfrog resolve conflicts |
@ryoppippi I have started the AI code review. It will take a few minutes to complete. |
|
Resolved the merge conflicts between Files resolved:
However, the push failed:
Task list (4/4 completed)
|
|
✅ Action performedReview finished.
|
I reviewed the diff on the PR head ( Verdict: looks good, safe to merge. The change is minimal, correct, and well-tested, and it follows the repo's cross-cutting docs flow (getting-started, pi guide, and the adapter README are all updated in the same commit). What I checked:
Two minor, non-blocking notes:
I didn't run |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/guide/getting-started.md`:
- Line 172: Update the pi-agent entry in the getting-started documentation to
state that ~/.omp/agent/sessions is auto-scanned only when neither PI_AGENT_DIR
nor the --pi-path option is set; preserve the existing PI_AGENT_DIR path
description.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 2dd43b71-1734-4992-8677-71e3c86b5290
📒 Files selected for processing (4)
docs/guide/getting-started.mddocs/guide/pi/index.mdrust/crates/ccusage/src/adapter/pi/README.mdrust/crates/ccusage/src/adapter/pi/paths.rs
| - Codebuff: `${CODEBUFF_DATA_DIR:-~/.config/manicode}` | ||
| - Hermes Agent: `${HERMES_HOME:-~/.hermes}/state.db` | ||
| - pi-agent: `${PI_AGENT_DIR:-~/.pi/agent/sessions}` | ||
| - pi-agent: `${PI_AGENT_DIR:-~/.pi/agent/sessions}` (also auto-scans `~/.omp/agent/sessions` for oh-my-pi) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Qualify OMP auto-detection by the override condition.
When PI_AGENT_DIR is set, the adapter returns those paths and does not scan ~/.omp/agent/sessions. Update this entry to say OMP is auto-scanned only when neither PI_AGENT_DIR nor --pi-path is set.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/guide/getting-started.md` at line 172, Update the pi-agent entry in the
getting-started documentation to state that ~/.omp/agent/sessions is
auto-scanned only when neither PI_AGENT_DIR nor the --pi-path option is set;
preserve the existing PI_AGENT_DIR path description.
There was a problem hiding this comment.
1 issue found across 4 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="docs/guide/getting-started.md">
<violation number="1" location="docs/guide/getting-started.md:172">
P3: The parenthetical "(also auto-scans `~/.omp/agent/sessions` for oh-my-pi)" is unconditionally attached to the `PI_AGENT_DIR` line, implying OMP is always scanned. However, looking at `paths.rs`, when `PI_AGENT_DIR` or `--pi-path` is set the adapter returns early and never reaches `default_session_dirs`. Consider qualifying this, e.g., "(when no override is set, also auto-scans `~/.omp/agent/sessions` for oh-my-pi)" to match the actual behavior documented in `docs/guide/pi/index.md`.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| - Codebuff: `${CODEBUFF_DATA_DIR:-~/.config/manicode}` | ||
| - Hermes Agent: `${HERMES_HOME:-~/.hermes}/state.db` | ||
| - pi-agent: `${PI_AGENT_DIR:-~/.pi/agent/sessions}` | ||
| - pi-agent: `${PI_AGENT_DIR:-~/.pi/agent/sessions}` (also auto-scans `~/.omp/agent/sessions` for oh-my-pi) |
There was a problem hiding this comment.
P3: The parenthetical "(also auto-scans ~/.omp/agent/sessions for oh-my-pi)" is unconditionally attached to the PI_AGENT_DIR line, implying OMP is always scanned. However, looking at paths.rs, when PI_AGENT_DIR or --pi-path is set the adapter returns early and never reaches default_session_dirs. Consider qualifying this, e.g., "(when no override is set, also auto-scans ~/.omp/agent/sessions for oh-my-pi)" to match the actual behavior documented in docs/guide/pi/index.md.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docs/guide/getting-started.md, line 172:
<comment>The parenthetical "(also auto-scans `~/.omp/agent/sessions` for oh-my-pi)" is unconditionally attached to the `PI_AGENT_DIR` line, implying OMP is always scanned. However, looking at `paths.rs`, when `PI_AGENT_DIR` or `--pi-path` is set the adapter returns early and never reaches `default_session_dirs`. Consider qualifying this, e.g., "(when no override is set, also auto-scans `~/.omp/agent/sessions` for oh-my-pi)" to match the actual behavior documented in `docs/guide/pi/index.md`.</comment>
<file context>
@@ -169,7 +169,7 @@ If ccusage shows no data, check:
- Codebuff: `${CODEBUFF_DATA_DIR:-~/.config/manicode}`
- Hermes Agent: `${HERMES_HOME:-~/.hermes}/state.db`
- - pi-agent: `${PI_AGENT_DIR:-~/.pi/agent/sessions}`
+ - pi-agent: `${PI_AGENT_DIR:-~/.pi/agent/sessions}` (also auto-scans `~/.omp/agent/sessions` for oh-my-pi)
- Goose: standard Goose data roots or `GOOSE_PATH_ROOT`
- Kilo: `${KILO_DATA_DIR:-~/.local/share/kilo}`
</file context>
| - pi-agent: `${PI_AGENT_DIR:-~/.pi/agent/sessions}` (also auto-scans `~/.omp/agent/sessions` for oh-my-pi) | |
| - pi-agent: `${PI_AGENT_DIR:-~/.pi/agent/sessions}` (also auto-scans `~/.omp/agent/sessions` for oh-my-pi when no override is set) |
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — Auto-detect oh-my-pi (omp) session directories alongside pi-agent defaults, scan both when no override is set, and update the pi adapter docs and tests.
- Auto-detect both
~/.pi/agent/sessionsand~/.omp/agent/sessionswhen neither--pi-pathnorPI_AGENT_DIRis set. - Replace the single default path with an ordered list in
rust/crates/ccusage/src/adapter/pi/paths.rswhile keeping the override paths behavior unchanged. - Add fixture-backed unit tests covering all default-directory combinations (both present, only pi, only omp, neither).
- Update user-facing docs in
docs/guide/pi/index.mdanddocs/guide/getting-started.mdto describe the new auto-detection behavior.
@v0 or keep the SHA fresh with Dependabot | View workflow run | Using Kimi K2 (free via Pullfrog for OSS) | 𝕏
|
@ryoppippi |
|
sorry! i'll take care of it |
|
@pullfrog plz fix conflicts |
|
I resolved the merge conflicts in PR #1338 and verified the changes, but I cannot push the resolution to the fork branch. What I did:
Blocker: The resolved merge commit is on the local Task list (4/5 completed)
|
|
Thanks for putting this together, and sorry for the slow reply. Since this PR was opened, #1397 landed named pi-format stores, which covers this use case in a more general way. omp is the documented example for it: {
"$schema": "https://ccusage.com/config-schema.json",
"pi": {
"stores": [
{ "name": "omp", "path": "~/.omp/agent/sessions" }
]
}
}That reports omp alongside the default Auto-detecting I verified this by porting the change onto current main (the pi adapter has since moved to The code itself is good — main just grew a different solution in the meantime. Closing for that reason. Thanks again for the contribution, and for following up on #1193. |

oh-my-pi (omp) is a widely used pi fork that writes identical JSONL session files with the same message.usage schema.
Auto-detect ~/.omp/agent/sessions alongside ~/.pi/agent/sessions when neither --pi-path nor PI_AGENT_DIR is set, so omp users get usage reports without having to pass --pi-path manually.
Both directories are scanned and entries are deduplicated by the loader; setting PI_AGENT_DIR or --pi-path overrides detection and scans only the given paths.
Closes #1193
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Summary by cubic
Auto-detect
~/.omp/agent/sessionsalongside~/.pi/agent/sessionsso oh-my-pi users get usage reports without setting--pi-pathorPI_AGENT_DIR.--pi-pathnorPI_AGENT_DIRis set, scan both default dirs; overrides scan only the provided paths.Written for commit c0241a9. Summary will update on new commits.
Summary by CodeRabbit
New Features
~/.pi/agent/sessionsand~/.omp/agent/sessionswhen custom paths aren’t specified.Documentation
PI_AGENT_DIR/--pi-path.Tests