Skip to content
Open
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
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,71 @@ Some widgets support "raw value" mode which displays just the value without a la

---

### ⚠️ Context Warning Alerts

Context widgets (Context Length, Context Percentage) feature visual threshold warnings to help you monitor context window usage:

**Visual Indicators:**
- **Yellow Warning** - Moderate context usage (⚠️ + yellow bold text)
- **Red Critical** - High context usage (🔴 + red bold text with background)

**Why Context Warnings?**
- Helps you stay aware of context window consumption
- Useful for managing long conversations and avoiding auto-compact
- Thresholds are personal preference - adjust based on your usage patterns

**Configuration:**

Context warnings are enabled by default but fully customizable. Edit your settings file (`~/.config/ccstatusline/settings.json`):

```json
{
"tokenWarnings": {
"enabled": true,
"warningThreshold": 120000,
"criticalThreshold": 140000,
"showEmojis": true
}
}
```

**Options:**
- `enabled` - Toggle warnings on/off (default: `true`)
- `warningThreshold` - Token count for yellow warning (default: `120000`)
- `criticalThreshold` - Token count for red alert (default: `140000`)
- `showEmojis` - Show emoji indicators (🔴/⚠️) or just colors (default: `true`)

**Setting Your Own Thresholds:**

The defaults (120k/140k) are starting points. Adjust based on your workflow:
- Short sessions: Lower thresholds (e.g., 80k/100k)
- Long conversations: Higher thresholds (e.g., 150k/170k)
- Experiment to find what works for you

**Examples:**

Disable warnings entirely:
```json
"tokenWarnings": { "enabled": false }
```

Earlier warnings for shorter sessions:
```json
"tokenWarnings": {
"warningThreshold": 80000,
"criticalThreshold": 100000
}
```

Colors only, no emojis:
```json
"tokenWarnings": {
"showEmojis": false
}
```

---

### 🔧 Custom Widgets

#### Custom Text Widget
Expand Down
15 changes: 15 additions & 0 deletions src/types/Settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ export const SettingsSchema_v1 = z.object({
globalBold: z.boolean().optional()
});

// Context warning alerts for monitoring context window usage
// Applies to Context Length and Context Percentage widgets
export const TokenWarningsSchema = z.object({
enabled: z.boolean().default(true),
warningThreshold: z.number().default(120000),
criticalThreshold: z.number().default(140000),
showEmojis: z.boolean().default(true)
});

// Main settings schema with defaults
export const SettingsSchema = z.object({
version: z.number().default(CURRENT_VERSION),
Expand Down Expand Up @@ -58,6 +67,12 @@ export const SettingsSchema = z.object({
theme: undefined,
autoAlign: false
}),
tokenWarnings: TokenWarningsSchema.default({
enabled: true,
warningThreshold: 120000,
criticalThreshold: 140000,
showEmojis: true
}),
updatemessage: z.object({
message: z.string().nullable().optional(),
remaining: z.number().nullable().optional()
Expand Down
41 changes: 41 additions & 0 deletions src/utils/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,47 @@ export function formatTokens(count: number): string {
return count.toString();
}

/**
* Apply threshold-based color warnings to token displays
* @param baseText - The text to display (e.g., "Ctx: 18.6k" or "18.6k")
* @param tokenCount - The actual token count to check against thresholds
* @param settings - Settings object containing tokenWarnings configuration
* @returns Styled text with color warnings if thresholds are exceeded, or original text
*/
export function applyTokenWarning(baseText: string, tokenCount: number, settings: Settings): string {
// Get token warnings config with defaults
const tokenWarnings = settings.tokenWarnings as {
enabled?: boolean;
warningThreshold?: number;
criticalThreshold?: number;
showEmojis?: boolean;
} | undefined;

// If warnings are disabled, return original text
if (tokenWarnings?.enabled === false) {
return baseText;
}

// Get thresholds with defaults
const warningThreshold = tokenWarnings?.warningThreshold ?? 120000;
const criticalThreshold = tokenWarnings?.criticalThreshold ?? 140000;
const showEmojis = tokenWarnings?.showEmojis ?? true;

// Check thresholds and apply styling
if (tokenCount >= criticalThreshold) {
// Critical: red background + bold
const prefix = showEmojis ? '🔴 ' : '';
return chalk.bold.red.bgRed(prefix + baseText);
} else if (tokenCount >= warningThreshold) {
// Warning: yellow + bold
const prefix = showEmojis ? '⚠️ ' : '';
return chalk.bold.yellow(prefix + baseText);
}

// Below thresholds: return original text
return baseText;
}

function renderPowerlineStatusLine(
widgets: WidgetItem[],
settings: Settings,
Expand Down
12 changes: 10 additions & 2 deletions src/widgets/ContextLength.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import type {
WidgetEditorDisplay,
WidgetItem
} from '../types/Widget';
import { formatTokens } from '../utils/renderer';
import {
applyTokenWarning,
formatTokens
} from '../utils/renderer';

export class ContextLengthWidget implements Widget {
getDefaultColor(): string { return 'brightBlack'; }
Expand All @@ -19,7 +22,12 @@ export class ContextLengthWidget implements Widget {
if (context.isPreview) {
return item.rawValue ? '18.6k' : 'Ctx: 18.6k';
} else if (context.tokenMetrics) {
return item.rawValue ? formatTokens(context.tokenMetrics.contextLength) : `Ctx: ${formatTokens(context.tokenMetrics.contextLength)}`;
const contextLength = context.tokenMetrics.contextLength;
const formattedLength = formatTokens(contextLength);
const baseText = item.rawValue ? formattedLength : `Ctx: ${formattedLength}`;

// Apply threshold-based warnings if configured
return applyTokenWarning(baseText, contextLength, settings);
}
return null;
}
Expand Down
6 changes: 5 additions & 1 deletion src/widgets/ContextPercentage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
WidgetItem
} from '../types/Widget';
import { getContextConfig } from '../utils/model-context';
import { applyTokenWarning } from '../utils/renderer';

export class ContextPercentageWidget implements Widget {
getDefaultColor(): string { return 'blue'; }
Expand Down Expand Up @@ -51,7 +52,10 @@ export class ContextPercentageWidget implements Widget {
const contextConfig = getContextConfig(modelId);
const usedPercentage = Math.min(100, (context.tokenMetrics.contextLength / contextConfig.maxTokens) * 100);
const displayPercentage = isInverse ? (100 - usedPercentage) : usedPercentage;
return item.rawValue ? `${displayPercentage.toFixed(1)}%` : `Ctx: ${displayPercentage.toFixed(1)}%`;
const baseText = item.rawValue ? `${displayPercentage.toFixed(1)}%` : `Ctx: ${displayPercentage.toFixed(1)}%`;

// Apply threshold-based warnings if configured
return applyTokenWarning(baseText, context.tokenMetrics.contextLength, settings);
}
return null;
}
Expand Down