diff --git a/Kitty-setup.md b/Kitty-setup.md new file mode 100644 index 0000000..385ef6d --- /dev/null +++ b/Kitty-setup.md @@ -0,0 +1,125 @@ +# Kitty Terminal Setup + +Custom kitty terminal theme with a status bar showing system info. + +## What You Get + +- Borderless window (no titlebar) +- Dark theme with orange (#D35400) accent +- Custom tab/status bar at top with: + - Flat tab style (0-indexed) + - `user@` prefix for non-seth users + - Right-aligned status: git branch, CPU%, memory, uptime, hostname, clock + - Nerd Font icons +- F12 to hide tab bar, Shift+F12 to show it + +## Prerequisites + +- **kitty** terminal (`>= 0.41`) +- **JetBrainsMono Nerd Font** (for status bar icons) +- **git** (for branch display in status bar) +- **Linux** (CPU/memory/uptime read from `/proc`) + +## Quick Install + +```bash +git clone https://git.sethpc.xyz/Seth/seth-linux-theme.git +cd seth-linux-theme +./install-kitty-theme.sh +``` + +Or for a specific user's home: + +```bash +./install-kitty-theme.sh /home/username +``` + +## Manual Install + +### 1. Install the Nerd Font + +```bash +mkdir -p /tmp/nerdfonts && cd /tmp/nerdfonts +curl -fLO https://github.com/ryanoasis/nerd-fonts/releases/latest/download/JetBrainsMono.zip +sudo mkdir -p /usr/local/share/fonts/NerdFonts +sudo unzip -o JetBrainsMono.zip -d /usr/local/share/fonts/NerdFonts/ +sudo fc-cache -f +``` + +Verify: + +```bash +fc-list | grep -i "JetBrains.*Nerd" +``` + +### 2. Copy theme files + +```bash +cp kitty/kitty-theme.conf ~/.config/kitty/ +cp kitty/tab_bar.py ~/.config/kitty/ +cp kitty/tab-bar-hide.conf ~/.config/kitty/ +cp kitty/tab-bar-show.conf ~/.config/kitty/ +``` + +### 3. Set the font in kitty.conf + +```bash +# In ~/.config/kitty/kitty.conf, set: +font_family JetBrainsMono Nerd Font +font_size 11.0 +``` + +### 4. Include the theme + +Add this line to the end of `~/.config/kitty/kitty.conf`: + +``` +include kitty-theme.conf +``` + +### 5. Restart kitty + +Close and reopen kitty. Ctrl+Shift+F5 does NOT reload tab bar or font changes. + +## Files + +| File | Purpose | +|------|---------| +| `kitty-theme.conf` | Colors, tab bar settings, keybindings | +| `tab_bar.py` | Custom tab bar renderer (flat tabs + status area) | +| `tab-bar-hide.conf` | Config snippet to hide tab bar | +| `tab-bar-show.conf` | Config snippet to show tab bar | + +## Keybindings + +| Key | Action | +|-----|--------| +| F12 | Hide tab/status bar | +| Shift+F12 | Show tab/status bar | + +## Status Bar Items + +All read from `/proc` (no subprocess overhead except git): + +| Item | Source | Icon | +|------|--------|------| +| Git branch | `git rev-parse` (1s timeout) | | +| CPU % | `/proc/stat` (delta between refreshes) | | +| Memory | `/proc/meminfo` (used/total in GB) | 󰍛 | +| Uptime | `/proc/uptime` | | +| Hostname | `os.uname().nodename` | | +| Clock | `datetime.now()` (HH:MM) | | + +## Customization + +- **Colors**: Edit `_ORANGE`, `_DIM`, `_TAB_BG`, `_BAR_BG` in `tab_bar.py` +- **Status items**: Add/remove cells in the `if is_last:` block in `tab_bar.py` +- **Refresh rate**: Change `tab_bar_timeout` in `kitty-theme.conf` (seconds) +- **User prefix**: The `_prefix` logic in `tab_bar.py` shows `user@` for non-seth users + +## Troubleshooting + +- **Icons show as boxes**: Nerd Font not installed or kitty not using it. Check `font_family` in kitty.conf. +- **Status bar not updating**: Ensure `tab_bar_timeout 60.0` is set in kitty-theme.conf. +- **F12 does nothing**: Ensure `allow_remote_control yes` and `listen_on unix:/tmp/kitty-{kitty_pid}` are in config. Restart kitty (not just reload). +- **CPU shows "..."**: Normal on first draw — needs two samples to compute delta. diff --git a/SESSION.md b/SESSION.md index e2daf8e..3d89c84 100644 --- a/SESSION.md +++ b/SESSION.md @@ -1,114 +1,90 @@ -MAIN OBJECTIVE: Create SESSION.md in your project directory according to the folliwing template. Do NOT modify this source file. -# SESSION.md — Persistent AI Session Memory +# SESSION.md — Seth Linux Theme -This is the template and guide for `SESSION.md` files used across projects in this homelab. +## Project Summary +Centralized Linux desktop theme for Seth's GNOME setup. Black titlebars, square corners, ultra-thin headerbars, dark mode with orange accent (#D35400). Configs for GTK3/4 CSS, kitty terminal, and GNOME gsettings. ---- - -## What SESSION.md is for - -`SESSION.md` is a **persistent memory file** — it accumulates decisions, discoveries, and context across AI coding sessions so the assistant doesn't start cold each time. - -It is **not** a chat transcript. -It is **not** static documentation of how something works. -It is a living record of *why things are the way they are*, plus a map to the right context files. - ---- - -## Where to put it - -| Scope | Location | Purpose | -|---|---|---| -| Global homelab | `/root/bin/SESSION.md` ← this file | Cross-project memory, patterns, major decisions | -| Per-project | `/SESSION.md` | Project-specific session memory | - -Each project `SESSION.md` should link back here and to any relevant context files. - ---- - -## How to populate it - -Copy the section structure below into your project's `SESSION.md` and fill it in. - -### Mandatory sections - -**Context pointers** — every `SESSION.md` must list the files the AI should load to understand the project: - -```markdown -## Context Files - -- `/root/bin/core_homelab.md` — cluster topology, SSH aliases -- `/root/bin/services_directory.md` — active service IPs and domains -- `/root/bin/SESSION.md` — global session memory (this file's parent) -- `./CONTEXT.md` — project-specific infrastructure and config -- `./README.md` — project overview -``` - -**Project summary** — one paragraph. What is this project? What problem does it solve? - -**Gitea repo** — link to the Gitea remote (if version-controlled): - -```markdown ## Gitea +- Repo: https://git.sethpc.xyz/Seth/seth-linux-theme -- Repo: https://git.sethpc.xyz/Seth/ -- Remote: `https://Seth:@git.sethpc.xyz/Seth/.git` -- API key: see `/root/bin/GITEA_API.md` (same key for all repos) -``` +## Context Files +- `gtk-3.0/gtk.css` — GTK3/4 headerbar CSS (same file used for both) +- `kitty/kitty-theme.conf` — kitty terminal overrides (borderless, black titlebar, tab bar config, keybindings) +- `kitty/tab_bar.py` — custom tab bar: flat tabs + right-aligned status (git, cpu, mem, uptime, host, clock) +- `kitty/tab-bar-hide.conf` / `tab-bar-show.conf` — toggle snippets (may be unused now with inline --override approach) +- `gnome/apply-gnome-settings.sh` — GNOME dark mode, orange accent, Super+right resize +- `install.sh` — deploys all configs to target user's ~/.config -**Session notes** — the meat of the file. Append here each session. - ---- - -## Session notes format - -Group entries by topic, not by date. Update the relevant section rather than appending raw timestamped blocks. Example: - -```markdown ## Session Notes -### Infrastructure decisions -- Chose LXC over Docker-in-LXC because the service doesn't need container isolation -- Enabled nesting=1 on CT 644 to allow Docker inside +### Architecture +- GTK CSS goes in `~/.config/gtk-3.0/gtk.css` and `~/.config/gtk-4.0/gtk.css` (same content) +- kitty uses its own config, not GTK — `wayland_titlebar_color` only works with CSD, not Mutter SSD +- `hide_window_decorations yes` removes Mutter's server-side decorations from kitty entirely (borderless) +- GNOME Shell rounded corners are Mutter-controlled, not GTK CSS — need GNOME Shell theme or extension to override DE-wide +- `resize-with-right-button true` enables Super+right-drag to resize (was disabled by default) -### Bug fixes & discoveries -- Service wasn't starting: mc1 had autoStart=false in MCSManager config - (fixed: set eventTask.autoStart=true in InstanceConfig/.json) -- tail -F (capital F) is correct — waits for file to appear, handles log rotation +### Deployment +- Desktop runs on steel141 (192.168.0.141) under `seth@` user +- `claude@` is headless, no DE — GUI configs must target `/home/seth/.config/` +- From claude@: `sudo -u seth cp /home/seth/.config/...` +- GTK3 apps pick up CSS changes live (open new window). GTK4/libadwaita apps need full relaunch. Kitty needs relaunch. -### Open threads -- [ ] Add Redis backend for session persistence (currently SQLite only) -- [ ] Web dashboard for recent AI god interactions -``` +### Current state (2026-04-07) +- GTK CSS: black headerbar, square corners, white text, transparent buttons, #999 backdrop text/icons, 36px min-height +- Kitty: borderless (`hide_window_decorations yes`), JetBrainsMono Nerd Font, custom tab bar with status area +- Kitty tab bar: flat style (no powerline), user@ prefix for non-seth users, right-aligned status (git branch, CPU%, memory, uptime, hostname, clock) with Nerd Font icons in orange +- Kitty tab bar toggle: F12 hides (min_tabs=999), Shift+F12 shows (min_tabs=1) via `remote_control load-config --override` +- GNOME: dark mode, orange accent, Super+right resize enabled ---- +### Open issues +- [ ] GNOME Shell rounded window corners — Mutter hardcodes CSD corner rounding at compositor level. No CSS override possible (tried `border-radius: 0 !important` on all nodes). No gsetting exists. GNOME Shell CSS `.window-frame` doesn't control it either. Only fix: patched Mutter or a GNOME Shell extension that modifies Mutter's clipping behavior. "Rounded Window Corners Reborn" extension only ADDS rounding (shader overlay), doesn't remove native rounding. -## How to keep it current +### Resolved issues (2026-04-07) +- [x] Nautilus sidebar/main headerbar height mismatch — Fixed by targeting `headerbar stackpage > box` and `headerbar stack` with `min-height: 0` and zero padding. Root cause: NautilusPathBar inside a GtkStack in the main headerbar was taller than the sidebar's simple AdwWindowTitle. +- [x] Thin gray border line at top of headerbar — Fixed by targeting `decoration`, `window.csd`, `.titlebar:not(headerbar)`, and `toolbarview > .top-bar` with `border: none; box-shadow: none; outline: none`. Was a CSD decoration border, not on the headerbar node itself. +- [x] User Themes extension — Installed (`gnome-shell-extension-user-theme` apt package), enabled, Sethian theme set via `gsettings set org.gnome.shell.extensions.user-theme name "Sethian"`. Required `gnome-shell --replace` to detect newly installed extension. -Run `/update-context` in OpenCode at the end of any session. The command will: -1. Scan the conversation for decisions, fixes, and discoveries not yet recorded -2. Append them to `SESSION.md` (both this file and the project-level one if applicable) -3. Commit and push to Gitea +### Design decisions +- 2026-04-07: Use stock Adwaita dark + CSS overrides, not a full third-party theme — minimal maintenance, survives GNOME updates +- 2026-04-07: Kitty borderless rather than trying to style Mutter's SSD — cleaner, no titlebar to fight with +- 2026-04-07: adw-gtk3 not needed if only overriding headerbar — stock Adwaita + user CSS is sufficient +- 2026-04-07: Flat tab style over powerline — powerline creates clipping artifacts with long titles, flat is simpler +- 2026-04-07: JetBrainsMono Nerd Font — needed for icon glyphs in tab bar status area +- 2026-04-07: Tab bar toggle via `remote_control load-config --override` — no scripts/sockets needed, inline kitty RC -Command defined at: `~/.config/opencode/commands/update-context.md` +### DANGER — never do these +- **NEVER run `gnome-shell --replace` from claude@ session** — it replaces seth's shell process, kills the active session, resets all extensions and theming to defaults. Use `dbus-send` reexec or ask seth to relog instead. -Mandatory per-reply discipline: -- Update `SESSION.md` immediately when a durable fact, decision, or fix is discovered. -- Before every final reply, run a memory check and append any missing durable notes. -- End every reply with one line: `Session memory: updated` or `Session memory: no new durable facts.` +### Kitty architecture notes +- Repo files (`seth-linux-theme/kitty/`) and Seth's live config (`/home/seth/.config/kitty/`) are separate copies, not symlinks — must deploy manually +- `tab_bar.py` custom draw function: kitty calls `draw_tab()` for each tab. `is_last=True` is the hook for drawing right-aligned status +- CPU % uses delta sampling from `/proc/stat` — first draw shows "..." (no prior sample), subsequent draws show real usage +- `kitty @ load-config` merges overrides into running instance without restart +- `remote_control` from a keymap runs inside kitty's process — no socket/listen_on needed +- Kitty does NOT hot-reload `tab_bar.py`, font changes, or keybindings — full restart required +- Ctrl+Shift+F5 only reloads colors/visuals +- `toggle_tab_bar` action does NOT exist in kitty 0.41.1 +- `set-option` RC command does NOT exist — use `load-config --override` instead +- `load-config-file` is wrong command name — correct is `load-config` +- Nerd Font installed system-wide at `/usr/local/share/fonts/NerdFonts/` ---- +### What was tried and didn't work +- `headerbar *` with `min-height: 0` — didn't equalize sidebar/main headerbar heights +- `headerbar > windowhandle > centerbox` targeting — no effect on height mismatch +- `wayland_titlebar_color` in kitty — ignored when Mutter uses server-side decorations +- `border: none` on headerbar — doesn't remove the gray line at top (it's not a headerbar border) +- `border-radius: 0 !important` on `window`, `window.csd`, `decoration`, `.titlebar` — doesn't remove rounded corners (Mutter compositor-level clipping) +- GNOME Shell theme `.window-frame { border-radius: 0 }` — doesn't control Mutter's window corner rounding +- GTK_DEBUG=interactive on Nautilus — inspector window doesn't open (GNOME 48, Nautilus 48.3). Ctrl+Shift+D/I also failed. Shell restart required for newly installed extensions. +- `draw_tab_with_powerline` — creates clipping artifacts with long tab titles (extra rectangle gets cut off) +- `toggle_tab_bar` kitty action — doesn't exist in 0.41.1 +- `remote_control set-option` — not a valid RC command +- `remote_control load-config-file` — wrong name, correct is `load-config` +- `map ctrl+shift+f1` — produces capital P instead of triggering action (escape sequence issue) +- Toggle via background script + `kitty @` + socket — overcomplicated, socket discovery unreliable from background processes +- `listen_on unix:/tmp/kitty-{kitty_pid}` + script with `kitty @ --to` — still failed, too many moving parts -## Global session notes - -### Patterns established across all projects - -- **Gitea backup convention:** commit every meaningful change immediately; push on the same command. No squashing, no batching unrelated changes. -- **Session file naming:** `SESSION.md` (not `CONVERSATION.md`, not `CONTEXT.md`). `CONTEXT.md` = static infra facts. `SESSION.md` = accumulated AI memory. -- **Context file loading:** Always include `core_homelab.md` and `services_directory.md` in project instructions. Specific project context goes in `CONTEXT.md`. -- **autoStart for MCSManager instances:** Must be set in `InstanceConfig/.json` (`eventTask.autoStart: true`), not just in the panel UI, to survive daemon restarts. - -### Infrastructure discoveries - -- `mc-godmode.service` on CT 644: already enabled and using `tail -F` correctly. The MC server itself had `autoStart: false` — that was the real issue. -- Gitea runs on port 443 via Caddy at `git.sethpc.xyz` (CT 146, node-173). Direct access to `192.168.0.125:80` does not work from CT 629 — always use the domain. +### Debugging notes (2026-04-07) +- Nautilus widget tree (from gresource): `NautilusWindow` (AdwApplicationWindow) → `AdwOverlaySplitView` → sidebar: `AdwToolbarView` → `AdwHeaderBar`; content: `AdwToolbarView` → `NautilusToolbar` (AdwBin) → `AdwHeaderBar` with title = `GtkBox` containing `NautilusPathBar` in a `GtkStack` +- The main headerbar height was driven by NautilusPathBar's default min-height/padding in the GtkStack +- The gray top line was from the CSD `decoration` node and/or `toolbarview > .top-bar` border diff --git a/gtk-3.0/gtk.css b/gtk-3.0/gtk.css index f38907d..fbee27b 100644 --- a/gtk-3.0/gtk.css +++ b/gtk-3.0/gtk.css @@ -1,11 +1,17 @@ -/* Black titlebar, square corners, ultra-thin */ +/* Seth Linux Theme — Black titlebar, square corners, ultra-thin headerbars */ + +/* === Headerbar === */ headerbar { background: #000; - border-radius: 0; + min-height: 36px; + border-radius: 0 !important; + border: none; + border-top: none; border-bottom: 1px solid #555; box-shadow: none; - min-height: 10px; - padding: 0 2px; + outline: none; + padding: 0 4px; + margin-top: 0; color: #fff; font-weight: bold; } @@ -20,9 +26,7 @@ headerbar button { background: transparent; color: #fff; border: none; - min-height: 14px; - min-width: 14px; - padding: 0 2px; + padding: 0 4px; margin: 0; box-shadow: none; } @@ -35,10 +39,61 @@ headerbar:backdrop button { color: #999; } -window, window.background { - border-radius: 0; +/* === Equalize sidebar/main headerbar heights (Nautilus path bar pushes main taller) === */ +headerbar stackpage > box, +headerbar stackpage > box > * { + min-height: 0; + padding-top: 0; + padding-bottom: 0; +} + +headerbar stack { + min-height: 0; +} + +/* === Window decoration: square corners, no borders === */ +window, window.background, window.csd, window.solid-csd { + border-radius: 0 !important; } .titlebar, decoration { - border-radius: 0; + border-radius: 0 !important; + border: none; + box-shadow: none; +} + +decoration { + border-top: none; + outline: none; + margin: 0; +} + +window.csd { + border: none; + box-shadow: none; + outline: none; +} + +.titlebar:not(headerbar) { + border: none; + box-shadow: none; + outline: none; + background: transparent; + min-height: 0; + padding: 0; + margin: 0; +} + +/* === Kill gray line at top of window (CSD decoration border) === */ +toolbarview > .top-bar { + border: none; + box-shadow: none; + outline: none; +} + +/* === Strip separators === */ +separator { + min-height: 0; + border: none; + background: none; } diff --git a/install-debian-theme.sh b/install-debian-theme.sh new file mode 100755 index 0000000..6e3287b --- /dev/null +++ b/install-debian-theme.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Install the full Seth Linux Theme on Debian/Ubuntu with GNOME +set -euo pipefail + +TARGET_HOME="${1:-$HOME}" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" + +echo "=== Seth Linux Theme — Full Install ===" +echo "Target: $TARGET_HOME" +echo "" + +# ── GTK CSS ── +echo "--- GTK CSS ---" +mkdir -p "$TARGET_HOME/.config/gtk-3.0" "$TARGET_HOME/.config/gtk-4.0" +cp "$SCRIPT_DIR/gtk-3.0/gtk.css" "$TARGET_HOME/.config/gtk-3.0/gtk.css" +cp "$SCRIPT_DIR/gtk-3.0/gtk.css" "$TARGET_HOME/.config/gtk-4.0/gtk.css" +echo "[ok] GTK3/4 CSS installed." + +# ── Kitty ── +echo "" +echo "--- Kitty Terminal ---" +if command -v kitty &>/dev/null; then + bash "$SCRIPT_DIR/install-kitty-theme.sh" "$TARGET_HOME" +else + echo "[skip] kitty not found. Install kitty first, then run:" + echo " $SCRIPT_DIR/install-kitty-theme.sh $TARGET_HOME" +fi + +# ── GNOME Settings ── +echo "" +echo "--- GNOME Settings ---" +if command -v gsettings &>/dev/null; then + bash "$SCRIPT_DIR/gnome/apply-gnome-settings.sh" +else + echo "[skip] gsettings not found — not a GNOME session?" +fi + +echo "" +echo "=== Install complete ===" +echo " - GTK apps: open new windows to see changes (libadwaita apps need full relaunch)" +echo " - Kitty: restart kitty" +echo " - GNOME: changes applied immediately" diff --git a/install-kitty-theme.sh b/install-kitty-theme.sh new file mode 100755 index 0000000..af4dd2e --- /dev/null +++ b/install-kitty-theme.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +# Install Seth's kitty theme + Nerd Font on any Linux machine +set -euo pipefail + +TARGET_HOME="${1:-$HOME}" +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +KITTY_DIR="$TARGET_HOME/.config/kitty" + +echo "=== Seth Linux Theme — Kitty Install ===" +echo "Target: $TARGET_HOME" + +# ── Nerd Font ── +if fc-list | grep -qi "JetBrainsMono.*Nerd" 2>/dev/null; then + echo "[ok] JetBrainsMono Nerd Font already installed." +else + echo "[install] Downloading JetBrainsMono Nerd Font..." + TMP="$(mktemp -d)" + curl -fsSL -o "$TMP/JetBrainsMono.zip" \ + https://github.com/ryanoasis/nerd-fonts/releases/latest/download/JetBrainsMono.zip + sudo mkdir -p /usr/local/share/fonts/NerdFonts + sudo unzip -oq "$TMP/JetBrainsMono.zip" -d /usr/local/share/fonts/NerdFonts/ + sudo fc-cache -f + rm -rf "$TMP" + echo "[ok] Nerd Font installed." +fi + +# ── Kitty config dir ── +mkdir -p "$KITTY_DIR" + +# Create default kitty.conf if none exists +if [ ! -f "$KITTY_DIR/kitty.conf" ]; then + echo "# kitty.conf" > "$KITTY_DIR/kitty.conf" + echo "[ok] Created default kitty.conf." +fi + +# ── Copy theme files ── +cp "$SCRIPT_DIR/kitty/kitty-theme.conf" "$KITTY_DIR/" +cp "$SCRIPT_DIR/kitty/tab_bar.py" "$KITTY_DIR/" +cp "$SCRIPT_DIR/kitty/tab-bar-hide.conf" "$KITTY_DIR/" +cp "$SCRIPT_DIR/kitty/tab-bar-show.conf" "$KITTY_DIR/" +echo "[ok] Theme files copied." + +# ── Set font in kitty.conf ── +if grep -q "^font_family" "$KITTY_DIR/kitty.conf"; then + sed -i 's/^font_family.*/font_family JetBrainsMono Nerd Font/' "$KITTY_DIR/kitty.conf" +elif grep -q "^# font_family" "$KITTY_DIR/kitty.conf"; then + sed -i 's/^# font_family.*/font_family JetBrainsMono Nerd Font/' "$KITTY_DIR/kitty.conf" +else + echo "" >> "$KITTY_DIR/kitty.conf" + echo "font_family JetBrainsMono Nerd Font" >> "$KITTY_DIR/kitty.conf" +fi +echo "[ok] Font set to JetBrainsMono Nerd Font." + +# ── Include theme conf ── +if ! grep -q "include kitty-theme.conf" "$KITTY_DIR/kitty.conf" 2>/dev/null; then + echo "" >> "$KITTY_DIR/kitty.conf" + echo "include kitty-theme.conf" >> "$KITTY_DIR/kitty.conf" +fi +echo "[ok] kitty-theme.conf included." + +echo "" +echo "Done. Restart kitty to see changes." +echo " F12 = hide tab bar" +echo " Shift+F12 = show tab bar" diff --git a/install.sh b/install.sh index c12fed9..4ece871 100755 --- a/install.sh +++ b/install.sh @@ -16,6 +16,7 @@ echo " GTK CSS installed." # Kitty theme conf if [ -d "$TARGET_HOME/.config/kitty" ]; then cp "$SCRIPT_DIR/kitty/kitty-theme.conf" "$TARGET_HOME/.config/kitty/kitty-theme.conf" + cp "$SCRIPT_DIR/kitty/tab_bar.py" "$TARGET_HOME/.config/kitty/tab_bar.py" if ! grep -q "include kitty-theme.conf" "$TARGET_HOME/.config/kitty/kitty.conf" 2>/dev/null; then echo "" >> "$TARGET_HOME/.config/kitty/kitty.conf" echo "include kitty-theme.conf" >> "$TARGET_HOME/.config/kitty/kitty.conf" diff --git a/kitty/kitty-theme.conf b/kitty/kitty-theme.conf index 13a2327..f1a3cb0 100644 --- a/kitty/kitty-theme.conf +++ b/kitty/kitty-theme.conf @@ -1,10 +1,37 @@ # Seth Linux Theme — kitty overrides # Include from kitty.conf: include ~/path/to/kitty-theme.conf -tab_bar_edge top allow_remote_control yes +listen_on unix:/tmp/kitty-{kitty_pid} wayland_titlebar_color #000000 macos_titlebar_color #000000 hide_window_decorations yes window_border_width 0 draw_minimal_borders yes + +# ── Status bar (tab bar at top) ────────────────── +tab_bar_edge top +tab_bar_min_tabs 1 +tab_bar_style custom +tab_powerline_style round +tab_bar_align left +tab_title_template " {index}: {title} " +active_tab_title_template " {index}: {title} " +tab_title_max_length 40 + +# Colors — Sethian dark + orange +active_tab_foreground #000000 +active_tab_background #D35400 +active_tab_font_style bold +inactive_tab_foreground #888888 +inactive_tab_background #1a1a1a +inactive_tab_font_style normal +tab_bar_background #0d0d0d +tab_bar_margin_height 2.0 0.0 + +# Refresh tab bar for clock updates +tab_bar_timeout 60.0 + +# Toggle tab/status bar +map f12 remote_control load-config --override tab_bar_min_tabs=999 +map shift+f12 remote_control load-config --override tab_bar_min_tabs=1 diff --git a/kitty/tab-bar-hide.conf b/kitty/tab-bar-hide.conf new file mode 100644 index 0000000..ae21ab5 --- /dev/null +++ b/kitty/tab-bar-hide.conf @@ -0,0 +1 @@ +tab_bar_min_tabs 999 diff --git a/kitty/tab-bar-show.conf b/kitty/tab-bar-show.conf new file mode 100644 index 0000000..9683846 --- /dev/null +++ b/kitty/tab-bar-show.conf @@ -0,0 +1 @@ +tab_bar_min_tabs 1 diff --git a/kitty/tab_bar.py b/kitty/tab_bar.py new file mode 100644 index 0000000..cbff639 --- /dev/null +++ b/kitty/tab_bar.py @@ -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 diff --git a/kitty/toggle-tab-bar.sh b/kitty/toggle-tab-bar.sh new file mode 100755 index 0000000..da5375c --- /dev/null +++ b/kitty/toggle-tab-bar.sh @@ -0,0 +1,17 @@ +#!/bin/bash +# Toggle kitty tab bar via kitty @ using KITTY_LISTEN_ON +STATE_FILE="/tmp/kitty-tab-bar-state" +SOCK="${KITTY_LISTEN_ON}" + +if [ -z "$SOCK" ]; then + # Fallback: find socket by parent kitty PID + SOCK="unix:/tmp/kitty-${KITTY_PID}" +fi + +if [ -f "$STATE_FILE" ] && [ "$(cat "$STATE_FILE")" = "hidden" ]; then + kitty @ --to "$SOCK" load-config /home/seth/.config/kitty/tab-bar-show.conf + echo "visible" > "$STATE_FILE" +else + kitty @ --to "$SOCK" load-config /home/seth/.config/kitty/tab-bar-hide.conf + echo "hidden" > "$STATE_FILE" +fi diff --git a/theme-setup.md b/theme-setup.md new file mode 100644 index 0000000..3dbd02a --- /dev/null +++ b/theme-setup.md @@ -0,0 +1,111 @@ +# Seth Linux Theme — Full Setup Guide + +Dark GNOME desktop theme with black titlebars, square corners, and orange (#D35400) accent. Covers GTK3/4, kitty terminal, and GNOME Shell settings. + +## What You Get + +- **GTK3/4**: Black headerbars, square window corners, ultra-thin bars (36px), no decorative borders +- **Kitty**: Borderless terminal with custom status bar (git, CPU, RAM, uptime, clock) +- **GNOME**: Dark mode, orange accent color, Super+right-drag resize + +## Prerequisites + +- **Debian/Ubuntu** (or any GNOME-based distro) +- **GNOME Shell** (tested on GNOME 48) +- **kitty** terminal (optional — theme works without it) +- **git** + +## Quick Install + +```bash +git clone https://git.sethpc.xyz/Seth/seth-linux-theme.git +cd seth-linux-theme +./install-debian-theme.sh +``` + +This installs everything: GTK CSS, kitty theme + Nerd Font, and GNOME settings. + +## What Each Component Does + +### GTK CSS (`gtk-3.0/gtk.css`) + +Applied to both GTK3 and GTK4 apps. Overrides: + +- Black headerbar background with white text +- 36px min-height headerbars (thinner than default) +- Square window corners (`border-radius: 0`) +- No CSD decoration borders or shadows +- Transparent headerbar buttons (white text, #222 hover) +- Backdrop state: #999 text/icons, #333 bottom border +- Nautilus sidebar/main headerbar height equalization + +### Kitty Terminal + +See [Kitty-setup.md](Kitty-setup.md) for full details. + +- Borderless window +- Custom tab bar with system status +- JetBrainsMono Nerd Font +- F12 toggle for tab bar + +### GNOME Settings + +- `color-scheme`: prefer-dark +- `accent-color`: orange +- `resize-with-right-button`: true (Super+right-drag to resize) +- `mouse-button-modifier`: Super + +## Manual Install + +### 1. GTK CSS + +```bash +mkdir -p ~/.config/gtk-3.0 ~/.config/gtk-4.0 +cp gtk-3.0/gtk.css ~/.config/gtk-3.0/gtk.css +cp gtk-3.0/gtk.css ~/.config/gtk-4.0/gtk.css +``` + +GTK3 apps pick up changes on next window open. GTK4/libadwaita apps need a full relaunch. + +### 2. Kitty + +See [Kitty-setup.md](Kitty-setup.md). + +### 3. GNOME Settings + +```bash +gsettings set org.gnome.desktop.interface color-scheme 'prefer-dark' +gsettings set org.gnome.desktop.interface accent-color 'orange' +gsettings set org.gnome.desktop.wm.preferences resize-with-right-button true +gsettings set org.gnome.desktop.wm.preferences mouse-button-modifier '' +``` + +## Files + +``` +seth-linux-theme/ +├── gtk-3.0/ +│ └── gtk.css # GTK3/4 headerbar + window CSS +├── kitty/ +│ ├── kitty-theme.conf # Kitty colors, tab bar, keybindings +│ ├── tab_bar.py # Custom tab bar renderer +│ ├── tab-bar-hide.conf # Toggle snippet (hide) +│ └── tab-bar-show.conf # Toggle snippet (show) +├── gnome/ +│ └── apply-gnome-settings.sh # GNOME gsettings +├── install.sh # Legacy install (home dir target) +├── install-kitty-theme.sh # Kitty-only install +└── install-debian-theme.sh # Full theme install (Debian/Ubuntu) +``` + +## Known Limitations + +- **Rounded window corners**: Mutter hardcodes corner rounding at the compositor level. GTK CSS `border-radius: 0` only affects CSD content, not the compositor clipping mask. Removing rounded corners requires a patched Mutter or a shell extension. +- **Kitty changes need restart**: `tab_bar.py`, font, and keybinding changes require closing and reopening kitty. Ctrl+Shift+F5 only reloads colors. +- **CPU % first draw**: Shows "..." on first tab bar draw (needs two `/proc/stat` samples to compute delta). + +## Customization + +- **Accent color**: Replace `#D35400` in `gtk.css`, `kitty-theme.conf`, and `tab_bar.py` +- **Headerbar height**: Change `min-height: 36px` in `gtk.css` +- **Tab bar items**: Edit the `if is_last:` block in `tab_bar.py`