fix(zellij): repair scrollback logging on shell exit #55
@@ -66,13 +66,18 @@ This config captures terminal output to `~/.terminal_history` (override with
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Kitty scrollback | When a Kitty window/tab closes | `scrollback_<timestamp>.log` |
|
| Kitty scrollback | When a Kitty window/tab closes | `scrollback_<timestamp>.log` |
|
||||||
| tmux pane | Continuously while the pane is open (`pipe-pane`) | `tmux_<session>-w<win>-p<pane>_<timestamp>.log` |
|
| tmux pane | Continuously while the pane is open (`pipe-pane`) | `tmux_<session>-w<win>-p<pane>_<timestamp>.log` |
|
||||||
| zellij pane | Snapshot taken on shell exit (`dump-screen`) | `zellij_<session>-p<pane>_<timestamp>.log` |
|
| zellij pane | Snapshot taken on **clean** shell exit (`dump-screen`) | `zellij_<session>-p<pane>_<timestamp>.log` |
|
||||||
| `paru` wrapper | Every `paru` invocation | `paru_<timestamp>.log` |
|
| `paru` wrapper | Every `paru` invocation | `paru_<timestamp>.log` |
|
||||||
| `yay` wrapper | Every `yay` invocation | `yay_<timestamp>.log` |
|
| `yay` wrapper | Every `yay` invocation | `yay_<timestamp>.log` |
|
||||||
|
|
||||||
Old logs are pruned automatically to stay within `$SCROLLBACK_HISTORY_MAX_FILES`
|
Old logs are pruned automatically to stay within `$SCROLLBACK_HISTORY_MAX_FILES`
|
||||||
(default 100) per source, and empty/trivial captures are discarded.
|
(default 100) per source, and empty/trivial captures are discarded.
|
||||||
|
|
||||||
|
> **zellij caveat:** zellij has no continuous pipe like tmux, so its pane is
|
||||||
|
> snapshotted only on a clean shell exit (`exit`/Ctrl-D). Closing a pane or
|
||||||
|
> quitting zellij directly tears down the pane/server before it can be dumped,
|
||||||
|
> so those sessions are not logged. End with `exit` to guarantee a log.
|
||||||
|
|
||||||
**These logs can contain secrets** — anything printed to your terminal (command
|
**These logs can contain secrets** — anything printed to your terminal (command
|
||||||
output, file dumps, tokens echoed to stdout) ends up in them. They never leave
|
output, file dumps, tokens echoed to stdout) ends up in them. They never leave
|
||||||
your machine, but treat `~/.terminal_history` as sensitive.
|
your machine, but treat `~/.terminal_history` as sensitive.
|
||||||
|
|||||||
+45
-5
@@ -133,7 +133,9 @@ logging=## 5.11 Pager and Logging
|
|||||||
logs=### logs
|
logs=### logs
|
||||||
smart-exit=### smart_exit
|
smart-exit=### smart_exit
|
||||||
ai=## 5.12 AI and Developer Tools
|
ai=## 5.12 AI and Developer Tools
|
||||||
antigravity=### antigravity
|
antigravity=### antigravity-resume
|
||||||
|
antigravity-ide=### antigravity-ide
|
||||||
|
agy=### agy
|
||||||
claude-cli=### claude
|
claude-cli=### claude
|
||||||
claude=### claude-resume
|
claude=### claude-resume
|
||||||
claude-docs=### claude-docs
|
claude-docs=### claude-docs
|
||||||
@@ -155,7 +157,37 @@ joplin=### joplin
|
|||||||
replay=### replay
|
replay=### replay
|
||||||
tmux=### tmux-clean
|
tmux=### tmux-clean
|
||||||
wake-lock=### wake-lock
|
wake-lock=### wake-lock
|
||||||
zellij=### zellij
|
|
||||||
|
# ── Tool-name synonyms (replacement → shadowed command) ──────
|
||||||
|
# These tools don't appear in any heading, so the fallback scan can't
|
||||||
|
# find them; map each to the function that wraps it.
|
||||||
|
eza=### ls
|
||||||
|
exa=### ls
|
||||||
|
lsd=### ls
|
||||||
|
trash=### rm
|
||||||
|
btop=### top
|
||||||
|
prettyping=### ping
|
||||||
|
duf=### du
|
||||||
|
dust=### du
|
||||||
|
kitten=### ssh
|
||||||
|
bat=### cat
|
||||||
|
|
||||||
|
# ── Tool integrations (Section: Integrations) ────────────────
|
||||||
|
zoxide=### Zoxide
|
||||||
|
z=### Zoxide
|
||||||
|
direnv=### DirEnv
|
||||||
|
venv=### Auto Python Venv
|
||||||
|
virtualenv=### Auto Python Venv
|
||||||
|
python=### Auto Python Venv
|
||||||
|
wakatime=### WakaTime
|
||||||
|
tailscale=### Tailscale
|
||||||
|
done=### Done Notifications
|
||||||
|
notifications=### Done Notifications
|
||||||
|
notify=### Done Notifications
|
||||||
|
pager-hierarchy=## Pager Hierarchy
|
||||||
|
shell-aliases=## 4.11 Shell Aliases
|
||||||
|
kitty-logging=### kitty-logging
|
||||||
|
watcher=### kitty-logging
|
||||||
|
|
||||||
# ── Section 6: Dependency Catalog ────────────────────────────
|
# ── Section 6: Dependency Catalog ────────────────────────────
|
||||||
catalog=# 6. DEPENDENCY CATALOG
|
catalog=# 6. DEPENDENCY CATALOG
|
||||||
@@ -193,6 +225,11 @@ integrations-detail=#### C4 — Terminal and Tool Integration
|
|||||||
c5=#### C5 — Logging and Capture
|
c5=#### C5 — Logging and Capture
|
||||||
logging-detail=#### C5 — Logging and Capture
|
logging-detail=#### C5 — Logging and Capture
|
||||||
logging-sentinel=#### C5 — Logging and Capture
|
logging-sentinel=#### C5 — Logging and Capture
|
||||||
|
zellij=#### C5 — Logging and Capture
|
||||||
|
zellij-logging=#### C5 — Logging and Capture
|
||||||
|
tmux-logging=#### C5 — Logging and Capture
|
||||||
|
pipe-pane=#### C5 — Logging and Capture
|
||||||
|
dump-screen=#### C5 — Logging and Capture
|
||||||
c6=#### C6 — Greeting and First-Run UI
|
c6=#### C6 — Greeting and First-Run UI
|
||||||
greeting=#### C6 — Greeting and First-Run UI
|
greeting=#### C6 — Greeting and First-Run UI
|
||||||
|
|
||||||
@@ -225,13 +262,16 @@ updating=## Updating
|
|||||||
# ── Section 10: Personalization ───────────────────────────────
|
# ── Section 10: Personalization ───────────────────────────────
|
||||||
personalization=# 10. PERSONALIZATION
|
personalization=# 10. PERSONALIZATION
|
||||||
personalize=# 10. PERSONALIZATION
|
personalize=# 10. PERSONALIZATION
|
||||||
secrets=## secrets.fish
|
secrets-file=## secrets.fish
|
||||||
local-config=## local.fish
|
local-config=## local.fish
|
||||||
|
|
||||||
# ── Section 11: Viewing This Manual ──────────────────────────
|
# ── Section 11: Viewing This Manual ──────────────────────────
|
||||||
viewing=# 11. VIEWING THIS MANUAL
|
viewing=# 11. VIEWING THIS MANUAL
|
||||||
manual=# 11. VIEWING THIS MANUAL
|
manual=# 11. VIEWING THIS MANUAL
|
||||||
ov=## With ov (recommended)
|
ov=## With ov (recommended)
|
||||||
man-page=## As a man page (if compiled)
|
man-page=## As a man page
|
||||||
manpage=## As a man page (if compiled)
|
manpage=## As a man page
|
||||||
jump=## Jumping to a section
|
jump=## Jumping to a section
|
||||||
|
html=## In the browser (HTML)
|
||||||
|
browser=## In the browser (HTML)
|
||||||
|
wiki=## As a wiki
|
||||||
|
|||||||
+26
-11
@@ -1423,11 +1423,6 @@ Add -i (interactive confirmation) to destructive commands:
|
|||||||
|
|
||||||
wake-lock rsync -avz src/ dest/
|
wake-lock rsync -avz src/ dest/
|
||||||
|
|
||||||
### zellij
|
|
||||||
|
|
||||||
Synopsis: zellij [args...]
|
|
||||||
Launches zellij with the Catppuccin Mocha theme applied.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# 6. DEPENDENCY CATALOG
|
# 6. DEPENDENCY CATALOG
|
||||||
@@ -1750,12 +1745,32 @@ SCROLLBACK_HISTORY_MAX_FILES, matching the paru/yay wrapper behaviour.
|
|||||||
|
|
||||||
The zellij capture works differently: Zellij has no live output-streaming
|
The zellij capture works differently: Zellij has no live output-streaming
|
||||||
facility like pipe-pane, so the log is taken as a one-shot snapshot when the
|
facility like pipe-pane, so the log is taken as a one-shot snapshot when the
|
||||||
shell exits, via `zellij action dump-screen --full`. A fish_exit handler
|
shell exits, via `zellij action dump-screen --full --ansi` (the --ansi flag
|
||||||
(registered whenever $ZELLIJ is set) writes the pane's full scrollback and
|
preserves color). The dump is captured on the fish process's stdout and
|
||||||
then prunes old zellij_*.log files the same way. Because the capture happens
|
written to the log file by fish itself (not via `--path`, which would make the
|
||||||
at exit, toggling __fish_config_op_logging takes effect on the next exit with
|
zellij server write the file). A fish_exit handler (registered whenever
|
||||||
no restart or sentinel coordination needed — the C5 guard is re-checked when
|
$ZELLIJ is set) writes the pane's full scrollback and then prunes old
|
||||||
the handler fires.
|
zellij_*.log files the same way. Because the capture happens at exit, toggling
|
||||||
|
__fish_config_op_logging takes effect on the next exit with no restart or
|
||||||
|
sentinel coordination needed — the C5 guard is re-checked when the handler
|
||||||
|
fires.
|
||||||
|
|
||||||
|
LIMITATION — zellij capture only fires on a clean shell exit (typing `exit`,
|
||||||
|
Ctrl-D, or a logout), because that is when the fish_exit handler runs. It does
|
||||||
|
NOT capture when you close a pane or quit zellij through zellij itself:
|
||||||
|
|
||||||
|
- Closing a pane signals the shell and tears the pane down concurrently, so
|
||||||
|
even if the handler runs, `dump-screen` may find the pane buffer already
|
||||||
|
gone.
|
||||||
|
- Quitting zellij kills the zellij server, and `dump-screen` needs a live
|
||||||
|
server to read from — there is nothing left to snapshot.
|
||||||
|
|
||||||
|
This is a structural difference from tmux, NOT a bug. tmux streams pane output
|
||||||
|
to disk continuously via pipe-pane, so whatever was printed is already saved
|
||||||
|
no matter how the pane dies. Zellij can only snapshot, and the only reliable
|
||||||
|
snapshot point from the shell is a clean exit. To guarantee a zellij pane is
|
||||||
|
logged, end the session with `exit` or Ctrl-D rather than zellij's close-pane
|
||||||
|
or quit actions.
|
||||||
|
|
||||||
The Kitty watcher is managed by the kitty-logging command: it installs a
|
The Kitty watcher is managed by the kitty-logging command: it installs a
|
||||||
version-marked watcher (fish-config-watcher.py) into the Kitty config directory
|
version-marked watcher (fish-config-watcher.py) into the Kitty config directory
|
||||||
|
|||||||
@@ -34,7 +34,12 @@ function _zellij_dump_log --description 'Dump the current Zellij pane scrollback
|
|||||||
set -l log_file "$log_dir/zellij_"$session"-p"$pane_id"_"$timestamp".log"
|
set -l log_file "$log_dir/zellij_"$session"-p"$pane_id"_"$timestamp".log"
|
||||||
|
|
||||||
mkdir -p $log_dir
|
mkdir -p $log_dir
|
||||||
zellij action dump-screen --full "$log_file" 2>/dev/null
|
# Dump to STDOUT and let this fish process write the file. `--path` makes the
|
||||||
|
# zellij *server* write the file (its CWD/permissions, historically flaky);
|
||||||
|
# capturing STDOUT keeps the write client-side and reliable. Drop the empty
|
||||||
|
# file if the dump produced nothing (e.g. pane already torn down on exit).
|
||||||
|
zellij action dump-screen --full --ansi >"$log_file" 2>/dev/null
|
||||||
|
test -s "$log_file"; or command rm -f "$log_file"
|
||||||
|
|
||||||
_prune_terminal_logs zellij
|
_prune_terminal_logs zellij
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
# Copyright (C) 2026 Rootiest
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
||||||
|
|
||||||
# SYNOPSIS
|
|
||||||
# zellij [args...]
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
# Launches zellij with the Catppuccin Mocha theme applied via
|
|
||||||
# --theme catppuccin-mocha.
|
|
||||||
#
|
|
||||||
# ARGUMENTS
|
|
||||||
# args... Arguments forwarded to zellij
|
|
||||||
#
|
|
||||||
# EXAMPLE
|
|
||||||
# zellij
|
|
||||||
function zellij --wraps='zellij' --description 'alias zellij=zellij options --theme catppuccin-mocha'
|
|
||||||
command zellij options --theme catppuccin-mocha $argv
|
|
||||||
|
|
||||||
end
|
|
||||||
Reference in New Issue
Block a user