mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-02 19:32:43 +00:00
docs: add kitty‑day‑save support and update related documentation
This commit is contained in:
1 parent
7e2ae53560
commit
472695e596
6 files changed
+39
-12
No files matched your search
@@ -100,6 +100,7 @@ mise tool versions stay local to each machine and are not managed.
|
||||
.config/mimeapps.list
|
||||
.config/systemd
|
||||
.config/systemd/**
|
||||
.local/bin/kitty-day-save
|
||||
.local/bin/niri-launch
|
||||
.config/fish/auto-Niri.fish
|
||||
.local/bin/cp-appid
|
||||
@@ -107,7 +108,7 @@ mise tool versions stay local to each machine and are not managed.
|
||||
{{ end }}
|
||||
```
|
||||
|
||||
The block is emitted, and these paths skipped, unless the OS is `linux` and the role is `desktop` or `laptop`. `mac` and `server` machines, and any non-Linux machine regardless of role, never receive the niri compositor config (`dot_config/niri/`), fontconfig (`dot_config/fontconfig/fonts.conf`), default-app associations (`dot_config/mimeapps.list`), the fish auto-start hook (`dot_config/fish/auto-Niri.fish`), the tmux window-title helper, or the `niri-launch` and `cp-appid` scripts. The `noctalia`, `niri-dynamic-workspaces`, and `systemd` rules match nothing in the current source tree; they only take effect if those configs are added later.
|
||||
The block is emitted, and these paths skipped, unless the OS is `linux` and the role is `desktop` or `laptop`. `mac` and `server` machines, and any non-Linux machine regardless of role, never receive the niri compositor config (`dot_config/niri/`), fontconfig (`dot_config/fontconfig/fonts.conf`), default-app associations (`dot_config/mimeapps.list`), the fish auto-start hook (`dot_config/fish/auto-Niri.fish`), the tmux window-title helper, the systemd user units (`dot_config/systemd/user/kitty-day-save.service`), or the `niri-launch`, `cp-appid` and `kitty-day-save` scripts. The `noctalia` and `niri-dynamic-workspaces` rules match nothing in the current source tree; they only take effect if those configs are added later.
|
||||
|
||||
| Machine | Desktop layer |
|
||||
| --- | --- |
|
||||
|
||||
@@ -14,7 +14,7 @@ Six scripts run during `chezmoi apply`. Four live in `.chezmoiscripts/`, a direc
|
||||
<Step title="Files, symlinks, externals">chezmoi writes the target state.</Step>
|
||||
<Step title="20-gh-extensions (after, onchange)">Install gh extensions.</Step>
|
||||
<Step title="25-skills (after, onchange)">Install and prune agent skills.</Step>
|
||||
<Step title="30-user-services (after, once)">Enable systemd user units on Linux.</Step>
|
||||
<Step title="30-user-services (after, once)">Enable systemd user units on Linux (nirinit, kitty-day-save).</Step>
|
||||
<Step title="40-post (after, onchange)">bat cache, font cache.</Step>
|
||||
<Step title="build-bat-cache (after, onchange)">Rebuild bat cache when its theme or config changes.</Step>
|
||||
<Step title="install-yazi-plugins (after, onchange)">Reinstall yazi plugins when the manifest changes.</Step>
|
||||
@@ -93,9 +93,10 @@ A skipped run still exits 0, so chezmoi records this content as done and a plain
|
||||
`.chezmoiscripts/run_once_after_30-user-services.sh.tmpl` enables session-critical systemd user units on Linux.
|
||||
|
||||
- If `~/.config/systemd/user/nirinit.service` exists and `systemctl` is available, runs `systemctl --user daemon-reload` and `systemctl --user enable nirinit.service`. Failures are ignored.
|
||||
- Same check for `~/.config/systemd/user/kitty-day-save.service` (from `dot_config/systemd/user/`, so Linux desktop/laptop roles only), then `systemctl --user enable --now kitty-day-save.service`. See [kitty-day-save](/shell/scripts#kitty-day-save).
|
||||
- On non-Linux systems it renders to `#!/bin/sh` / `exit 0`.
|
||||
|
||||
Other personal automation units (brain-lens, omp-loop, rclone, hermes, voxtype) are deliberately not enabled; the script comment says to enable them by hand per machine. The repo does not currently contain a `dot_config/systemd/` directory, so the unit file has to exist on the machine already for this script to do anything.
|
||||
Other personal automation units (brain-lens, omp-loop, rclone, hermes, voxtype) are deliberately not enabled; the script comment says to enable them by hand per machine. Their unit files are not in the repo, so they have to exist on the machine already.
|
||||
|
||||
## 40-post [#40-post]
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ sidebar:
|
||||
---
|
||||
|
||||
:::note[Role gating]
|
||||
`.chezmoiignore.tmpl` skips the niri layer unless the machine runs Linux **and** its role is `desktop` or `laptop`. The gated targets are `~/.config/niri`, `~/.config/noctalia`, `~/.config/niri-dynamic-workspaces`, `~/.config/fontconfig`, `~/.config/mimeapps.list`, `~/.config/systemd`, `~/.local/bin/niri-launch`, `~/.local/bin/cp-appid`, `~/.config/fish/auto-Niri.fish`, and `~/.config/tmux/niri-title.sh`. On `mac` and `server` roles these are not applied.
|
||||
`.chezmoiignore.tmpl` skips the niri layer unless the machine runs Linux **and** its role is `desktop` or `laptop`. The gated targets are `~/.config/niri`, `~/.config/noctalia`, `~/.config/niri-dynamic-workspaces`, `~/.config/fontconfig`, `~/.config/mimeapps.list`, `~/.config/systemd`, `~/.local/bin/kitty-day-save`, `~/.local/bin/niri-launch`, `~/.local/bin/cp-appid`, `~/.config/fish/auto-Niri.fish`, and `~/.config/tmux/niri-title.sh`. On `mac` and `server` roles these are not applied.
|
||||
|
||||
`~/.config/hypr`, `~/.config/waybar`, the `omarchy-*` scripts, and the `niri-launch-ai` / `-browser` / `-terminal` / `-webapp` wrappers are **not** listed there, so chezmoi applies them on every role and OS. Only the exact path `.local/bin/niri-launch` is ignored, not the wrappers that call it.
|
||||
:::
|
||||
|
||||
@@ -41,6 +41,7 @@ Several scripts below also exist as fish functions of the same name (`ai`, `c2p`
|
||||
| [`ghn`](#ghn) | sh | Create a private repo, clone it, print the path |
|
||||
| [`git-summary`](#git-summary) | sh | Aggregate a repo's `AGENTS.md` files with code2prompt |
|
||||
| [`gop`](#gop) | sh | Open the current repo's web page |
|
||||
| [`kitty-day-save`](#kitty-day-save) | bash | Save kitty's daily session right before shutdown/reboot |
|
||||
| [`launch_omp_livediff_overlay`](#launch_omp_livediff_overlay) | sh | omp overlay plus a livediff split in kitty |
|
||||
| [`lc-elir`](#lc-elir) | sh | Run `/leetcode-eli5` via omp on picked solutions |
|
||||
| [`mdcp`](#mdcp) | sh | Fetch a URL as Markdown, copy it, preview it |
|
||||
@@ -189,6 +190,17 @@ Opens a repo's web page for any forge whose URL layout is `https://<host>/<owner
|
||||
|
||||
**Needs:** `git`, a browser or `xdg-open`.
|
||||
|
||||
## kitty-day-save
|
||||
|
||||
```sh
|
||||
kitty-day-save # hold a logind delay lock, flush on shutdown, exit
|
||||
kitty-day-save --now # flush every running kitty immediately
|
||||
```
|
||||
|
||||
Run by `kitty-day-save.service` (`dot_config/systemd/user/`, `WantedBy=graphical-session.target`, `Restart=always` after 10 s). It wraps itself in `systemd-inhibit --what=shutdown --mode=delay` and waits on `gdbus monitor` for login1's `PrepareForShutdown (true,)`. logind sends that before anything is killed and waits for the lock (`InhibitDelayMaxSec`, 5 s by default), so every kitty still has all its windows. It then sends `kitten day_session.py flush` over remote control to each `@kitty-<pid>` socket in `/proc/net/unix` (3 s timeout each) and exits, which releases the lock. The kitty that owns today's session saves it and holds further saves for 60 s; other kitties ignore the flush. See [kitty daily sessions](/terminal/kitty#daily-sessions).
|
||||
|
||||
**Needs:** `systemd-inhibit`, `gdbus`, `kitten`. Linux desktop/laptop roles only (`.chezmoiignore.tmpl`).
|
||||
|
||||
## launch_omp_livediff_overlay
|
||||
|
||||
```sh
|
||||
|
||||
@@ -61,7 +61,7 @@ Colors come from the active Omarchy theme; it is included last so it wins. `syml
|
||||
| `allow_remote_control` | `socket-only` |
|
||||
| `listen_on` | `unix:@kitty-{kitty_pid}` |
|
||||
| `enabled_layouts` | `splits:split_axis=vertical,stack` |
|
||||
| Tab bar | `powerline`, `angled`, aligned left, top edge, `tab_title_template "{custom}"` |
|
||||
| Tab bar | `powerline`, `slanted`, centered, top edge, always shown (`tab_bar_min_tabs 1`, so the stack-layout indicator is visible with one tab), `tab_title_template "{custom}"` |
|
||||
|
||||
:::note
|
||||
Transparency uses kitty's own alpha, so text stays opaque. This alpha is also what lets the compositor blur the window: Hyprland enables blur globally and opts out every window except terminal classes.
|
||||
@@ -86,7 +86,7 @@ The socket also exports `KITTY_LISTEN_ON` into each pane. nvim reads it to know
|
||||
| Key | Action |
|
||||
| --- | --- |
|
||||
| `super+n` | Vertical split 50/50 (`launch_vs50`) |
|
||||
| `super+z` | Toggle `stack` layout (zoom) |
|
||||
| `super+z` | Toggle `stack` layout (zoom); the tab title gains a layers icon and pane count (`nf-md-layers 3`) while other panes are hidden |
|
||||
| `ctrl+shift+t`, `super+enter` | New tab in current cwd |
|
||||
| `ctrl+space`, `ctrl+shift+j` | Horizontal split, 30% (`launch_hs`) |
|
||||
| `ctrl+enter`, `ctrl+shift+l` | Vertical split, 40% (`launch_vs`) |
|
||||
@@ -100,7 +100,6 @@ The socket also exports `KITTY_LISTEN_ON` into each pane. nvim reads it to know
|
||||
| `super+a` | Spawn a separate kitty (`--class=kitty-herdr`, `--config ~/.config/kitty/herdr.conf`) |
|
||||
| `ctrl+shift+c` / `ctrl+shift+v` | Copy / paste clipboard |
|
||||
| `alt+q w e r t y u i o` | Go to tab 1–9 |
|
||||
| `ctrl+shift+d` | `day_session.py` picker: reopen any archived day's session |
|
||||
| `ctrl+h/j/k/l` | `pass_keys.py`: move to neighbor window left/bottom/top/right, or pass the key through |
|
||||
| `super+left` / `super+right` | Resize window narrower / wider |
|
||||
| `super+up` / `super+down` | Resize window taller / shorter (by 3) |
|
||||
@@ -118,10 +117,12 @@ The tmux and herdr hosts are separate kitty processes because `launch` cannot ta
|
||||
|
||||
| Directive | Role |
|
||||
| --- | --- |
|
||||
| `geninclude day_session.py` | Creates today's (empty) session file and emits `startup_session <path>` whenever no running kitty owns today's session. Ownership is an `flock` on `$XDG_RUNTIME_DIR/kitty-day-<day>.kitty-session.lock`, held until that kitty exits, so closing kitty and launching it again always reopens the day, even if other kitties (or yesterday's) are still running. A second concurrent instance starts plain instead of duplicating today's tabs. |
|
||||
| `geninclude day_session.py` | Creates today's (empty) session file and emits `startup_session <path>` whenever no running kitty owns today's session. Ownership is an `flock` on `$XDG_RUNTIME_DIR/kitty-day-<day>.kitty-session.lock`, held until that kitty exits, so closing kitty and launching it again always reopens the day, even if other kitties (or yesterday's) are still running. A second concurrent instance starts plain instead of duplicating today's tabs. A kitty started with `--session` for another day never takes the lock. |
|
||||
| `watcher day_session.py` | About 1 s after a window opens, closes, resizes or splits, changes focus or finishes a command (catches `cd`), and every 30 s for output from long-running programs, rewrites the session this instance started with. Title changes are ignored so spinners don't trigger saves. Skips the save once the session has no windows, so closing kitty keeps the last good state. |
|
||||
| `map ctrl+shift+d kitten day_session.py` | Picker over every archived day, newest first; opens the choice with `goto_session`. Past days are snapshots: tabs opened from them are not saved back. |
|
||||
| `tab_bar_filter session:~ or session:^$` | Tab bar shows only the active day's tabs plus tabs outside any session. |
|
||||
|
||||
Earlier days open with the [`kitty-days`](/tools/television#kitty-days) tv cable (`tv kitty-days`), each in its own kitty (`kitty --session <file>`). A past day is a read-only snapshot: nothing in that kitty saves it back. Today's file opened that way, while no kitty owns it, becomes the live day again.
|
||||
|
||||
Before shutdown or reboot, the `kitty-day-save.service` user unit runs [`kitty-day-save`](/shell/scripts#kitty-day-save) under a logind delay inhibitor. On `PrepareForShutdown(true)` it sends `kitten day_session.py flush` to every `@kitty-<pid>` socket: the owning kitty saves at once (all windows are still alive), then skips saves for 60 s so windows dying during the shutdown can't shrink the file. [`30-user-services`](/chezmoi/scripts#30-user-services) enables the unit.
|
||||
|
||||
What a restored window gets back:
|
||||
|
||||
@@ -211,12 +212,12 @@ Kitten `ssh` config: for `hostname goliath`, `share_connections yes`.
|
||||
|
||||
| File | Purpose |
|
||||
| --- | --- |
|
||||
| `tab_bar.py` | Provides `draw_title` for `{custom}` in the tab template. Title is `<index> <icon> <label>`: the label is the git repo root name of the tab's cwd (walks up for `.git`), or the file nvim is editing (parsed from nvim's title). Icon comes from the foreground process cmdline (editors, AI agents like claude/omp/opencode/codex, git tools, docker, herdr, tmux, yazi, btop, atuin, ssh, chezmoi, …) with a folder fallback. Labels are elided at 28 chars. No subprocesses or timers. |
|
||||
| `tab_bar.py` | Provides `draw_title` for `{custom}` in the tab template. Title is `<index> <icon> <label>`: the label is the git repo root name of the tab's cwd (walks up for `.git`), or the file nvim is editing (parsed from nvim's title). Icon comes from the foreground process cmdline (editors, AI agents like claude/omp/opencode/codex, git tools, docker, herdr, tmux, yazi, btop, atuin, ssh, chezmoi, …) with a folder fallback. Labels are elided at 28 chars. In the `stack` layout with more than one pane, ` <nf-md-layers> <panes>` is appended; kitty repaints the tab bar on every layout change. No subprocesses or timers. |
|
||||
| `pass_keys.py` | Bound to `ctrl+h/j/k/l`. If the window's foreground process matches `vim`, `nvim`, `fzf`, `tv`, `tmux` or `herdr`, the key is forwarded; otherwise kitty moves to the neighboring window. |
|
||||
| `navigate_kitty.py` | No-UI kitten that calls `neighboring_window` with a direction argument; the counterpart nvim can invoke. Not mapped in `kitty.conf`. |
|
||||
| `select_tab.py` | Full-screen fuzzy tab picker using `kitty @ ls` data; shows cwds zsh-style. Keys: Up/Down/PgUp/PgDn scroll, Enter selects, typing filters, `ctrl+c`/Esc quits. Not mapped in `kitty.conf`. |
|
||||
| `switchtab.py` | Focuses the tab whose `vt` user var matches the argument, or launches one with that var and reorders tabs by `vt`. Not mapped. |
|
||||
| `window_titler.py` | Watcher that appends `[<vt> <pty>]` to window titles. Not referenced in `kitty.conf`. |
|
||||
| `day_session.py` | Daily sessions: `geninclude` script, global watcher and no-UI picker kitten in one file. See [Daily sessions](#daily-sessions). |
|
||||
| `day_session.py` | Daily sessions: `geninclude` script, global watcher and the `flush` no-UI kitten in one file. See [Daily sessions](#daily-sessions). |
|
||||
|
||||
Related: the [tmux](/terminal/tmux) `is_vim` check and herdr's `vim-herdr-navigation` plugin complete the `ctrl+h/j/k/l` chain. Niri window rules match the `kitty`, `kitty-tmux` and `kitty-herdr` app-ids ([Niri](/desktop/niri)).
|
||||
@@ -76,6 +76,7 @@ Every custom cable except `agents` (a fixed list, see [agents](#agents)), `omp-s
|
||||
| [`agents`](#agents) | `cable/agents.toml` | `tv agents` |
|
||||
| [`omp-sessions`](#omp-sessions) | `cable/omp-sessions.toml` | `tv omp-sessions`, <kbd>ctrl-a</kbd> (`omp-session`) when it has nothing to resume |
|
||||
| [`jobs`](#jobs) | `cable/jobs.toml` | <kbd>ctrl-z</kbd> in fish (`_jobs_bind`) with two or more background jobs |
|
||||
| [`kitty-days`](#kitty-days) | `cable/kitty-days.toml` | `tv kitty-days` |
|
||||
|
||||
The keys are bound in fish (`fish_user_key_bindings.fish`), zsh (`keybinds.zsh`), and bash (`keybinds.bash`); bash has no <kbd>ctrl-a</kbd> binding, and <kbd>ctrl-z</kbd> is fish only. See [fish](/shell/fish#key-bindings) and [bash and zsh](/shell/bash-zsh).
|
||||
|
||||
@@ -171,3 +172,14 @@ The preview finds the job's processes by process group (procps `ps -g` matches s
|
||||
| <kbd>ctrl-d</kbd> | `kill` then `reload_source`: SIGTERM to the job's process group, then SIGCONT so a stopped job receives it. Once the group is gone (polled up to 1 s) the row is removed from `$TV_JOBS`, so the reloaded list drops it; a job that ignores SIGTERM stays listed. Fish reports the termination at the next prompt |
|
||||
|
||||
**Needs:** `ps`, fish.
|
||||
|
||||
### kitty-days
|
||||
|
||||
Lists the daily kitty sessions that `~/.config/kitty/day_session.py` saves under `~/.local/share/kitty-sessions/<monday>/<day>.kitty-session` ([kitty daily sessions](/terminal/kitty#daily-sessions)). Entries are `<day> <weekday> week of <monday> <n> tabs<TAB><session file>`, through `mtime-sort`. The preview parses the session file with an inline `python3` script (written without braces, which tv would treat as templates): each tab, then each window's cwd and the program it restores, with the last 6 lines of its saved scrollback in color.
|
||||
|
||||
| Key | Action |
|
||||
| --- | --- |
|
||||
| <kbd>enter</kbd> | `open`: `setsid -f kitty --session <file>`, a new kitty with that day's tabs, scrollback and programs. Past days are read-only snapshots; today's file comes back as the live day if no kitty owns it |
|
||||
| <kbd>ctrl-e</kbd> | `edit`: the session file in `nvim` |
|
||||
|
||||
**Needs:** `kitty`, `python3`, `mtime-sort`.
|
||||
Reference in new issue
Block a user