Last active
May 13, 2026 08:24
-
-
Save gatopeich/567c04d523833c40c7cca0ab06baa736 to your computer and use it in GitHub Desktop.
TMUX/Byobu status bar: CPU+MEM usage bars in only 4 chars
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| # Byobu custom status script: CPU + MEM as colored UTF-8 block chars. | |
| # Install: place in ~/.byobu/bin/01_cpu_mem_bars and chmod +x | |
| # Enable: add 'custom' to tmux_right in ~/.byobu/status | |
| # | |
| # Integration — vanilla tmux (~/.tmux.conf): | |
| # set -g status-right '#(~/.byobu/bin/01_cpu_mem_bars)%H:%M:%S' | |
| # | |
| # Integration — byobu (~/.byobu/profile.tmux): | |
| # source $BYOBU_PREFIX/share/byobu/profiles/tmux | |
| # set -g status-right '#(byobu-status tmux_right)#(~/.byobu/bin/01_cpu_mem_bars)%H:%M:%S' | |
| # | |
| # Output examples (as seen in byobu status bar): | |
| # c▁m▂ CPU ~10% (cyan), MEM ~20% (cyan) — all quiet | |
| # c▃M▆ CPU ~25% (cyan), MEM ~70% (yellow) — memory notable | |
| # C▅M▇ CPU ~60% (yellow), MEM ~85% (red) — both busy | |
| # C█M█ CPU ~95% (red), MEM ~95% (red) — under pressure | |
| # C▆M! MEM ≥95% — memory alarm: M! in white bold on red background | |
| # | |
| # Letter is uppercase when usage > 50%, lowercase otherwise. | |
| # Colors: cyan <30%, green 30-60%, yellow 60-85%, red >85% | |
| import os, time | |
| CACHE = os.path.join(os.environ.get('TMPDIR', '/tmp'), 'proc_stat.last') | |
| def cpu_pct(): | |
| cur = [int(x) for x in open('/proc/stat').readline().split()[1:]] | |
| try: | |
| prev = [int(x) for x in open(CACHE).read().split()] | |
| cached_time = os.path.getmtime(CACHE) | |
| except OSError: | |
| cached_time, prev = 0, cur | |
| total = sum(cur) - sum(prev) | |
| # Write cache only when stale or on counter wrap — avoids redundant writes | |
| # when multiple byobu status processes run close together each second. | |
| # time.time() is called here, as close as reasonable to cache write. | |
| if time.time() - cached_time > 1 or total <= 0: | |
| with open(CACHE, 'w', encoding="utf-8") as cache: | |
| cache.write(' '.join(map(str, cur))) | |
| if total <= 0: | |
| return 0 | |
| idle = (cur[3] + cur[4]) - (prev[3] + prev[4]) | |
| return (total - idle) * 100 // total | |
| def mem_pct(): | |
| info = {} | |
| for line in open('/proc/meminfo'): | |
| k, v = line.split()[0].rstrip(':'), int(line.split()[1]) | |
| info[k] = v | |
| if 'MemTotal' in info and 'MemAvailable' in info: break | |
| return (info['MemTotal'] - info['MemAvailable']) * 100 // info['MemTotal'] | |
| def fmt(pct): | |
| color = 'red' if pct > 85 else 'yellow' if pct > 60 else 'green' if pct > 30 else 'cyan' | |
| bar = chr(0x2580 + max(1, pct * 8 // 100)) | |
| return color, bar | |
| cpu = cpu_pct() | |
| mem = mem_pct() | |
| cc, cb = fmt(cpu) | |
| cl = 'C' if cpu > 50 else 'c' | |
| if mem >= 95: | |
| mem_part = '#[bg=red,fg=white,bold]M!' | |
| else: | |
| mc, mb = fmt(mem) | |
| ml = 'M' if mem > 50 else 'm' | |
| mem_part = f'#[fg={mc}]{ml}{mb}' | |
| print(f'\033#[fg=black,bg=default]▐#[fg={cc},bg=black]{cl}{cb}{mem_part}#[fg=black,bg=default]▌#[default]', end='') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment