Skip to content

Commit d47b7bd

Browse files
authored
feat(context): make the context-window fallback configurable (#480)
Motivated by #429. The context widgets already read the real window from Claude Code's context_window.context_window_size when present, and from a [1m]-style model-name hint otherwise; only the final fallback was a hard-coded 200k. On an older Claude Code that does not report the window size for a 1M-context model, that fallback made the bar read against 200k (e.g. 750k/200k, pinned full). Demote the hard-coded 200k to the default of a configurable last-resort fallback, CCSTATUSLINE_CONTEXT_SIZE_FALLBACK (positive integer, ignored when unset or invalid), mirroring CCSTATUSLINE_WIDTH. The live status field and model-name hint still take precedence, so the override only applies when the window is otherwise unknown.
1 parent 477164e commit d47b7bd

3 files changed

Lines changed: 76 additions & 4 deletions

File tree

docs/USAGE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ bun run example
4444
- **Tokens Input** / **Tokens Output** / **Tokens Cached** / **Tokens Total** - Show current-session token counts. Input/output prefer cumulative transcript metrics and fall back to `context_window.total_input_tokens` / `context_window.total_output_tokens` when transcript metrics are unavailable; cached/total use transcript metrics.
4545
- **Cache Hit Rate** / **Cache Read** / **Cache Write** - Show prompt-cache efficiency. Cache Hit Rate uses cache reads divided by cache reads plus cache writes; Cache Read and Cache Write include each value's share of prompt context. They default to the latest turn from `context_window.current_usage`, can switch to cumulative session totals, and can hide when empty.
4646
- **Input Speed** / **Output Speed** / **Total Speed** - Show session-average token throughput with an optional per-widget rolling window (`0-120` seconds; `0` = full-session average).
47-
- **Context Length** / **Context Window** / **Context %** / **Context % (usable)** / **Context Bar** - Show current context length, total context window size, used/remaining percentage, usable-window percentage, or a progress bar.
47+
- **Context Length** / **Context Window** / **Context %** / **Context % (usable)** / **Context Bar** - Show current context length, total context window size, used/remaining percentage, usable-window percentage, or a progress bar. The window size is taken from Claude Code's reported `context_window.context_window_size` when present, then from a model-name hint (e.g. a `[1m]` suffix), and finally from a fixed fallback. Set `CCSTATUSLINE_CONTEXT_SIZE_FALLBACK` to a positive integer to override that last-resort fallback (defaults to `200000`) — useful when an older Claude Code does not report the window size for a 1M-context model, so the bar would otherwise read against 200k.
4848
- **Compaction Counter** - Show how many context compactions have been detected in the current session by scanning transcript compaction markers. It can render as icon plus number, text plus number, or number-only, and can hide while the count is zero. Two optional, independent per-item add-ons toggle extra detail: a trigger split (`↻ 3 (2 auto, 1 manual)`; a compaction whose trigger is missing or unrecognized is bucketed as `unknown`) and tokens reclaimed (`↻ 3 ↓887.0k`, each compaction's `preTokens - postTokens` floored at 0 and summed, shown only when greater than 0 — so very old transcripts predating the `postTokens` field display nothing).
4949
- **Session Usage** / **Weekly Usage** / **Weekly Sonnet Usage** / **Weekly Opus Usage** / **Extra Usage Utilization** / **Extra Usage Remaining** / **Extra Usage Used** / **Block Timer** / **Block Reset Timer** / **Weekly Reset Timer** - Show usage percentages, monthly pay-as-you-go overage usage, and current block/reset timing. The all-models weekly bar covers `seven_day` from the usage API; the per-model variants surface the `seven_day_sonnet` and `seven_day_opus` buckets that Claude Code's own `/usage` panel shows. Extra usage widgets accept known extra-usage state as complete when an account has no monthly limit configured, avoid repeated refetches and stale `[Timeout]` output, and format amounts with the API-reported billing currency when available. Session and weekly usage bars can show a time cursor; reset timers can show remaining time, progress, or exact reset date/time with timezone and locale controls.
5050

src/utils/__tests__/model-context.test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
afterEach,
23
describe,
34
expect,
45
it
@@ -126,6 +127,58 @@ describe('getContextConfig', () => {
126127
expect(config.usableTokens).toBe(160000);
127128
});
128129
});
130+
131+
describe('CCSTATUSLINE_CONTEXT_SIZE_FALLBACK override', () => {
132+
afterEach(() => {
133+
delete process.env.CCSTATUSLINE_CONTEXT_SIZE_FALLBACK;
134+
});
135+
136+
it('uses the env value as the fallback when no window size is otherwise known', () => {
137+
process.env.CCSTATUSLINE_CONTEXT_SIZE_FALLBACK = '1000000';
138+
const config = getContextConfig('claude-sonnet-4-5-20250929');
139+
140+
expect(config.maxTokens).toBe(1000000);
141+
expect(config.usableTokens).toBe(800000);
142+
});
143+
144+
it('uses the env value as the fallback when the model is unknown', () => {
145+
process.env.CCSTATUSLINE_CONTEXT_SIZE_FALLBACK = '500000';
146+
const config = getContextConfig(undefined);
147+
148+
expect(config.maxTokens).toBe(500000);
149+
expect(config.usableTokens).toBe(400000);
150+
});
151+
152+
it('falls back to 200k when the env value is non-numeric', () => {
153+
process.env.CCSTATUSLINE_CONTEXT_SIZE_FALLBACK = 'not-a-number';
154+
const config = getContextConfig('claude-3-5-sonnet-20241022');
155+
156+
expect(config.maxTokens).toBe(200000);
157+
expect(config.usableTokens).toBe(160000);
158+
});
159+
160+
it('falls back to 200k when the env value is zero or negative', () => {
161+
process.env.CCSTATUSLINE_CONTEXT_SIZE_FALLBACK = '0';
162+
expect(getContextConfig(undefined).maxTokens).toBe(200000);
163+
164+
process.env.CCSTATUSLINE_CONTEXT_SIZE_FALLBACK = '-5';
165+
expect(getContextConfig(undefined).maxTokens).toBe(200000);
166+
});
167+
168+
it('does not override the live context_window_size from the status JSON', () => {
169+
process.env.CCSTATUSLINE_CONTEXT_SIZE_FALLBACK = '500000';
170+
const config = getContextConfig('claude-3-5-sonnet-20241022', 1000000);
171+
172+
expect(config.maxTokens).toBe(1000000);
173+
});
174+
175+
it('does not override a [1m] model-name hint', () => {
176+
process.env.CCSTATUSLINE_CONTEXT_SIZE_FALLBACK = '500000';
177+
const config = getContextConfig('claude-sonnet-4-5-20250929[1m]');
178+
179+
expect(config.maxTokens).toBe(1000000);
180+
});
181+
});
129182
});
130183

