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
25 changes: 24 additions & 1 deletion src/gain.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::Result;
use crate::tracking::Tracker;

pub fn run(graph: bool, history: bool, verbose: u8) -> Result<()> {
pub fn run(graph: bool, history: bool, quota: bool, tier: &str, _verbose: u8) -> Result<()> {
let tracker = Tracker::new()?;
let summary = tracker.get_summary()?;

Expand Down Expand Up @@ -68,6 +68,29 @@ pub fn run(graph: bool, history: bool, verbose: u8) -> Result<()> {
}
}

if quota {
const ESTIMATED_PRO_MONTHLY: usize = 6_000_000; // ~6M tokens/month (heuristic: ~44K/5h × 6 periods/day × 30 days)

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

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

The inline comment states "~44K/5h × 6 periods/day × 30 days" but this calculation yields approximately 7.9M tokens, not 6M. Additionally, 24 hours divided by 5-hour periods equals 4.8 periods per day, not 6. The constant value of 6M appears to be based on different assumptions than what the comment describes. Consider either: 1) updating the comment to accurately reflect the calculation (e.g., "~44K/5h × 4.5 periods/day × 30 days"), or 2) clarifying that this is a conservative estimate with different assumptions.

Suggested change
const ESTIMATED_PRO_MONTHLY: usize = 6_000_000; // ~6M tokens/month (heuristic: ~44K/5h × 6 periods/day × 30 days)
const ESTIMATED_PRO_MONTHLY: usize = 6_000_000; // ~6M tokens/month (heuristic: ~44K/5h × 4.5 periods/day × 30 days)

Copilot uses AI. Check for mistakes.

let (quota_tokens, tier_name) = match tier {
"pro" => (ESTIMATED_PRO_MONTHLY, "Pro ($20/mo)"),
"5x" => (ESTIMATED_PRO_MONTHLY * 5, "Max 5x ($100/mo)"),
"20x" => (ESTIMATED_PRO_MONTHLY * 20, "Max 20x ($200/mo)"),
_ => (ESTIMATED_PRO_MONTHLY, "Pro ($20/mo)"), // default fallback
};

let quota_pct = (summary.total_saved as f64 / quota_tokens as f64) * 100.0;

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

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

The quota output should be preceded by an empty line to visually separate it from the previous section (history, graph, or command summary). Looking at lines 46, 47, and 68-69 in the same file, other sections include a blank line after them. The quota section should follow the same pattern by adding a println!(); before line 83 to maintain consistency with the existing output formatting.

Suggested change
println!();

Copilot uses AI. Check for mistakes.
println!("Monthly Quota Analysis:");
println!("────────────────────────────────────────");
println!("Subscription tier: {}", tier_name);
println!("Estimated monthly quota: {}", format_tokens(quota_tokens));
println!("Tokens saved (lifetime): {}", format_tokens(summary.total_saved));
println!("Quota preserved: {:.1}%", quota_pct);
println!();
println!("Note: Heuristic estimate based on ~44K tokens/5h (Pro baseline)");
println!(" Actual limits use rolling 5-hour windows, not monthly caps.");
}
Comment on lines +71 to +92

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

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

The new quota calculation logic lacks test coverage. The repository has comprehensive test coverage (tests found in filter.rs, git.rs, grep_cmd.rs, json_cmd.rs, local_llm.rs, log_cmd.rs, ls.rs, pnpm_cmd.rs, read.rs, runner.rs, vitest_cmd.rs), but gain.rs has no tests. Consider adding unit tests to verify: 1) correct quota calculations for each tier (pro, 5x, 20x), 2) the format_tokens function works correctly with the quota values, 3) percentage calculations are accurate, and 4) edge cases like zero total_saved.

Copilot uses AI. Check for mistakes.

Ok(())
}

Expand Down
10 changes: 8 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,12 @@ enum Commands {
/// Show recent command history
#[arg(short = 'H', long)]
history: bool,
/// Show monthly quota savings estimate
#[arg(short, long)]
quota: bool,
/// Subscription tier for quota calculation: pro, 5x, 20x
#[arg(short, long, default_value = "20x", requires = "quota")]

Copilot AI Jan 29, 2026

Copy link

Choose a reason for hiding this comment

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

The tier parameter accepts any string value but silently falls back to "pro" for invalid values (line 78). This could lead to user confusion. Consider using clap's value_parser with PossibleValue to restrict input to valid values ("pro", "5x", "20x") and provide clear error messages for invalid input. This would make the CLI more robust and user-friendly by catching errors at parse time rather than silently using a fallback.

Suggested change
#[arg(short, long, default_value = "20x", requires = "quota")]
#[arg(
short,
long,
default_value = "20x",
requires = "quota",
value_parser = ["pro", "5x", "20x"]
)]

Copilot uses AI. Check for mistakes.
tier: String,
},

/// Show or create configuration file
Expand Down Expand Up @@ -519,8 +525,8 @@ fn main() -> Result<()> {
}
}

Commands::Gain { graph, history } => {
gain::run(graph, history, cli.verbose)?;
Commands::Gain { graph, history, quota, tier } => {
gain::run(graph, history, quota, &tier, cli.verbose)?;
}

Commands::Config { create } => {
Expand Down
Loading