fix!: remove session order flag#613
Conversation
There was a problem hiding this comment.
Summary of Changes
Hello @amorriscode, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request streamlines the ccusage session command by removing an unnecessary sorting flag. The associated documentation has been updated to reflect this change, ensuring users are aware of the simplified command structure and the default sorting behavior for session reports.
Highlights
- Command Line Interface Simplification: The --order flag has been removed from the ccusage session command, simplifying its usage.
- Documentation Updates: The documentation for ccusage session has been updated to reflect the removal of the --order flag and to clarify that session reports now default to sorting by most expensive sessions.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Code Review
This pull request correctly removes the --order flag from the session command and updates the documentation accordingly. This is a good simplification. My review found one high-severity issue: there is a discrepancy between the documented sorting behavior (by cost) and the actual implementation (by date) for session reports. This should be addressed to avoid user confusion.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/commands/session.ts (3)
41-47: Critical: mixed use of ctx.values vs mergedOptions drops config-file overrides for session listing.You compute mergedOptions but most of the non-—id path still reads ctx.values, so config.yml overrides (e.g., timezone/locale/compact/offline/mode/jq/debug) won’t apply. Use mergedOptions consistently.
-const config = loadConfig(ctx.values.config, ctx.values.debug); -const mergedOptions: typeof ctx.values = mergeConfigWithArgs(ctx, ctx.values.debug); +const config = loadConfig(ctx.values.config, ctx.values.debug); +const mergedOptions: typeof ctx.values = mergeConfigWithArgs(ctx, ctx.values.debug); @@ -const sessionData = await loadSessionData({ - since: ctx.values.since, - until: ctx.values.until, - mode: ctx.values.mode, - offline: ctx.values.offline, - timezone: ctx.values.timezone, - locale: ctx.values.locale, -}); +const sessionData = await loadSessionData({ + since: mergedOptions.since, + until: mergedOptions.until, + mode: mergedOptions.mode, + offline: mergedOptions.offline, + timezone: mergedOptions.timezone, + locale: mergedOptions.locale, +}); @@ -if (ctx.values.debug && !useJson) { +if (mergedOptions.debug && !useJson) { const mismatchStats = await detectMismatches(undefined); - printMismatchReport(mismatchStats, ctx.values.debugSamples); + printMismatchReport(mismatchStats, mergedOptions.debugSamples); } @@ -if (ctx.values.jq != null) { - const jqResult = await processWithJq(jsonOutput, ctx.values.jq); +if (mergedOptions.jq != null) { + const jqResult = await processWithJq(jsonOutput, mergedOptions.jq); @@ - dateFormatter: (dateStr: string) => formatDateCompact(dateStr, ctx.values.timezone, ctx.values.locale), - forceCompact: ctx.values.compact, + dateFormatter: (dateStr: string) => formatDateCompact(dateStr, mergedOptions.timezone, mergedOptions.locale), + forceCompact: mergedOptions.compact, @@ -if (ctx.values.breakdown) { +if (mergedOptions.breakdown) {Also applies to: 66-73, 89-93, 114-121, 134-136, 158-159
65-75: Guarantee default sort by cost desc in the command to fully resolve #350.Docs promise cost-desc sorting by default. If loadSessionData doesn’t already sort, results may be unsorted. Sort here defensively.
-// Original session listing logic -const sessionData = await loadSessionData({ +// Original session listing logic +const sessionData = await loadSessionData({ since: mergedOptions.since, until: mergedOptions.until, mode: mergedOptions.mode, offline: mergedOptions.offline, timezone: mergedOptions.timezone, locale: mergedOptions.locale, }); + +// Ensure default sort by cost (highest first) +sessionData.sort((a, b) => (b.totalCost ?? 0) - (a.totalCost ?? 0));
86-93: Use mergedOptions for all flag checks
Replace everyctx.values.*reference aftermergeConfigWithArgswith the correspondingmergedOptions.*(e.g. since/until/mode/offline/timezone/locale inloadSessionData,debuganddebugSamples,jq,compact,breakdown) so that CLI flags respect merged defaults.
🧹 Nitpick comments (6)
docs/guide/getting-started.md (1)
86-90: Docs: Example correctly reflects flag removal; consider adding a one‑line note about default sort.To reduce user confusion after removing --order/--desc, add a sentence below the code block pointing to the Sessions “Sorting” section that states sessions are sorted by cost (highest first) by default.
docs/guide/session-reports.md (1)
219-221: Docs: Nice update; add an explicit note that --order/--desc is no longer supported.A short “Note: --order has been removed; sessions are always sorted by cost (highest first)” will help users migrating from earlier versions.
src/commands/session.ts (4)
24-26: Fix ESLint no-unused-vars by renaming the omitted key.Rename the destructured key binding so it’s clearly intentional and lint-clean.
-// All shared args except --order (not supported for session) -const { order, ...sharedArgs } = sharedCommandConfig.args; +// All shared args except --order (not supported for session) +const { order: _order, ...sharedArgs } = sharedCommandConfig.args;
27-39: Type-safety around define(): address no-unsafe-call from ESLint.If gunshi lacks types, ESLint flags define() calls. Either add types for gunshi or narrowly disable the rule for this call with context.
// Option A (preferred): add proper typings for gunshi's define() // declare module "gunshi" { export function define<T>(cfg: T): T; } // Option B (narrow suppression): // eslint-disable-next-line @typescript-eslint/no-unsafe-call export const sessionCommand = define({ ... });
39-39: Remove duplicate toKebab: true (already spread from sharedCommandConfig).Minor cleanup; avoids confusion.
- toKebab: true,
140-145: Remove unused maxSessionLength.It’s calculated but never used.
-// Add session data -let maxSessionLength = 0; for (const data of sessionData) { const sessionDisplay = data.sessionId.split("-").slice(-2).join("-"); - - maxSessionLength = Math.max(maxSessionLength, sessionDisplay.length);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
docs/guide/getting-started.md(1 hunks)docs/guide/session-reports.md(1 hunks)src/commands/session.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
docs/guide/*.md
📄 CodeRabbit inference engine (CLAUDE.md)
Use image paths like "/screenshot.png" for images stored in /docs/public/ and always include descriptive alt text
Files:
docs/guide/session-reports.mddocs/guide/getting-started.md
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use tab indentation and double quotes; format with ESLint
Do not use console.log; use logger.ts instead (only allow console.log when explicitly eslint-disabled)
Use .ts extensions for local file imports (e.g., import { foo } from "./utils.ts")
Prefer @praha/byethrow Result type over traditional try-catch; use Result.try(), Result.isFailure()/isSuccess() and early returns; reserve try-catch for complex file I/O or legacy code
For async operations, wrap with a function using Result.try() and call it
Variables use camelCase; Types use PascalCase; Constants may use UPPER_SNAKE_CASE
Only export constants/functions/types that are used by other modules; keep internal/private items non-exported
Always use Node.js path utilities for file paths for cross-platform compatibility
Use in-source testing blocks guarded by if (import.meta.vitest != null); do not create separate test files
Use Vitest globals (describe, it, expect) without imports inside test blocks
Only use dynamic imports (await import()) inside test blocks to avoid tree-shaking issues
Mock data in tests should use fs-fixture createFixture() for Claude data directory simulation
Tests must use current Claude 4 models (Sonnet and Opus) and cover both; do not use Claude 3 models
Model names in tests must exactly match LiteLLM pricing database entries
Files:
src/commands/session.ts
🧬 Code graph analysis (1)
src/commands/session.ts (1)
src/_shared-args.ts (2)
sharedArgs(23-115)sharedCommandConfig(120-123)
🪛 ESLint
src/commands/session.ts
[error] 25-25: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 25-25: 'order' is assigned a value but never used.
(ts/no-unused-vars)
[error] 27-27: Unsafe call of a(n) error type typed value.
(ts/no-unsafe-call)
| // All shared args except --order (not supported for session) | ||
| const { order, ...sharedArgs } = sharedCommandConfig.args; | ||
|
|
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Verify behavioral change: --order flag removal and default cost sort.
- Ensure CLI now rejects or ignores --order for session.
- Confirm sessions are indeed sorted by cost desc end-to-end.
Also applies to: 32-32, 65-75
🏁 Script executed:
#!/bin/bash
# 1) Check that session command args no longer include 'order'
rg -n 'session' src/commands -C3 | sed -n '1,160p'
rg -n '\border\b' src/commands/session.ts src/_shared-args.ts -C2
# 2) Verify loadSessionData does not re-sort to date and, if it does, that session.ts sorts by cost after call
rg -nP '(loadSessionData|sort\()' src -C3
# 3) Search docs for any remaining usage of --order/--desc
rg -nP --glob 'docs/**' '\-\-order|\-\-desc|\border\s+desc' -C2Length of output: 24177
🏁 Script executed:
#!/bin/bash
sed -n '850,930p' src/data-loader.tsLength of output: 2743
🏁 Script executed:
#!/bin/bash
# Show the function around the cost-based sort to confirm its context
sed -n '400,480p' src/data-loader.tsLength of output: 2154
🏁 Script executed:
#!/bin/bash
rg -nP 'export (type|interface) SessionUsage' src/data-loader.ts -C5Length of output: 348
Implement cost-based sorting for session command
Session entries are still ordered by date (default from loadSessionData) instead of cost. In src/commands/session.ts immediately after line 66 (the loadSessionData call), add:
// Sort sessions by total cost descending (highest cost first)
sessionData.sort((a, b) => b.totalCost - a.totalCost);🧰 Tools
🪛 ESLint
[error] 25-25: Unsafe assignment of an error typed value.
(ts/no-unsafe-assignment)
[error] 25-25: 'order' is assigned a value but never used.
(ts/no-unused-vars)
🤖 Prompt for AI Agents
In src/commands/session.ts around line 66 (immediately after the loadSessionData
call), session entries are still ordered by date; to implement cost-based
sorting, call sessionData.sort((a, b) => b.totalCost - a.totalCost) so sessions
are ordered by totalCost descending (highest cost first). Place this single-line
sort right after loadSessionData returns and before any rendering or output
logic.
commit: |

Resolves #350
Summary by CodeRabbit
Refactor
Documentation
Chores