feat: custom kitty tab bar with system status + install scripts

Custom tab_bar.py with flat tabs, right-aligned status area (git branch,
CPU%, memory, uptime, hostname, clock) using Nerd Font icons. F12/Shift+F12
toggle for tab bar. Added Kitty-setup.md, theme-setup.md, and install
scripts for kitty-only and full Debian theme deployment.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mortdecai
2026-04-09 07:26:15 -04:00
parent 03407654d6
commit 0c0066fef1
12 changed files with 692 additions and 109 deletions
+163
View File
@@ -0,0 +1,163 @@
"""Custom kitty tab bar — Sethian status bar.
Flat tab style (no powerline separators) + right-aligned status area.
Shows user@ prefix for non-seth users.
Status: git branch, CPU%, memory, uptime, hostname, clock.
"""
import os
import subprocess
from datetime import datetime
from kitty.tab_bar import (
DrawData,
ExtraData,
Screen,
TabBarData,
as_rgb,
)
_user = os.environ.get("USER", "")
_prefix = f"{_user}@" if _user and _user != "seth" else ""
_hostname = os.uname().nodename
# Nerd Font icons
_ICON_BRANCH = "\ue725"
_ICON_CPU = "\uf4bc"
_ICON_MEM = "\uf035b"
_ICON_UP = "\uf0aa"
_ICON_HOST = "\uf108"
_ICON_CLOCK = "\uf017"
# Colors
_ORANGE = as_rgb(0xD35400)
_BLACK = as_rgb(0x000000)
_DIM = as_rgb(0x666666)
_TAB_BG = as_rgb(0x1A1A1A)
_BAR_BG = as_rgb(0x0D0D0D)
def _get_git_branch() -> str:
try:
r = subprocess.run(
["git", "rev-parse", "--abbrev-ref", "HEAD"],
capture_output=True, text=True, timeout=1,
)
if r.returncode == 0:
return r.stdout.strip()
except Exception:
pass
return ""
def _get_cpu_percent() -> str:
try:
with open("/proc/stat") as f:
parts = f.readline().split()
idle = int(parts[4]) + int(parts[5])
total = sum(int(p) for p in parts[1:])
prev_idle = getattr(_get_cpu_percent, "_i", 0)
prev_total = getattr(_get_cpu_percent, "_t", 0)
_get_cpu_percent._i = idle
_get_cpu_percent._t = total
if prev_total == 0:
return "..."
dt = total - prev_total
di = idle - prev_idle
return f"{(1.0 - di / dt) * 100:.0f}%" if dt else "0%"
except Exception:
return "?"
def _get_memory() -> str:
try:
info = {}
with open("/proc/meminfo") as f:
for line in f:
p = line.split()
info[p[0].rstrip(":")] = int(p[1])
used = info["MemTotal"] - info.get("MemAvailable", info.get("MemFree", 0))
return f"{used / 1048576:.0f}/{info['MemTotal'] / 1048576:.0f}G"
except Exception:
return "?"
def _get_uptime() -> str:
try:
with open("/proc/uptime") as f:
secs = int(float(f.read().split()[0]))
d, rem = divmod(secs, 86400)
h, rem = divmod(rem, 3600)
m = rem // 60
if d > 0:
return f"{d}d {h}h"
return f"{h}h {m}m" if h > 0 else f"{m}m"
except Exception:
return "?"
def draw_tab(
draw_data: DrawData,
screen: Screen,
tab: TabBarData,
before: int,
max_tab_length: int,
index: int,
is_last: bool,
extra_data: ExtraData,
) -> int:
# Build tab title
title = tab.title
if _prefix:
title = f"{_prefix}{title}"
label = f" {index - 1}: {title} "
# Truncate if needed
if len(label) > max_tab_length:
label = label[: max_tab_length - 1] + "\u2026"
# Draw the tab
if tab.is_active:
screen.cursor.fg = _BLACK
screen.cursor.bg = _ORANGE
screen.cursor.bold = True
else:
screen.cursor.fg = _DIM
screen.cursor.bg = _TAB_BG
screen.cursor.bold = False
screen.draw(label)
screen.cursor.bold = False
# Small gap between tabs
screen.cursor.fg = _DIM
screen.cursor.bg = _BAR_BG
screen.draw(" ")
end = screen.cursor.x
# Right-aligned status on last tab
if is_last:
sep = " "
cells: list[tuple[str, int]] = []
branch = _get_git_branch()
if branch:
cells += [(_ICON_BRANCH + " ", _ORANGE), (branch, _DIM), (sep, _DIM)]
cells += [(_ICON_CPU + " ", _ORANGE), (_get_cpu_percent(), _DIM), (sep, _DIM)]
cells += [(_ICON_MEM + " ", _ORANGE), (_get_memory(), _DIM), (sep, _DIM)]
cells += [(_ICON_UP + " ", _ORANGE), (_get_uptime(), _DIM), (sep, _DIM)]
cells += [(_ICON_HOST + " ", _ORANGE), (_hostname, _DIM), (sep, _DIM)]
cells += [(_ICON_CLOCK + " ", _ORANGE), (datetime.now().strftime("%H:%M"), _DIM), (" ", _DIM)]
total_len = sum(len(t) for t, _ in cells)
right_pos = screen.columns - total_len
if right_pos > end:
screen.cursor.x = right_pos
for text, fg in cells:
screen.cursor.fg = fg
screen.cursor.bg = _BAR_BG
screen.draw(text)
return end