Skip to content

Context and Cost data from stdin#17

Merged
kostyay merged 3 commits intokostyay:mainfrom
saar120:feat/context-window-stdin
Feb 10, 2026
Merged

Context and Cost data from stdin#17
kostyay merged 3 commits intokostyay:mainfrom
saar120:feat/context-window-stdin

Conversation

@saar120
Copy link
Contributor

@saar120 saar120 commented Feb 9, 2026

Use context_window and cost data from Claude Code's stdin JSON instead of parsing the transcript JSONL file
Fall back to transcript parsing for older Claude Code versions that don't provide context_window
Add fmtCost and fmtDuration template functions for displaying session cost and duration

saar120 and others added 2 commits February 8, 2026 22:20
Prefer pre-calculated context_window.used_percentage from Claude Code
stdin over transcript JSONL parsing, fixing inaccurate context % display.
Add cost/duration fields and fmtCost/fmtDuration template functions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Owner

@kostyay kostyay left a comment

Choose a reason for hiding this comment

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

Overall: good feature with clean fallback logic. Struct definitions match the official Claude Code statusline API correctly. Using used_percentage over raw tokens is the right call given bug #13783 (cumulative tokens in total_input_tokens/total_output_tokens). A few suggestions below.

// autoCompactScaleFactor converts a percentage of the full context window to a percentage
// of the usable context (80% auto-compact threshold). This matches the calculation in
// tokens.GetContextConfig where UsableTokens = MaxTokens * 0.8.
const autoCompactScaleFactor = 1.0 / 0.8 // 1.25
Copy link
Owner

Choose a reason for hiding this comment

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

This constant duplicates the 0.8 threshold already defined in tokens.GetContextConfig (UsableTokens = MaxTokens * 0.8). If that threshold ever changes, this will silently diverge.

Also, the 4-line const + if/cap block can collapse to one line with Go's builtin min():

// Scale to usable context (80% auto-compact threshold → multiply by 1.25)
data.ContextPctUse = min(*cw.UsedPercentage * 1.25, 100)

Requires Go 1.21+ (which this repo targets). Eliminates the constant, the comment block, and the if/cap.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it, but maybe it's better to avoid just stating it on the comments and use a threshold const instead.
I've moved the 0.8 threshold to a common const, that way if it change - only one const to update.

}

// CostInfo contains session cost data provided by Claude Code.
type CostInfo struct {
Copy link
Owner

Choose a reason for hiding this comment

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

The official docs also provide cost.total_lines_added and cost.total_lines_removed. Not blocking, but consider adding them for completeness:

type CostInfo struct {
	TotalCostUSD       float64 `json:"total_cost_usd"`
	TotalDurationMS    int64   `json:"total_duration_ms"`
	TotalAPIDurationMS int64   `json:"total_api_duration_ms"`
	TotalLinesAdded    int     `json:"total_lines_added"`
	TotalLinesRemoved  int     `json:"total_lines_removed"`
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I saw them and thought they are redundant because the code already supports git added/removed , but I guess some users might want Claude data instead.
Added.

},

// fmtDuration formats milliseconds to human-readable: 125000 -> "2m 5s"
"fmtDuration": func(ms int64) string {
Copy link
Owner

Choose a reason for hiding this comment

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

This won't handle sessions over 60 minutes well — 125m 30s instead of 2h 5m. Long sessions are common. Suggest adding an hours branch:

"fmtDuration": func(ms int64) string {
	totalSec := ms / 1000
	hours := totalSec / 3600
	mins := (totalSec % 3600) / 60
	secs := totalSec % 60
	if hours > 0 {
		return fmt.Sprintf("%dh %dm", hours, mins)
	}
	if mins > 0 {
		return fmt.Sprintf("%dm %ds", mins, secs)
	}
	return fmt.Sprintf("%ds", secs)
},

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good point - added + tests

…ures

Centralize auto-compact threshold as tokens.AutoCompactThreshold constant,
inline populateCostMetrics into Build(), add hours support to fmtDuration,
add CostLinesAdded/CostLinesRemoved fields, and document per-call vs
session-cumulative token semantics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@saar120 saar120 requested a review from kostyay February 10, 2026 08:01
Copy link
Owner

@kostyay kostyay left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for contribution!

@kostyay kostyay enabled auto-merge (squash) February 10, 2026 11:40
@kostyay kostyay disabled auto-merge February 10, 2026 11:42
@kostyay kostyay merged commit eeeb896 into kostyay:main Feb 10, 2026
3 checks passed
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.

2 participants