Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

- Build: `dotnet build AIUsageMonitor.slnx`
- Run CLI (binary name is `aimon`): `dotnet run --project src/AIUsageMonitor.Cli -- <command>`
- Commands: `today`, `week`, `month`, `models`, `sessions`, `hours`, `export`
- Commands: `today`, `week`, `month`, `models`, `sessions`, `hours`, `watch`, `export`
- `watch` takes a sub-view (`today|week|models|sessions|hours`) and refreshes it on an interval
- `export` supports `--format json|csv` and `--output <path>` (defaults to stdout, JSON)
- Run WPF app (Windows-only): `dotnet run --project src/AIUsageMonitor.WPF`
- Run tests: `dotnet test AIUsageMonitor.slnx`
- Single test: `dotnet test tests/AIUsageMonitor.Core.Tests --filter "FullyQualifiedName~MethodName"`
- Versioning is via MinVer, driven by `v*` git tags (prefix `v`); no manual version bumps in project files.

## Architecture

Expand Down Expand Up @@ -40,3 +43,7 @@ DI is wired through `ServiceCollectionExtensions.AddClaudeUsageCore()`, which re
### WPF

`DashboardViewModel` polls `DataService` on a `DispatcherTimer` (once per minute) and renders daily/model/hourly series via LiveChartsCore, using CommunityToolkit.Mvvm for the MVVM plumbing.

### Releases

Pushing a `v*` tag (see `.github/workflows/ci.yml`) builds self-contained CLI binaries for win-x64/linux-x64/osx-x64/osx-arm64, attaches them to a GitHub release (marked pre-release for prerelease tags), and publishes the `aimon` dotnet tool to NuGet. The NuGet publish job runs on `ubuntu` specifically to avoid a `pwsh` glob issue.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# AIUsageMonitor

[![CI](https://github.com/coldhighsun/AIUsageMonitor/actions/workflows/ci.yml/badge.svg)](https://github.com/coldhighsun/AIUsageMonitor/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![.NET](https://img.shields.io/badge/.NET-10.0-512BD4?logo=dotnet&logoColor=white)](https://dotnet.microsoft.com/)
[![GitHub release](https://img.shields.io/github/v/release/coldhighsun/AIUsageMonitor?logo=github)](https://github.com/coldhighsun/AIUsageMonitor/releases/latest)
[![GitHub Release Downloads](https://img.shields.io/github/downloads/coldhighsun/AIUsageMonitor/total?logo=github&label=release%20downloads)](https://github.com/coldhighsun/AIUsageMonitor/releases)
[![NuGet Tool Downloads](https://img.shields.io/nuget/dt/AIUsageMonitor.Cli?logo=nuget&label=nuget%20downloads)](https://www.nuget.org/packages/AIUsageMonitor.Cli)
[![Platform](https://img.shields.io/badge/platform-Windows%20%7C%20cross--platform%20CLI-0078D6?logo=windows&logoColor=white)](#projects)
[![GitHub last commit](https://img.shields.io/github/last-commit/coldhighsun/AIUsageMonitor)](https://github.com/coldhighsun/AIUsageMonitor/commits/main)
[![GitHub stars](https://img.shields.io/github/stars/coldhighsun/AIUsageMonitor?style=flat)](https://github.com/coldhighsun/AIUsageMonitor/stargazers)
[![GitHub issues](https://img.shields.io/github/issues/coldhighsun/AIUsageMonitor)](https://github.com/coldhighsun/AIUsageMonitor/issues)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md)

[English](#english) | [中文](#chinese)

Expand Down
1 change: 1 addition & 0 deletions src/AIUsageMonitor.Cli/AIUsageMonitor.Cli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<RepositoryUrl>https://github.com/coldhighsun/AIUsageMonitor</RepositoryUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>claude;claude-code;anthropic;cli;usage;analytics;dotnet-tool;tokens;cost</PackageTags>
</PropertyGroup>

<ItemGroup>
Expand Down
8 changes: 4 additions & 4 deletions src/AIUsageMonitor.Cli/Rendering/SpectreRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static IRenderable BuildDailySummary(DailySummary summary)
return table;
}

var chart = new BarChart().Label("[bold]Tokens by Model[/]").Width(80).UseValueFormatter(v => ((long)v).ToString("N0"));
var chart = new BarChart().Label("[bold]Tokens by Model[/]").Width(80).UseValueFormatter(v => FormatTokens((long)v));
var colorIndex = 0;
var colors = new[] { Color.Blue, Color.Green, Color.Yellow, Color.Red, Color.Purple, Color.Orange1, Color.Cyan1 };
foreach (var (model, tokens) in summary.TokensByModel.OrderByDescending(x => x.Value))
Expand Down Expand Up @@ -51,7 +51,7 @@ public static IRenderable BuildPeriodSummary(PeriodSummary summary)
return table;
}

var chart = new BarChart().Label("[bold]Daily Tokens[/]").Width(80).UseValueFormatter(v => ((long)v).ToString("N0"));
var chart = new BarChart().Label("[bold]Daily Tokens[/]").Width(80).UseValueFormatter(v => FormatTokens((long)v));
var colorIndex = 0;
foreach (var day in summary.DailyBreakdown)
{
Expand Down Expand Up @@ -115,7 +115,7 @@ public static IRenderable BuildSessionStats(SessionStats stats)

public static IRenderable BuildHourlyActivity(List<HourlyActivity> hours)
{
var chart = new BarChart().Label("[bold]Tokens by Hour[/]").Width(80).UseValueFormatter(v => ((long)v).ToString("N0"));
var chart = new BarChart().Label("[bold]Tokens by Hour[/]").Width(80).UseValueFormatter(v => FormatTokens((long)v));
var colorIndex = 0;
foreach (var h in hours)
{
Expand All @@ -127,7 +127,7 @@ public static IRenderable BuildHourlyActivity(List<HourlyActivity> hours)

public static IRenderable BuildHourlyTokenChart(List<HourBucket> buckets)
{
var chart = new BarChart().Label("[bold]Tokens by Hour[/]").Width(80).UseValueFormatter(v => ((long)v).ToString("N0"));
var chart = new BarChart().Label("[bold]Tokens by Hour[/]").Width(80).UseValueFormatter(v => FormatTokens((long)v));
var colorIndex = 0;
foreach (var bucket in buckets)
{
Expand Down
2 changes: 1 addition & 1 deletion src/AIUsageMonitor.WPF/ViewModels/DashboardViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ private void BuildHourlyChart(List<HourlyActivity> hours)

HourlyYAxes =
[
new() { Labeler = value => value.ToString("N0") }
new() { Labeler = value => FormatTokens((long)value) }
];
}

Expand Down
Loading