Skip to content

Add profile usage summary command#4

Open
Hobeom wants to merge 1 commit into
Digital-Threads:masterfrom
Hobeom:feat/profile-usage
Open

Add profile usage summary command#4
Hobeom wants to merge 1 commit into
Digital-Threads:masterfrom
Hobeom:feat/profile-usage

Conversation

@Hobeom
Copy link
Copy Markdown

@Hobeom Hobeom commented May 14, 2026

Summary

  • add aimux usage to summarize transcript token usage by profile
  • support --profile, --since, and --all filters
  • deduplicate repeated transcript entries by request id and surface unmapped sessions as unknown
  • document the new command in the README

Notes

This builds on the existing session attribution logic from .claude.json and aimux session history. Historical shared transcripts that cannot be mapped to a profile are intentionally shown as unknown rather than guessed.

Closes #1

Test plan

  • npm test
  • npm run build
  • node dist/cli.js usage --since 24h

Copy link
Copy Markdown

@shahinyanm1-work shahinyanm1-work left a comment

Choose a reason for hiding this comment

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

Thanks for picking this up — the structure is good and the tests are a nice touch. Two things blocking the merge plus a couple of smaller notes.

Blockers

  1. requestKey includes sessionId, so when a session gets forked (claude --resume <id> --fork-session, which aimux does automatically on cross-profile attach), the original transcript and the forked one share the same requestId but live under different session ids. The dedupe key treats them as two requests and double-counts the tokens. Drop sessionId from the key when a requestId is present — request:<requestId> is enough.

  2. The walker reads every .jsonl under projects/ without filtering subagent transcripts. Real installs have thousands of those (classifier, memory, task-journal, etc.) — each one is a real assistant turn with message.usage, so they'll inflate "unknown" by a huge factor. sessionScanner.ts already has the logic — quickFirstLineType(path) === 'queue-operation' and parseSessionJsonl(path).isSubagent. Reuse those before parsing usage lines.

Should fix before merge

  1. estimatedCostUsd is summed into the summary but never shown in the table. Either add a COST column (formatted as $X.XX) or drop the field — right now it's dead work.

  2. In requestKey, the fallback when no id/uuid/requestId is found is Math.random(). That defeats the dedupe — every line gets a unique key. Either use a stable surrogate like ${sessionId}:line:${index} or just continue and skip the line.

Nit

  1. usage.test.ts calls setAimuxDir in beforeEach but never restores it. If something else in the test run depends on the default aimux dir, it'll pick up the tmpdir from this test. Save the previous value and restore in afterEach.

Happy to discuss any of these if my read of the code is off. Once 1 and 2 are sorted I'll take another pass.

@Shahinyanm Shahinyanm dismissed shahinyanm1-work’s stale review May 26, 2026 12:52

Re-posting from primary maintainer account.

Copy link
Copy Markdown
Member

@Shahinyanm Shahinyanm left a comment

Choose a reason for hiding this comment

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

Thanks for picking this up — structure is good and the tests are a nice touch. Two things blocking the merge plus a couple of smaller notes.

Blockers

  1. requestKey includes sessionId, so when a session gets forked (claude --resume <id> --fork-session, which aimux does automatically on cross-profile attach), the original transcript and the forked one share the same requestId but live under different session ids. The dedupe key treats them as two requests and double-counts the tokens. Drop sessionId from the key when a requestId is present — request:<requestId> is enough.

  2. The walker reads every .jsonl under projects/ without filtering subagent transcripts. Real installs have thousands of those (classifier, memory, task-journal, etc.) — each one is a real assistant turn with message.usage, so they'll inflate "unknown" by a huge factor. sessionScanner.ts already has the logic — quickFirstLineType(path) === 'queue-operation' and parseSessionJsonl(path).isSubagent. Reuse those before parsing usage lines.

Should fix before merge

  1. estimatedCostUsd is summed into the summary but never shown in the table. Either add a COST column (formatted as $X.XX) or drop the field — right now it's dead work.

  2. In requestKey, the fallback when no id/uuid/requestId is found is Math.random(). That defeats the dedupe — every line gets a unique key. Either use a stable surrogate like ${sessionId}:line:${index} or just continue and skip the line.

Nit

  1. usage.test.ts calls setAimuxDir in beforeEach but never restores it. If something else in the test run depends on the default aimux dir, it'll pick up the tmpdir from this test. Save the previous value and restore in afterEach.

Happy to discuss any of these if my read is off. Once 1 and 2 are sorted I'll take another pass.

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.

Feature request: show usage per profile

3 participants