Skip to content

Commit df91d28

Browse files
brontoguanaclaude
andcommitted
v1.0.2: Add total CPU% and available/cached RAM display
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent fc3a4ff commit df91d28

5 files changed

Lines changed: 56 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 1.0.2 — 2026-03-18
4+
5+
- Show total CPU percentage across all cores (e.g. 400% = 4 cores maxed)
6+
- Show available RAM and disk cache size under memory section
7+
38
## 1.0.0 — 2026-03-10
49

510
- Complete rewrite from Python to Rust — single static binary (~1.2 MB)

ktop-rs/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ktop"
3-
version = "1.0.0"
3+
version = "1.0.2"
44
edition = "2021"
55
description = "Terminal system resource monitor for hybrid LLM workloads"
66
license = "MIT"

ktop-rs/src/app.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub struct AppState {
2626

2727
// CPU
2828
pub cpu_pct: f64,
29+
pub cpu_total_pct: f64,
2930
pub cpu_hist: VecDeque<f64>,
3031
pub cpu_cores: usize,
3132
pub cpu_freq: String,
@@ -34,6 +35,8 @@ pub struct AppState {
3435
pub ram_pct: f64,
3536
pub ram_used: u64,
3637
pub ram_total: u64,
38+
pub ram_available: u64,
39+
pub ram_cached: u64,
3740
pub swap_pct: f64,
3841
pub swap_used: u64,
3942
pub swap_total: u64,
@@ -134,12 +137,15 @@ pub fn run(
134137
theme_cursor,
135138
theme_scroll: 0,
136139
cpu_pct: 0.0,
140+
cpu_total_pct: 0.0,
137141
cpu_hist: VecDeque::with_capacity(HISTORY_LEN),
138142
cpu_cores: sys.cpus().len(),
139143
cpu_freq: system::read_cpu_freq().unwrap_or_else(|| "N/A".to_string()),
140144
ram_pct: 0.0,
141145
ram_used: 0,
142146
ram_total: 0,
147+
ram_available: 0,
148+
ram_cached: 0,
143149
swap_pct: 0.0,
144150
swap_used: 0,
145151
swap_total: 0,
@@ -186,6 +192,7 @@ pub fn run(
186192
// Sample CPU
187193
sys.refresh_cpu_usage();
188194
state.cpu_pct = sys.global_cpu_usage() as f64;
195+
state.cpu_total_pct = sys.cpus().iter().map(|c| c.cpu_usage() as f64).sum();
189196
state.cpu_hist.push_back(state.cpu_pct);
190197
if state.cpu_hist.len() > HISTORY_LEN {
191198
state.cpu_hist.pop_front();
@@ -207,6 +214,9 @@ pub fn run(
207214
} else {
208215
0.0
209216
};
217+
let (avail, cached) = system::read_available_cached();
218+
state.ram_available = avail;
219+
state.ram_cached = cached;
210220
state.swap_total = sys.total_swap();
211221
state.swap_used = sys.used_swap();
212222
state.swap_pct = if state.swap_total > 0 {

ktop-rs/src/system.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,27 @@ fn chrono_format_full(epoch: f64) -> String {
412412
month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec)
413413
}
414414

415+
// ── Available/Cached from /proc/meminfo ──
416+
417+
pub fn read_available_cached() -> (u64, u64) {
418+
let mut available: u64 = 0;
419+
let mut cached: u64 = 0;
420+
if let Ok(contents) = fs::read_to_string("/proc/meminfo") {
421+
for line in contents.lines() {
422+
if let Some(rest) = line.strip_prefix("MemAvailable:") {
423+
if let Ok(kb) = rest.trim().trim_end_matches(" kB").trim().parse::<u64>() {
424+
available = kb * 1024;
425+
}
426+
} else if let Some(rest) = line.strip_prefix("Cached:") {
427+
if let Ok(kb) = rest.trim().trim_end_matches(" kB").trim().parse::<u64>() {
428+
cached = kb * 1024;
429+
}
430+
}
431+
}
432+
}
433+
(available, cached)
434+
}
435+
415436
// ── CPU frequency from sysfs ──
416437

417438
pub fn read_cpu_freq() -> Option<String> {

ktop-rs/src/ui.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,10 @@ fn render_cpu(f: &mut Frame, area: Rect, state: &AppState) {
313313
lines.push(Line::from(overall));
314314

315315
lines.push(Line::from(Span::styled(
316-
format!("Cores: {} Freq: {}", state.cpu_cores, state.cpu_freq),
316+
format!(
317+
"Cores: {} Total: {:.0}% Freq: {}",
318+
state.cpu_cores, state.cpu_total_pct, state.cpu_freq
319+
),
317320
Style::default().fg(Color::DarkGray),
318321
)));
319322
lines.push(Line::from(""));
@@ -396,10 +399,21 @@ fn render_mem(f: &mut Frame, area: Rect, state: &AppState) {
396399
swap_line.extend(swap_bar);
397400
swap_line.push(Span::styled(format!(" {:5.1}%", swap_pct), Style::default().fg(Color::DarkGray)));
398401
lines.push(Line::from(swap_line));
399-
lines.push(Line::from(format!(
400-
" {} used / {}",
401-
fmt_bytes(state.swap_used as f64),
402-
fmt_bytes(state.swap_total as f64)
402+
lines.push(Line::from(Span::styled(
403+
format!(
404+
" {} used / {}",
405+
fmt_bytes(state.swap_used as f64),
406+
fmt_bytes(state.swap_total as f64)
407+
),
408+
Style::default().fg(Color::DarkGray),
409+
)));
410+
lines.push(Line::from(Span::styled(
411+
format!(
412+
" {} avail Cache: {}",
413+
fmt_bytes(state.ram_available as f64),
414+
fmt_bytes(state.ram_cached as f64)
415+
),
416+
Style::default().fg(Color::DarkGray),
403417
)));
404418

405419
let block = styled_block("Memory", theme.mem);

0 commit comments

Comments
 (0)