131184
describe('getModelContextIdentifier', () => {

src/utils/model-context.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,22 @@ interface ModelIdentifier {
1010

1111
const DEFAULT_CONTEXT_WINDOW_SIZE = 200000;
1212
const USABLE_CONTEXT_RATIO = 0.8;
13+
const CONTEXT_SIZE_FALLBACK_ENV_VAR = 'CCSTATUSLINE_CONTEXT_SIZE_FALLBACK';
14+
15+
// User-configurable last-resort fallback window size. Mirrors CCSTATUSLINE_WIDTH:
16+
// a positive integer read from the environment, ignored when unset or invalid.
17+
// Defaults to 200k so behavior is unchanged unless the user opts in.
18+
function getFallbackContextWindowSize(): number {
19+
const raw = process.env[CONTEXT_SIZE_FALLBACK_ENV_VAR];
20+
if (raw) {
21+
const parsed = Number.parseInt(raw, 10);
22+
if (Number.isFinite(parsed) && parsed > 0) {
23+
return parsed;
24+
}
25+
}
26+
27+
return DEFAULT_CONTEXT_WINDOW_SIZE;
28+
}
1329

1430
function toValidWindowSize(value: number | null | undefined): number | null {
1531
if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
@@ -82,10 +98,13 @@ export function getContextConfig(modelIdentifier?: string, contextWindowSize?: n
8298
};
8399
}
84100

85-
// Default to 200k for older models
101+
// Last-resort fallback when neither the live status window size nor a
102+
// model-name hint is available. Defaults to 200k, overridable via
103+
// CCSTATUSLINE_CONTEXT_SIZE_FALLBACK.
104+
const fallbackWindowSize = getFallbackContextWindowSize();
86105
const defaultConfig = {
87-
maxTokens: DEFAULT_CONTEXT_WINDOW_SIZE,
88-
usableTokens: Math.floor(DEFAULT_CONTEXT_WINDOW_SIZE * USABLE_CONTEXT_RATIO)
106+
maxTokens: fallbackWindowSize,
107+
usableTokens: Math.floor(fallbackWindowSize * USABLE_CONTEXT_RATIO)
89108
};
90109

91110
if (!modelIdentifier) {

0 commit comments

Comments
 (0)