use std::ffi::OsStr;
use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
use serde_json::Value;
use crate::monitor::{self, DaemonView, Health};
use crate::tracking::Tracker;
use crate::ui;
const CTX_WINDOW_DEFAULT: i64 = 200_000;
const CTX_BAR_WIDTH: usize = 8;
const CTX_GREEN_PCT: i64 = 40;
const CTX_AMBER_PCT: i64 = 65;
pub(crate) const CACHE_TTL_SECS: i64 = 3600;
const REFRESH_INTERVAL_SECS: i64 = 300;
const BRAND: &str = "38;2;153;204;255"; const CYAN: &str = "36"; const VIOLET: &str = "38;2;181;137;255"; const YELLOW: &str = "33"; const GREEN: &str = "32";
const AMBER: &str = "33";
const ORANGE: &str = "38;2;255;140;0"; const RED: &str = "31";
const DIM: &str = "2";
const BOLD: &str = "1";
fn paint(color: bool, code: &str, s: &str) -> String {
if color {
format!("\x1b[{code}m{s}\x1b[0m")
} else {
s.to_string()
}
}
struct CcInput {
model: String,
#[allow(dead_code)]
effort: Option<String>,
session_id: Option<String>,
ctx_tokens: i64,
model_id: String,
window: Option<i64>,
five_hour_pct: Option<f64>,
seven_day_pct: Option<f64>,
five_hour_resets_at: Option<i64>,
seven_day_resets_at: Option<i64>,
cache_pct: Option<f64>,
}
fn parse_cc(input: &str) -> CcInput {
let v: Value = serde_json::from_str(input).unwrap_or(Value::Null);
let model = v
.pointer("/model/display_name")
.and_then(Value::as_str)
.unwrap_or("?")
.to_string();
let model_id = v
.pointer("/model/id")
.and_then(Value::as_str)
.unwrap_or("")
.to_string();
let effort = v
.pointer("/effort/level")
.and_then(Value::as_str)
.map(str::to_string);
let session_id = v
.pointer("/session_id")
.and_then(Value::as_str)
.filter(|s| !s.is_empty())
.map(str::to_string);
let ctx_tokens = v
.pointer("/context_window/total_input_tokens")
.and_then(Value::as_i64)
.unwrap_or(0);
let window = v
.pointer("/context_window/context_window_size")
.and_then(Value::as_i64)
.filter(|&w| w > 0);
let five_hour_pct = v
.pointer("/rate_limits/five_hour/used_percentage")
.and_then(Value::as_f64);
let seven_day_pct = v
.pointer("/rate_limits/seven_day/used_percentage")
.and_then(Value::as_f64);
let five_hour_resets_at = v
.pointer("/rate_limits/five_hour/resets_at")
.and_then(Value::as_i64);
let seven_day_resets_at = v
.pointer("/rate_limits/seven_day/resets_at")
.and_then(Value::as_i64);
let cache_pct = {
let cu = v.pointer("/context_window/current_usage");
let field = |k: &str| {
cu.and_then(|c| c.get(k))
.and_then(Value::as_i64)
.unwrap_or(0)
};
let read = field("cache_read_input_tokens");
let total = read + field("input_tokens") + field("cache_creation_input_tokens");
(total > 0).then(|| read as f64 / total as f64 * 100.0)
};
CcInput {
model,
effort,
session_id,
model_id,
ctx_tokens,
window,
five_hour_pct,
seven_day_pct,
five_hour_resets_at,
seven_day_resets_at,
cache_pct,
}
}
struct Led {
health: Health,
trim_pct: Option<f64>,
reroute: Option<String>,
reroute_window: Option<i64>,
resolved_model: Option<String>,
cache_cold: bool,
last_cache_pct: Option<f64>,
last_ctx_tokens: i64,
sub_five: Option<QuotaSlot>,
sub_seven: Option<QuotaSlot>,
}
type QuotaSlot = (String, f64);
fn proxy_health() -> Health {
use crate::daemon;
let ca_present = matches!(crate::serve::ca_cert_path(), Ok(p) if p.exists());
let env_port = crate::setup::configured_port();
let view = |running: bool, pid: u32, port: u16, accepting: bool| DaemonView {
running,
pid,
port,
uptime: String::new(),
uptime_secs: 0,
ca_present,
port_accepting: accepting,
env_port,
autostart: false,
restarts: 0,
version: None,
binary_version: String::new(),
log_path: None,
last_request: None,
};
let dv = match daemon::running() {
Some(s) => view(true, s.pid, s.port, daemon::probe_port(s.port)),
None => match env_port.filter(|&p| daemon::probe_port(p)) {
Some(p) => view(true, 0, p, true),
None => view(false, 0, 0, false),
},
};
monitor::health(&dv)
}
fn ledger_snapshot(cc: &CcInput) -> Led {
let cfg = llmtrim_core::config::RuntimeConfig::get();
let global = cfg.sub.clone().filter(|s| !s.is_empty() && s != "off");
let window_intent = crate::window_sub::lookup(cc.session_id.as_deref());
let configured = match &window_intent {
Some(crate::window_sub::Intent::Enabled { provider }) => Some(provider.clone()),
Some(crate::window_sub::Intent::Disabled) => None,
None => global,
};
let health = proxy_health();
let row = cc.session_id.as_deref().and_then(session_row);
let lifetime = || {
Tracker::open()
.and_then(|t| t.summary())
.ok()
.filter(|s| s.input_before > 0)
.map(|s| ui::saved_pct(s.input_before as f64, s.input_after as f64))
};
let session_savings = row.as_ref().map(|r| (r.input_before, r.input_after));
let trim_pct = trim_for(cc.session_id.as_deref(), session_savings, lifetime);
let ledger_cold = row.as_ref().is_some_and(|r| cache_cold(&r.last_ts));
let cache_cold = effective_cache_cold(cc, ledger_cold);
let arrow = if matches!(window_intent, Some(crate::window_sub::Intent::Disabled)) {
ArrowSource::None
} else {
let window_forces = matches!(
window_intent,
Some(crate::window_sub::Intent::Enabled { .. })
);
let effective_fallback = cfg.sub_fallback && !window_forces;
arrow_source(configured.as_deref(), effective_fallback, row.as_ref())
};
let (reroute, reroute_window, resolved_model) = match arrow {
ArrowSource::Served { provider, model } => {
let window = model.as_deref().and_then(upstream_window);
let shown = model.filter(|_| provider != "kimi");
(Some(provider), window, shown)
}
ArrowSource::Predicted(provider) => {
let tiers = llmtrim_core::config::sub_tiers_for(&provider);
(
Some(provider.clone()),
reroute_real_window(&provider, &cc.model_id, &tiers),
reroute_resolved_model(&provider, &cc.model_id, &tiers),
)
}
ArrowSource::None => (None, None, None),
};
let (sub_five, sub_seven) = sub_quota_for(reroute.as_deref());
Led {
health,
trim_pct,
reroute,
reroute_window,
resolved_model,
cache_cold,
last_cache_pct: row
.as_ref()
.and_then(|r| r.last_cache_hit)
.map(|f| f * 100.0),
last_ctx_tokens: row.as_ref().map_or(0, |r| r.last_input_tokens),
sub_five,
sub_seven,
}
}
#[cfg(feature = "intercept")]
fn sub_quota_for(reroute: Option<&str>) -> (Option<QuotaSlot>, Option<QuotaSlot>) {
let Some(provider) = reroute else {
return (None, None);
};
let Some(snap) = crate::reroute::quota::load_fresh() else {
return (None, None);
};
if snap.provider != provider {
return (None, None);
}
let (short, weekly) = crate::reroute::quota::split_short_weekly(&snap);
let label = |w: &crate::reroute::quota::RateWindow, fallback: &str| {
remaining_time_label(w.resets_at).unwrap_or_else(|| {
let s = crate::reroute::quota::size_label(w.limit_window_seconds);
if s == "?" { fallback.to_string() } else { s }
})
};
(
short.map(|w| (label(w, "5h"), w.used_percent)),
weekly.map(|w| (label(w, "7d"), w.used_percent)),
)
}
#[cfg(not(feature = "intercept"))]
fn sub_quota_for(_reroute: Option<&str>) -> (Option<QuotaSlot>, Option<QuotaSlot>) {
(None, None)
}
fn ctx_tokens_for(blob: i64, ledger_last: i64) -> i64 {
if blob > 0 { blob } else { ledger_last }
}
fn cache_pct_for(blob: Option<f64>, ledger_last: Option<f64>) -> Option<f64> {
blob.or(ledger_last)
}
enum ArrowSource {
Served {
provider: String,
model: Option<String>,
},
Predicted(String),
None,
}
fn arrow_source(
configured: Option<&str>,
fallback_mode: bool,
row: Option<&SessionLedgerRow>,
) -> ArrowSource {
let predict = |p: &str| ArrowSource::Predicted(p.to_string());
match row {
Some(r) => match &r.last_sub_provider {
Some(provider) => {
if let Some(p) = configured
&& !fallback_mode
&& p != provider.as_str()
{
return predict(p);
}
ArrowSource::Served {
provider: provider.clone(),
model: r.last_model.clone(),
}
}
None => match configured {
Some(p) if !fallback_mode => predict(p),
_ => ArrowSource::None,
},
},
None => match configured {
Some(p) if !fallback_mode => predict(p),
_ => ArrowSource::None,
},
}
}
struct SessionLedgerRow {
input_before: i64,
input_after: i64,
last_ts: String,
last_sub_provider: Option<String>,
last_model: Option<String>,
last_cache_hit: Option<f64>,
last_input_tokens: i64,
}
#[cfg(feature = "breakdown")]
fn session_row(sid: &str) -> Option<SessionLedgerRow> {
crate::breakdown::db::BreakdownDb::open()
.ok()
.and_then(|db| db.sessions().ok())
.and_then(|rows| {
rows.into_iter()
.find(|r| r.cc_session_id.as_deref() == Some(sid))
})
.map(|r| SessionLedgerRow {
input_before: r.input_before,
input_after: r.input_after,
last_ts: r.last_ts,
last_sub_provider: r.last_sub_provider,
last_model: r.last_model,
last_cache_hit: r.last_cache_hit,
last_input_tokens: r.last_input_tokens,
})
}
#[cfg(not(feature = "breakdown"))]
fn session_row(_sid: &str) -> Option<SessionLedgerRow> {
None
}
pub(crate) fn session_sub_model(session_id: &str) -> Option<String> {
let row = session_row(session_id)?;
row.last_sub_provider.as_ref()?;
row.last_model
}
#[cfg(feature = "intercept")]
pub(crate) fn session_cache_warm(session_id: &str) -> bool {
session_row(session_id).is_some_and(|r| ts_within_ttl(&r.last_ts))
}
#[cfg(feature = "intercept")]
fn ts_within_ttl(last_ts: &str) -> bool {
chrono::DateTime::parse_from_rfc3339(last_ts)
.map(|t| chrono::Utc::now().signed_duration_since(t).num_seconds() < CACHE_TTL_SECS)
.unwrap_or(false)
}
fn trim_for(
session_id: Option<&str>,
session_savings: Option<(i64, i64)>,
lifetime: impl FnOnce() -> Option<f64>,
) -> Option<f64> {
match (session_savings, session_id) {
(Some((before, after)), _) => {
(before > 0).then(|| ui::saved_pct(before as f64, after as f64))
}
(None, Some(_)) => None,
(None, None) => lifetime(),
}
}
#[cfg(feature = "intercept")]
fn reroute_real_window(
provider: &str,
incoming_model_id: &str,
tiers: &std::collections::BTreeMap<String, String>,
) -> Option<i64> {
use crate::reroute::SubProvider;
let sp = match provider {
"codex" => SubProvider::Codex,
"kimi" => SubProvider::Kimi,
"grok" => SubProvider::Grok,
_ => return None,
};
upstream_window(&crate::reroute::resolve_model(sp, incoming_model_id, tiers))
}
#[cfg(feature = "intercept")]
fn upstream_window(model: &str) -> Option<i64> {
let lookup = if model == crate::reroute::KIMI_MODEL {
"moonshotai/kimi-k2"
} else {
model
};
llmtrim_core::context_window(lookup).map(|w| w as i64)
}
#[cfg(not(feature = "intercept"))]
fn upstream_window(_model: &str) -> Option<i64> {
None
}
#[cfg(not(feature = "intercept"))]
fn reroute_real_window(
_provider: &str,
_incoming_model_id: &str,
_tiers: &std::collections::BTreeMap<String, String>,
) -> Option<i64> {
None
}
#[cfg(feature = "intercept")]
fn reroute_resolved_model(
provider: &str,
incoming_model_id: &str,
tiers: &std::collections::BTreeMap<String, String>,
) -> Option<String> {
use crate::reroute::SubProvider;
let sp = match provider {
"codex" => SubProvider::Codex,
"grok" => SubProvider::Grok,
_ => return None,
};
Some(crate::reroute::resolve_model(sp, incoming_model_id, tiers))
}
#[cfg(not(feature = "intercept"))]
fn reroute_resolved_model(
_provider: &str,
_incoming_model_id: &str,
_tiers: &std::collections::BTreeMap<String, String>,
) -> Option<String> {
None
}
fn cache_cold(last_ts: &str) -> bool {
chrono::DateTime::parse_from_rfc3339(last_ts)
.map(|t| chrono::Utc::now().signed_duration_since(t).num_seconds() >= CACHE_TTL_SECS)
.unwrap_or(false)
}
fn effective_cache_cold(cc: &CcInput, ledger_cold: bool) -> bool {
if !ledger_cold {
return false;
}
cc.ctx_tokens != 0 || cc.cache_pct.is_some()
}
fn quota_color(pct: f64) -> &'static str {
if pct >= 90.0 {
RED
} else if pct >= 80.0 {
ORANGE
} else if pct >= 70.0 {
AMBER
} else {
GREEN
}
}
fn remaining_time_label(resets_at: Option<i64>) -> Option<String> {
let minutes = (resets_at? - chrono::Utc::now().timestamp()).max(0) / 60;
Some(if minutes >= 24 * 60 {
format!("{}d", minutes / (24 * 60))
} else if minutes >= 60 {
format!("{}h", minutes / 60)
} else {
format!("{minutes}m")
})
}
fn model_segment(cc: &CcInput, led: &Led, color: bool) -> String {
let mut s = format!(
"{} {}",
paint(color, BRAND, "◆"),
paint(color, BOLD, &cc.model)
);
if let (Health::Healthy, Some(p)) = (led.health, &led.reroute) {
let code = match p.as_str() {
"kimi" => VIOLET,
"grok" => YELLOW,
_ => CYAN,
};
let tail = led.resolved_model.clone().unwrap_or_else(|| p.clone());
s.push_str(&paint(color, code, &format!("→{tail}")));
}
s
}
fn effective_window(cc: &CcInput, led: &Led) -> i64 {
led.reroute_window
.or(cc.window)
.filter(|&w| w > 0)
.unwrap_or(CTX_WINDOW_DEFAULT)
}
fn context_segment(ctx_tokens: i64, window: i64, cache_cold: bool, color: bool) -> String {
let tokens = ctx_tokens.max(0);
let window = window.max(1);
let filled = (tokens.min(window) * CTX_BAR_WIDTH as i64 / window) as usize;
let bar: String = "▓".repeat(filled) + &"░".repeat(CTX_BAR_WIDTH - filled);
let k = (tokens as f64 / 1000.0).round() as i64;
let pct = (tokens as f64 / window as f64 * 100.0) as i64;
let code = if cache_cold {
RED
} else if tokens == 0 {
DIM
} else if pct >= CTX_AMBER_PCT {
RED
} else if pct >= CTX_GREEN_PCT {
ORANGE
} else {
GREEN
};
paint(color, code, &format!("{bar} {k}k"))
}
fn trim_or_health_segment(led: &Led, color: bool) -> Option<String> {
match led.health {
Health::Healthy => Some(match led.trim_pct {
Some(pct) => paint(color, DIM, &format!("✂ {pct:.1}%")),
None => paint(color, DIM, "✂ –"),
}),
Health::Degraded => Some(paint(color, RED, "⚠ llmtrim degraded")),
Health::Stopped => None,
}
}
fn quota_windows(cc: &CcInput, led: &Led) -> (Option<QuotaSlot>, Option<QuotaSlot>) {
if led.health == Health::Healthy
&& led.reroute.is_some()
&& (led.sub_five.is_some() || led.sub_seven.is_some())
{
return (led.sub_five.clone(), led.sub_seven.clone());
}
let five = cc.five_hour_pct.map(|p| {
(
remaining_time_label(cc.five_hour_resets_at).unwrap_or_else(|| "5h".to_string()),
p,
)
});
let seven = cc.seven_day_pct.map(|p| {
(
remaining_time_label(cc.seven_day_resets_at).unwrap_or_else(|| "7d".to_string()),
p,
)
});
(five, seven)
}
fn extra_segments(cc: &CcInput, led: &Led, color: bool) -> Vec<String> {
let mut out = Vec::new();
let quota = |label: &str, p: f64| {
format!(
"{}{}",
paint(color, DIM, &format!("{label}·")),
paint(color, quota_color(p), &format!("{}%", p.floor() as i64))
)
};
let glyph = paint(color, DIM, "◔");
let sep = paint(color, DIM, "·");
match quota_windows(cc, led) {
(Some((five_label, h)), Some((seven_label, d))) => {
out.push(format!(
"{glyph} {} {sep} {}",
quota(&five_label, h),
quota(&seven_label, d)
));
}
(Some((five_label, h)), None) => out.push(format!("{glyph} {}", quota(&five_label, h))),
(None, Some((seven_label, d))) => out.push(format!("{glyph} {}", quota(&seven_label, d))),
(None, None) => {}
}
if led.cache_cold {
out.push(paint(color, RED, "♻ cache cold"));
} else if let Some(c) = cache_pct_for(cc.cache_pct, led.last_cache_pct) {
out.push(paint(
color,
DIM,
&format!("♻ {}% cached", c.floor() as i64),
));
}
out
}
const SEP: &str = " ";
fn render_line(cc: &CcInput, led: &Led, cols: usize, color: bool) -> String {
let mut core = vec![
model_segment(cc, led, color),
context_segment(
ctx_tokens_for(cc.ctx_tokens, led.last_ctx_tokens),
effective_window(cc, led),
led.cache_cold,
color,
),
];
if let Some(seg) = trim_or_health_segment(led, color) {
core.push(seg);
}
let mut line = core.join(SEP);
for extra in extra_segments(cc, led, color) {
let candidate = format!("{line}{SEP}{extra}");
if cols == 0 || ui::visible_width(&candidate) <= cols {
line = candidate;
} else {
break;
}
}
line
}
pub fn run() -> Result<()> {
use std::io::Read;
let mut input = String::new();
std::io::stdin().read_to_string(&mut input).ok();
let cc = parse_cc(&input);
let led = ledger_snapshot(&cc);
let cols = std::env::var("COLUMNS")
.ok()
.and_then(|s| s.parse::<usize>().ok())
.unwrap_or(0);
let color = std::env::var_os("NO_COLOR").is_none();
println!("{}", render_line(&cc, &led, cols, color));
Ok(())
}
pub fn claude_code_present() -> bool {
claude_settings_path()
.ok()
.and_then(|p| p.parent().map(std::path::Path::is_dir))
.unwrap_or(false)
}
pub(crate) fn claude_settings_path() -> Result<PathBuf> {
if let Some(dir) = std::env::var_os("CLAUDE_CONFIG_DIR") {
return Ok(PathBuf::from(dir).join("settings.json"));
}
let home = std::env::var("HOME")
.or_else(|_| std::env::var("USERPROFILE"))
.context("neither HOME nor USERPROFILE is set")?;
Ok(PathBuf::from(home).join(".claude").join("settings.json"))
}
pub(crate) fn shell_quote_path(path: &str) -> String {
#[cfg(windows)]
{
format!("\"{}\"", path.replace('"', "\\\""))
}
#[cfg(not(windows))]
{
format!("'{}'", path.replace('\'', "'\"'\"'"))
}
}
pub fn stable_exe_string() -> String {
std::env::current_exe()
.ok()
.filter(|p| p.exists())
.map(|p| stable_executable_path(&p, std::env::var_os("PATH").as_deref()))
.map(|p| p.display().to_string())
.unwrap_or_else(|| "llmtrim".to_string())
}
pub(crate) fn atomic_write_json(path: &Path, value: &Value) -> Result<()> {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)
.with_context(|| format!("failed to create {}", parent.display()))?;
}
let tmp = path.with_extension("json.tmp");
std::fs::write(&tmp, serde_json::to_string_pretty(value)?)
.with_context(|| format!("failed to write {}", tmp.display()))?;
std::fs::rename(&tmp, path)
.with_context(|| format!("failed to rename onto {}", path.display()))?;
Ok(())
}
fn stable_executable_path(current_exe: &Path, path: Option<&OsStr>) -> PathBuf {
let Some(current_real) = std::fs::canonicalize(current_exe).ok() else {
return current_exe.to_path_buf();
};
let Some(name) = current_exe.file_name() else {
return current_exe.to_path_buf();
};
let Some(path) = path else {
return current_exe.to_path_buf();
};
for dir in std::env::split_paths(path) {
if !dir.is_absolute() {
continue;
}
let candidate = dir.join(name);
if candidate == current_exe {
continue;
}
if std::fs::canonicalize(&candidate).ok().as_ref() == Some(¤t_real) {
return candidate;
}
}
current_exe.to_path_buf()
}
pub(crate) fn exe_command(subcommand: &str) -> String {
format!("{} {subcommand}", shell_quote_path(&stable_exe_string()))
}
fn statusline_config() -> Value {
serde_json::json!({
"type": "command",
"command": exe_command("statusline"),
"padding": 0,
"refreshInterval": REFRESH_INTERVAL_SECS,
})
}
fn is_llmtrim_statusline_command(command: &str) -> bool {
is_llmtrim_command(command, "statusline")
}
pub(crate) fn is_llmtrim_command(command: &str, subcommand: &str) -> bool {
let Some(executable) = command.strip_suffix(&format!(" {subcommand}")) else {
return false;
};
let executable = unquote_path_token(executable.trim());
let name = executable.rsplit(['/', '\\']).next().unwrap_or(executable);
name.strip_suffix(".exe").unwrap_or(name) == "llmtrim"
}
pub(crate) fn unquote_path_token(s: &str) -> &str {
let s = s.trim();
if s.len() >= 2 && s.starts_with('"') && s.ends_with('"') {
return &s[1..s.len() - 1];
}
if s.len() >= 2 && s.starts_with('\'') && s.ends_with('\'') {
return &s[1..s.len() - 1];
}
s
}
fn set_statusline(settings: &mut Value, path: &std::path::Path) -> Result<()> {
let obj = settings
.as_object_mut()
.with_context(|| format!("{} is not a JSON object", path.display()))?;
obj.insert("statusLine".to_string(), statusline_config());
Ok(())
}
fn clear_statusline(settings: &mut Value, path: &std::path::Path) -> Result<bool> {
let obj = settings
.as_object_mut()
.with_context(|| format!("{} is not a JSON object", path.display()))?;
Ok(obj.remove("statusLine").is_some())
}
pub fn install(print: bool) -> Result<()> {
if print {
let snippet = serde_json::json!({ "statusLine": statusline_config() });
println!("{}", serde_json::to_string_pretty(&snippet)?);
return Ok(());
}
let path = claude_settings_path()?;
let mut settings: Value = match std::fs::read_to_string(&path) {
Ok(s) => serde_json::from_str(&s)
.with_context(|| format!("{} is not valid JSON", path.display()))?,
Err(_) => Value::Object(Default::default()),
};
set_statusline(&mut settings, &path)?;
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)
.with_context(|| format!("failed to create {}", parent.display()))?;
}
write_settings(&path, &settings)?;
println!(
"Wired the llmtrim status line into {}. Restart Claude Code to see it.",
path.display()
);
Ok(())
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OwnedStatus {
Missing,
Stale,
Current,
Foreign,
}
pub fn owned_status() -> OwnedStatus {
let Ok(path) = claude_settings_path() else {
return OwnedStatus::Missing;
};
let Ok(s) = std::fs::read_to_string(&path) else {
return OwnedStatus::Missing;
};
let Ok(settings) = serde_json::from_str::<Value>(&s) else {
return OwnedStatus::Missing;
};
owned_status_of(&settings)
}
fn owned_status_of(settings: &Value) -> OwnedStatus {
let Some(status_line) = settings.get("statusLine").and_then(Value::as_object) else {
return OwnedStatus::Missing;
};
let Some(command) = status_line.get("command").and_then(Value::as_str) else {
return OwnedStatus::Foreign;
};
if !is_llmtrim_statusline_command(command) {
return OwnedStatus::Foreign;
}
let desired = statusline_config();
let desired_cmd = desired.get("command").and_then(Value::as_str).unwrap_or("");
let desired_refresh = desired
.get("refreshInterval")
.and_then(Value::as_i64)
.unwrap_or(REFRESH_INTERVAL_SECS);
let refresh = status_line.get("refreshInterval").and_then(Value::as_i64);
if command == desired_cmd && refresh == Some(desired_refresh) {
OwnedStatus::Current
} else {
OwnedStatus::Stale
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SyncOutcome {
Installed,
Refreshed,
AlreadyCurrent,
SkippedForeign,
}
pub fn sync_owned() -> Result<SyncOutcome> {
let path = claude_settings_path()?;
let mut settings: Value = match std::fs::read_to_string(&path) {
Ok(s) => serde_json::from_str(&s)
.with_context(|| format!("{} is not valid JSON", path.display()))?,
Err(_) => Value::Object(Default::default()),
};
match owned_status_of(&settings) {
OwnedStatus::Foreign => Ok(SyncOutcome::SkippedForeign),
OwnedStatus::Current => Ok(SyncOutcome::AlreadyCurrent),
OwnedStatus::Missing => {
set_statusline(&mut settings, &path)?;
write_settings(&path, &settings)?;
Ok(SyncOutcome::Installed)
}
OwnedStatus::Stale => {
refresh_statusline_config(&mut settings)?;
write_settings(&path, &settings)?;
Ok(SyncOutcome::Refreshed)
}
}
}
fn write_settings(path: &Path, settings: &Value) -> Result<()> {
atomic_write_json(path, settings)
}
fn refresh_statusline_config(settings: &mut Value) -> Result<bool> {
let Some(status_line) = settings
.get_mut("statusLine")
.and_then(Value::as_object_mut)
else {
return Ok(false);
};
let Some(command) = status_line.get("command").and_then(Value::as_str) else {
return Ok(false);
};
if !is_llmtrim_statusline_command(command) {
return Ok(false);
}
let desired = statusline_config();
let desired_cmd = desired
.get("command")
.and_then(Value::as_str)
.map(str::to_string)
.unwrap_or_default();
let desired_refresh = desired
.get("refreshInterval")
.cloned()
.unwrap_or(Value::from(REFRESH_INTERVAL_SECS));
let mut changed = false;
if status_line.get("command").and_then(Value::as_str) != Some(desired_cmd.as_str()) {
status_line.insert("command".to_string(), Value::String(desired_cmd));
changed = true;
}
if status_line.get("refreshInterval") != Some(&desired_refresh) {
status_line.insert("refreshInterval".to_string(), desired_refresh);
changed = true;
}
Ok(changed)
}
pub fn refresh_if_installed() -> Result<bool> {
match owned_status() {
OwnedStatus::Missing | OwnedStatus::Foreign | OwnedStatus::Current => Ok(false),
OwnedStatus::Stale => {
let path = claude_settings_path()?;
let Ok(s) = std::fs::read_to_string(&path) else {
return Ok(false);
};
let mut settings: Value = serde_json::from_str(&s)
.with_context(|| format!("{} is not valid JSON", path.display()))?;
if !refresh_statusline_config(&mut settings)? {
return Ok(false);
}
write_settings(&path, &settings)?;
Ok(true)
}
}
}
pub fn uninstall() -> Result<()> {
let path = claude_settings_path()?;
let Ok(s) = std::fs::read_to_string(&path) else {
println!("No {} to edit — nothing to remove.", path.display());
return Ok(());
};
let mut settings: Value = serde_json::from_str(&s)
.with_context(|| format!("{} is not valid JSON", path.display()))?;
if clear_statusline(&mut settings, &path)? {
std::fs::write(&path, serde_json::to_string_pretty(&settings)?)
.with_context(|| format!("failed to write {}", path.display()))?;
println!("Removed the llmtrim status line from {}.", path.display());
} else {
println!("No llmtrim status line found in {}.", path.display());
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
fn led(health: Health) -> Led {
Led {
health,
trim_pct: Some(6.8),
reroute: Some("codex".to_string()),
reroute_window: None,
resolved_model: Some("gpt-5.6-terra".to_string()),
cache_cold: false,
last_cache_pct: None,
last_ctx_tokens: 0,
sub_five: Some(("5h".into(), 24.0)),
sub_seven: Some(("7d".into(), 12.0)),
}
}
fn cc(ctx: i64) -> CcInput {
CcInput {
model: "Opus".to_string(),
effort: Some("high".to_string()),
session_id: None,
model_id: "claude-opus-4-8".to_string(),
ctx_tokens: ctx,
window: Some(200_000),
five_hour_pct: Some(24.0),
seven_day_pct: Some(12.0),
five_hour_resets_at: None,
seven_day_resets_at: None,
cache_pct: Some(63.0),
}
}
#[test]
fn full_line_has_every_segment_when_wide() {
let out = render_line(&cc(142_000), &led(Health::Healthy), 0, false);
assert_eq!(
out,
"◆ Opus→gpt-5.6-terra ▓▓▓▓▓░░░ 142k ✂ 6.8% ◔ 5h·24% · 7d·12% ♻ 63% cached"
);
}
#[test]
fn context_gauge_colors_by_percent_of_real_window() {
let mut c = cc(142_000);
c.window = Some(1_000_000);
let out = context_segment(c.ctx_tokens, 1_000_000, false, true);
assert!(out.contains(GREEN), "14% of 1M is green: {out}");
let out = context_segment(142_000, 200_000, false, true);
assert!(out.contains(RED), "71% of 200k is red: {out}");
let out = context_segment(100_000, 200_000, false, true);
assert!(out.contains(ORANGE), "50% is orange: {out}");
}
#[test]
fn context_gauge_pins_full_over_window() {
let out = render_line(&cc(210_000), &led(Health::Healthy), 0, false);
assert!(
out.contains("▓▓▓▓▓▓▓▓ 210k"),
"over window pins full: {out}"
);
}
#[test]
fn cold_cache_forces_red_gauge_regardless_of_fill() {
let mut l = led(Health::Healthy);
l.cache_cold = true;
let out = context_segment(1_000, 1_000_000, true, true);
assert!(out.contains(RED), "cold cache reddens even at 0.1%: {out}");
}
#[test]
fn reroute_arrow_hidden_when_not_healthy() {
let out = render_line(&cc(142_000), &led(Health::Degraded), 0, false);
assert!(!out.contains("→codex"), "no arrow when degraded: {out}");
assert!(
out.contains("⚠ llmtrim degraded"),
"warns instead of ✂: {out}"
);
}
#[test]
fn stopped_omits_trim_and_arrow_without_warning() {
let mut l = led(Health::Stopped);
l.reroute = None;
l.resolved_model = None;
let out = render_line(&cc(48_000), &l, 0, false);
assert!(!out.contains('✂'), "no trim when off: {out}");
assert!(!out.contains('⚠'), "clean off is not an error: {out}");
assert!(out.starts_with("◆ Opus"), "model still shown: {out}");
}
#[test]
fn narrow_terminal_sheds_extras_right_to_left() {
let full = render_line(&cc(142_000), &led(Health::Healthy), 0, false);
let width =
ui::visible_width("◆ Opus→gpt-5.6-terra ▓▓▓▓▓░░░ 142k ✂ 6.8% ◔ 5h·24% · 7d·12%");
let out = render_line(&cc(142_000), &led(Health::Healthy), width, false);
assert!(out.ends_with("7d·12%"), "keeps quota, sheds cache: {out}");
assert!(!out.contains("cached"), "cache dropped first: {out}");
assert!(full.len() > out.len());
}
#[test]
fn absent_data_segments_do_not_render() {
let mut c = cc(48_000);
c.effort = None; c.five_hour_pct = None; c.seven_day_pct = None;
c.cache_pct = None; let mut l = led(Health::Healthy);
l.reroute = None; l.resolved_model = None;
let out = render_line(&c, &l, 0, false);
assert_eq!(out, "◆ Opus ▓░░░░░░░ 48k ✂ 6.8%");
}
#[test]
fn cold_cache_shows_compact_hint_not_stale_pct() {
let mut l = led(Health::Healthy);
l.cache_cold = true;
let out = render_line(&cc(48_000), &l, 0, false);
assert!(out.contains("♻ cache cold"), "cold hint shown: {out}");
assert!(!out.contains("cached"), "no stale % when cold: {out}");
}
#[test]
fn post_compact_reset_clears_cold_even_when_ledger_stale() {
let mut c = cc(0);
c.cache_pct = None;
assert!(
!effective_cache_cold(&c, true),
"empty context after compact is not cold"
);
let mut l = led(Health::Healthy);
l.cache_cold = effective_cache_cold(&c, true);
let out = render_line(&c, &l, 0, false);
assert!(!out.contains("cold"), "no cold nudge after compact: {out}");
let gauge = context_segment(c.ctx_tokens, 200_000, l.cache_cold, true);
assert!(
gauge.contains(DIM),
"gauge dim (not red) on fresh post-compact context: {gauge}"
);
assert!(
!gauge.contains(RED),
"gauge not red on fresh post-compact context: {gauge}"
);
}
#[test]
fn idle_cold_stays_when_context_still_populated() {
let mut c = cc(142_000);
c.cache_pct = Some(5.0);
assert!(
effective_cache_cold(&c, true),
"populated context with stale ledger still shows cold"
);
}
#[test]
fn quota_labels_show_time_remaining_until_reset() {
let mut c = cc(48_000);
c.five_hour_resets_at = Some(
(chrono::Utc::now() + chrono::Duration::hours(3) + chrono::Duration::minutes(30))
.timestamp(),
);
c.seven_day_resets_at = Some(
(chrono::Utc::now() + chrono::Duration::days(4) + chrono::Duration::hours(12))
.timestamp(),
);
let mut l = led(Health::Healthy);
l.reroute = None;
l.resolved_model = None;
l.sub_five = None;
l.sub_seven = None;
let out = render_line(&c, &l, 0, false);
assert!(out.contains("◔ 3h·24% · 4d·12%"), "remaining labels: {out}");
}
#[test]
fn quota_color_escalates_green_amber_orange_red() {
assert_eq!(quota_color(50.0), GREEN);
assert_eq!(quota_color(75.0), AMBER);
assert_eq!(quota_color(85.0), ORANGE); assert_eq!(quota_color(95.0), RED);
}
#[test]
fn quota_windows_colour_independently() {
let mut l = led(Health::Healthy);
l.sub_five = Some(("5h".into(), 95.0));
l.sub_seven = Some(("7d".into(), 12.0));
let segs = extra_segments(&cc(48_000), &l, true);
let quota = segs
.iter()
.find(|s| s.contains("5h"))
.expect("quota segment");
assert!(
quota.contains(&format!("\x1b[{DIM}m5h·")),
"5h label dim: {quota}"
);
assert!(
quota.contains(&format!("\x1b[{RED}m95%")),
"5h pct red: {quota}"
);
assert!(
quota.contains(&format!("\x1b[{DIM}m7d·")),
"7d label dim: {quota}"
);
assert!(
quota.contains(&format!("\x1b[{GREEN}m12%")),
"7d pct green: {quota}"
);
}
#[test]
fn trim_is_not_coloured_by_tier() {
let seg = trim_or_health_segment(&led(Health::Healthy), true).unwrap();
assert!(
seg.contains(&format!("\x1b[{DIM}m✂ 6.8%")),
"trim dim: {seg}"
);
assert!(
!seg.contains(&format!("\x1b[{GREEN}m✂")),
"not green: {seg}"
);
}
#[test]
fn quota_shows_worse_window_and_folds_to_one_segment() {
let out = render_line(&cc(48_000), &led(Health::Healthy), 0, false);
assert!(out.contains("◔ 5h·24% · 7d·12%"), "both windows: {out}");
let mut l = led(Health::Healthy);
l.sub_seven = None;
let out = render_line(&cc(48_000), &l, 0, false);
assert!(
out.contains("◔ 5h·24%") && !out.contains("7d"),
"5h only: {out}"
);
}
#[test]
fn sub_weekly_only_omits_invented_five_hour() {
let mut l = led(Health::Healthy);
l.sub_five = None;
l.sub_seven = Some(("7d".into(), 1.0));
let out = render_line(&cc(48_000), &l, 0, false);
assert!(out.contains("◔ 7d·1%"), "weekly shown: {out}");
assert!(!out.contains("5h"), "no invented 5h: {out}");
}
#[test]
fn sub_without_snapshot_falls_back_to_claude_blob() {
let mut l = led(Health::Healthy);
l.sub_five = None;
l.sub_seven = None;
let out = render_line(&cc(48_000), &l, 0, false);
assert!(
out.contains("◔ 5h·24% · 7d·12%"),
"claude blob until sub cache arrives: {out}"
);
}
#[test]
fn degraded_proxy_falls_back_to_claude_blob_even_with_sub_cache() {
let mut l = led(Health::Degraded);
l.sub_five = Some(("5h".into(), 95.0));
l.sub_seven = Some(("7d".into(), 1.0));
let out = render_line(&cc(48_000), &l, 0, false);
assert!(
out.contains("◔ 5h·24% · 7d·12%"),
"claude blob when degraded: {out}"
);
assert!(!out.contains("95%"), "stale sub 5h not shown: {out}");
}
#[test]
fn off_sub_still_uses_claude_blob_quota() {
let mut l = led(Health::Healthy);
l.reroute = None;
l.resolved_model = None;
l.sub_five = None;
l.sub_seven = None;
let out = render_line(&cc(48_000), &l, 0, false);
assert!(
out.contains("◔ 5h·24% · 7d·12%"),
"claude blob when not rerouted: {out}"
);
}
#[test]
fn kimi_reroute_when_healthy() {
let tiers = std::collections::BTreeMap::new();
let mut l = led(Health::Healthy);
l.reroute = Some("kimi".to_string());
l.resolved_model = reroute_resolved_model("kimi", "claude-opus-4-6", &tiers);
assert!(
l.resolved_model.is_none(),
"kimi collapses to one wire id; the arrow shows the shortname"
);
let out = render_line(&cc(72_000), &l, 0, true);
assert!(out.contains("→kimi"), "kimi arrow present: {out}");
assert!(
!out.contains("kimi-for-coding"),
"no internal wire id on the line: {out}"
);
}
#[test]
fn grok_reroute_shows_resolved_model_when_healthy() {
let tiers = std::collections::BTreeMap::new();
let mut l = led(Health::Healthy);
l.reroute = Some("grok".to_string());
l.resolved_model = reroute_resolved_model("grok", "claude-opus-4-8", &tiers);
assert_eq!(l.resolved_model.as_deref(), Some("grok-4.5"));
let out = render_line(&cc(72_000), &l, 0, true);
assert!(out.contains("→grok-4.5"), "grok arrow shows model: {out}");
}
fn ledger_row(sub: Option<&str>, model: Option<&str>) -> SessionLedgerRow {
SessionLedgerRow {
input_before: 1000,
input_after: 940,
last_ts: chrono::Utc::now().to_rfc3339(),
last_sub_provider: sub.map(str::to_string),
last_model: model.map(str::to_string),
last_cache_hit: None,
last_input_tokens: 0,
}
}
#[test]
fn fallback_mode_shows_no_arrow_until_a_backend_actually_serves() {
let row = ledger_row(None, Some("claude-opus-4-8"));
assert!(matches!(
arrow_source(Some("codex"), true, Some(&row)),
ArrowSource::None
));
}
#[test]
fn always_mode_predicts_after_anthropic_turns() {
let row = ledger_row(None, Some("claude-opus-4-8"));
let ArrowSource::Predicted(p) = arrow_source(Some("grok"), false, Some(&row)) else {
panic!("always mode must predict after Anthropic-only history");
};
assert_eq!(p, "grok");
}
#[test]
fn always_mode_predicts_switched_provider_over_stale_served() {
let row = ledger_row(Some("codex"), Some("gpt-5.6-terra"));
let ArrowSource::Predicted(p) = arrow_source(Some("grok"), false, Some(&row)) else {
panic!("switched provider must override stale Served");
};
assert_eq!(p, "grok");
}
#[test]
fn fallback_mode_keeps_stale_served_until_ledger_moves() {
let row = ledger_row(Some("codex"), Some("gpt-5.6-terra"));
let ArrowSource::Served { provider, .. } = arrow_source(Some("grok"), true, Some(&row))
else {
panic!("fallback keeps Served");
};
assert_eq!(provider, "codex");
}
#[test]
fn fallback_mode_shows_the_backend_once_the_chain_fires() {
let row = ledger_row(Some("codex"), Some("gpt-5.6-terra"));
let ArrowSource::Served { provider, model } = arrow_source(Some("codex"), true, Some(&row))
else {
panic!("a fired fallback must surface the backend that served it");
};
assert_eq!(provider, "codex");
assert_eq!(model.as_deref(), Some("gpt-5.6-terra"));
}
#[test]
fn fallback_mode_never_predicts_from_config_on_a_fresh_session() {
assert!(matches!(
arrow_source(Some("codex"), true, None),
ArrowSource::None
));
assert!(matches!(
arrow_source(Some("codex"), false, None),
ArrowSource::Predicted(p) if p == "codex"
));
}
#[test]
fn ledger_truth_wins_when_it_matches_policy() {
let row = ledger_row(Some("codex"), Some("gpt-5.6-terra"));
let ArrowSource::Served { provider, model } =
arrow_source(Some("codex"), false, Some(&row))
else {
panic!("matching policy keeps Served");
};
assert_eq!(provider, "codex");
assert_eq!(model.as_deref(), Some("gpt-5.6-terra"));
}
#[test]
fn trim_for_does_not_flash_lifetime_on_a_fresh_session() {
let lifetime = || Some(6.8);
assert_eq!(trim_for(Some("sess-uuid"), None, lifetime), None);
let own = trim_for(Some("sess-uuid"), Some((300, 200)), lifetime).unwrap();
assert!((own - 33.333).abs() < 0.01, "per-session figure: {own}");
assert_eq!(trim_for(None, None, lifetime), Some(6.8));
}
#[test]
fn context_gauge_holds_its_fill_while_a_turn_is_in_flight() {
let mut mid_turn = cc(48_000);
mid_turn.ctx_tokens = 0;
let mut l = led(Health::Healthy);
l.last_ctx_tokens = 48_000;
assert_eq!(
render_line(&mid_turn, &l, 0, false),
render_line(&cc(48_000), &l, 0, false),
"mid-turn gauge matches the completed-turn gauge"
);
assert_eq!(ctx_tokens_for(142_000, 48_000), 142_000);
assert_eq!(ctx_tokens_for(0, 0), 0);
}
#[test]
fn cache_segment_holds_its_value_while_a_turn_is_in_flight() {
let mut mid_turn = cc(48_000);
mid_turn.cache_pct = None;
let mut l = led(Health::Healthy);
l.last_cache_pct = Some(98.0);
let out = render_line(&mid_turn, &l, 0, false);
assert!(out.contains("♻ 98% cached"), "last turn stands in: {out}");
let out = render_line(&cc(48_000), &l, 0, false);
assert!(
out.contains("♻ 63% cached"),
"blob wins when present: {out}"
);
assert_eq!(cache_pct_for(None, None), None);
}
#[test]
fn healthy_but_idle_shows_dim_marker_not_zero() {
let mut l = led(Health::Healthy);
l.trim_pct = None;
let out = render_line(&cc(48_000), &l, 0, false);
assert!(out.contains("✂ –"), "idle marker shown: {out}");
assert!(!out.contains("0.0%"), "no fake zero: {out}");
}
#[test]
fn quota_and_cache_floor_not_round() {
let mut c = cc(48_000);
c.cache_pct = Some(99.9);
let mut l = led(Health::Healthy);
l.sub_five = Some(("5h".into(), 89.9));
let out = render_line(&c, &l, 0, false);
assert!(out.contains("5h·89%"), "quota floored: {out}");
assert!(out.contains("♻ 99% cached"), "cache floored: {out}");
}
#[test]
fn parse_cc_reads_session_id() {
let cc = parse_cc(r#"{"model":{"display_name":"Opus"},"session_id":"abc-123"}"#);
assert_eq!(cc.session_id.as_deref(), Some("abc-123"));
let cc = parse_cc(r#"{"model":{"display_name":"Opus"},"session_id":""}"#);
assert!(cc.session_id.is_none());
}
#[test]
fn parse_cc_reads_nested_fields() {
let blob = r#"{"model":{"display_name":"Sonnet","id":"claude-sonnet-5"},"effort":{"level":"medium"},
"context_window":{"total_input_tokens":123456,"context_window_size":1000000,
"current_usage":{"input_tokens":10,"cache_creation_input_tokens":10,"cache_read_input_tokens":80}},
"rate_limits":{"five_hour":{"used_percentage":41.2,"resets_at":1738425600},
"seven_day":{"used_percentage":9.0,"resets_at":1738857600}}}"#;
let cc = parse_cc(blob);
assert_eq!(cc.model, "Sonnet");
assert_eq!(cc.model_id, "claude-sonnet-5");
assert_eq!(cc.effort.as_deref(), Some("medium"));
assert_eq!(cc.ctx_tokens, 123456);
assert_eq!(cc.window, Some(1_000_000));
assert_eq!(cc.five_hour_pct, Some(41.2));
assert_eq!(cc.seven_day_pct, Some(9.0));
assert_eq!(cc.five_hour_resets_at, Some(1_738_425_600));
assert_eq!(cc.seven_day_resets_at, Some(1_738_857_600));
assert_eq!(cc.cache_pct, Some(80.0));
}
#[test]
fn install_merge_preserves_unrelated_keys() {
let p = std::path::Path::new("settings.json");
let mut settings = serde_json::json!({
"theme": "dark",
"permissions": { "allow": ["Bash"] },
});
set_statusline(&mut settings, p).unwrap();
assert_eq!(settings["statusLine"]["type"], "command");
assert_eq!(settings["theme"], "dark");
assert_eq!(settings["permissions"]["allow"][0], "Bash");
}
#[cfg(unix)]
#[test]
fn statusline_prefers_stable_path_alias_for_active_binary() {
let root = std::env::temp_dir().join(format!(
"llmtrim-statusline-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
));
let versioned_dir = root.join("Cellar/llmtrim/0.9.5/bin");
let stable_dir = root.join("bin");
std::fs::create_dir_all(&versioned_dir).unwrap();
std::fs::create_dir_all(&stable_dir).unwrap();
let name = "llmtrim";
let current = versioned_dir.join(name);
let stable = stable_dir.join(name);
std::fs::write(¤t, b"binary").unwrap();
std::os::unix::fs::symlink(¤t, &stable).unwrap();
let path = std::env::join_paths([&stable_dir]).unwrap();
assert_eq!(
stable_executable_path(¤t, Some(path.as_os_str())),
stable
);
std::fs::remove_dir_all(root).unwrap();
}
#[test]
fn recognizes_only_llmtrim_statusline_commands_for_refresh() {
assert!(is_llmtrim_statusline_command(
"/opt/homebrew/Cellar/llmtrim/0.9.4/bin/llmtrim statusline"
));
assert!(is_llmtrim_statusline_command(
r#""C:\Program Files\llmtrim\llmtrim.exe" statusline"#
));
assert!(!is_llmtrim_statusline_command("my-statusline-command"));
assert!(!is_llmtrim_statusline_command(
"llmtrim statusline --custom"
));
}
#[test]
fn refreshes_owned_statusline_without_touching_other_settings() {
let mut settings = serde_json::json!({
"theme": "dark",
"statusLine": {
"type": "command",
"command": "/opt/homebrew/Cellar/llmtrim/0.9.4/bin/llmtrim statusline",
"padding": 2
}
});
assert!(refresh_statusline_config(&mut settings).unwrap());
assert_eq!(settings["theme"], "dark");
assert_ne!(
settings["statusLine"]["command"],
"/opt/homebrew/Cellar/llmtrim/0.9.4/bin/llmtrim statusline"
);
assert_eq!(settings["statusLine"]["padding"], 2);
assert_eq!(settings["statusLine"]["type"], "command");
let mut custom = serde_json::json!({
"statusLine": { "type": "command", "command": "my-statusline-command" }
});
assert!(!refresh_statusline_config(&mut custom).unwrap());
assert_eq!(custom["statusLine"]["command"], "my-statusline-command");
}
#[test]
fn refresh_is_a_no_op_when_the_command_already_points_at_this_binary() {
let mut settings = serde_json::json!({ "statusLine": statusline_config() });
assert!(!refresh_statusline_config(&mut settings).unwrap());
}
#[test]
fn statusline_config_asks_claude_code_to_refresh_while_idle() {
assert_eq!(
statusline_config()["refreshInterval"],
serde_json::json!(300)
);
}
#[test]
fn uninstall_removes_only_our_key_and_reports_presence() {
let p = std::path::Path::new("settings.json");
let mut settings = serde_json::json!({ "theme": "dark", "statusLine": { "x": 1 } });
assert!(
clear_statusline(&mut settings, p).unwrap(),
"reports it was present"
);
assert!(settings.get("statusLine").is_none(), "our key gone");
assert_eq!(settings["theme"], "dark", "other keys kept");
assert!(!clear_statusline(&mut settings, p).unwrap());
}
#[test]
fn merge_rejects_a_non_object_settings_file() {
let p = std::path::Path::new("settings.json");
let mut settings = serde_json::json!([1, 2, 3]);
assert!(set_statusline(&mut settings, p).is_err());
assert!(clear_statusline(&mut settings, p).is_err());
}
#[test]
fn cache_pct_absent_without_current_usage() {
let cc = parse_cc(
r#"{"model":{"display_name":"Opus"},"context_window":{"total_input_tokens":100}}"#,
);
assert!(
cc.cache_pct.is_none(),
"no current_usage ⇒ no cache segment"
);
}
#[test]
fn parse_cc_tolerates_garbage_and_missing_fields() {
let cc = parse_cc("not json");
assert_eq!(cc.model, "?");
assert_eq!(cc.ctx_tokens, 0);
assert!(cc.effort.is_none());
}
#[test]
fn context_gauge_handles_extreme_token_counts() {
assert!(context_segment(-5000, 200_000, false, false).starts_with("░░░░░░░░ 0k"));
assert!(context_segment(i64::MAX / 4, 200_000, false, false).starts_with("▓▓▓▓▓▓▓▓"));
}
#[test]
fn cache_cold_parses_timestamps() {
assert!(!cache_cold("garbage"), "unparseable ⇒ not cold");
let fresh = chrono::Utc::now().to_rfc3339();
assert!(!cache_cold(&fresh), "just now ⇒ warm");
let stale =
(chrono::Utc::now() - chrono::Duration::seconds(CACHE_TTL_SECS + 60)).to_rfc3339();
assert!(cache_cold(&stale), "past the TTL ⇒ cold");
}
#[cfg(feature = "intercept")]
#[test]
fn ts_within_ttl_gates_the_compact_redirect() {
assert!(
!ts_within_ttl("garbage"),
"unparseable ⇒ not warm (redirect)"
);
assert!(
ts_within_ttl(&chrono::Utc::now().to_rfc3339()),
"just now ⇒ warm"
);
let stale =
(chrono::Utc::now() - chrono::Duration::seconds(CACHE_TTL_SECS + 60)).to_rfc3339();
assert!(!ts_within_ttl(&stale), "past the TTL ⇒ not warm (redirect)");
let fresh =
(chrono::Utc::now() - chrono::Duration::seconds(CACHE_TTL_SECS - 60)).to_rfc3339();
assert!(
ts_within_ttl(&fresh) && !cache_cold(&fresh),
"within TTL: warm, not cold"
);
assert!(
!ts_within_ttl(&stale) && cache_cold(&stale),
"past TTL: not warm, cold"
);
}
#[test]
fn effective_window_prefers_reroute_then_blob() {
let mut l = led(Health::Healthy);
l.reroute_window = Some(262_144);
assert_eq!(effective_window(&cc(0), &l), 262_144);
l.reroute_window = None;
assert_eq!(effective_window(&cc(0), &l), 200_000);
let mut c = cc(0);
c.window = None;
assert_eq!(effective_window(&c, &l), CTX_WINDOW_DEFAULT);
}
}