Skip to content

feat(cli): add projects command and sessions --list - #52

Merged
coldhighsun merged 3 commits into
mainfrom
feat/cli-projects
Oct 9, 2026
Merged

coldhighsun merged 3 commits into
mainfrom
feat/cli-projects

Conversation

@coldhighsun

Copy link
Copy Markdown
Owner

Summary

  • aimon projects: token usage and estimated cost per project, ordered by --sort tokens|cost|sessions|messages.
  • aimon sessions --list: the individual sessions, ordered by --sort tokens|cost|messages|duration|start.
  • Both default to the last 30 days and take the date range options (--from/--to, --last, --month), --top, --project, --model and --json. A table gets a Messages column when ordered by messages; the project name is shortened from the left to fit the console width.
  • sessions without --list is unchanged; giving it a range, --top, --sort, --project or --model without --list is an error instead of being ignored.
  • Core: SessionUsageBuilder aggregates the transcripts per session for a range of local days. A session is identified by the session id on each line, so one resumed across several files is a single session, copied lines are counted once and stay with the original session and project folder (transcripts are named after their session, so a line's home transcript is counted first), and a streamed response is counted once. DataService.GetSessionUsage / GetProjectUsage expose the result.
  • Token counting and pricing now live in one place (ModelTokenTotals, TokenUsage.TotalTokens) instead of being copied in each builder.
  • Removes the unused SessionParser.ParseSessionSummary / SessionSummary, and corrects the stale GetSessionSummaries text in CLAUDE.md.

Behaviour notes

  • Sessions are clipped to the range, so a session that started earlier shows only what happened inside it. messages counts transcript lines (a streamed response is several), and duration is the wall-clock span between the first and last message, idle gaps included.
  • For the same days, tokens and messages match aimon month exactly. The cost here prices every message exactly (including 5-minute and 1-hour cache writes), so it differs a little from month, which scales an all-time model mix; month also counts a session once per day it was active.
  • --model for sessions counts only the assistant messages of matching models.

Test plan

  • dotnet build AIUsageMonitor.slnx (no warnings)
  • dotnet test AIUsageMonitor.slnx (388 passed)
  • The first commit also builds and passes the Core tests on its own
  • Ran projects, sessions --list (--top, --sort, --project, --model, --json, invalid ranges and options) against real local data; tokens and messages reconcile with aimon month for the same days

RecentActivityBuilder and SessionBlockBuilder each summed a response's tokens, split cache writes by lifetime and priced them with their own copy of the same code, and a response total was spelled out again in StatsCacheBuilder and HourlyActivityBuilder. Add ModelTokenTotals for the per-model sums and cost, and TokenUsage.TotalTokens for a response's total, and use them everywhere.
Add per-session and per-project usage. SessionUsageBuilder aggregates the transcripts by the session id on each line, across files, for a range of local days: resumed copies are counted once and stay with the original session and project folder, a streamed response is counted once, and a model filter counts only matching assistant messages. DataService exposes GetSessionUsage and GetProjectUsage, with a project text filter. aimon projects and aimon sessions --list take the date range options, --top, --sort, --project, --model and --json, default to the last 30 days, and share their flow in UsageList. sessions without --list is unchanged and rejects the list options. Remove the unused SessionParser.ParseSessionSummary and SessionSummary.
@codecov

codecov Bot commented Oct 9, 2026

Copy link
Copy Markdown

@coldhighsun
coldhighsun merged commit 5e2d4e7 into main Oct 9, 2026
9 checks passed
@coldhighsun
coldhighsun deleted the feat/cli-projects branch October 9, 2026 14:53
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.

1 participant