diff --git a/docs/shell/scripts.md b/docs/shell/scripts.md index 712c0de..11faa66 100644 --- a/docs/shell/scripts.md +++ b/docs/shell/scripts.md @@ -441,7 +441,7 @@ The project root is the git toplevel, else the pane's directory. **Background.** Long-running items, marked `· background`, are ` run dev`, `docker compose up`, and pj tasks named `dev`/`start`/`serve`/`watch`/`preview` or with one of those as a `:` segment (`dev:web`, `api:dev`). They run through `--bg` in a detached session named `:` (`leetcode:bun-run-dev`, `leetcode:docker-compose-up`), shown in a rounded 90%×80% popup attached to it. q detaches the popup and leaves the task running: the session's `key-table` is `pj-task`, which binds only `q` and ctrl-c, so other keys reach the task instead of root-table bindings (prefix bindings still work). ctrl-c runs `confirm-before` (`Stop ? (y/n)`); y sends ctrl-c to the task, which stops it and ends the session, closing the popup, and any other key cancels. If the task exits on its own, the `[exit N]` prompt keeps its output until enter. Picking the item again, or its **Running** entry, reopens the popup instead of starting a second copy. The session has `status off`, `detach-on-destroy on`, and `@pj_task` set to the task's root, which is how the Running group finds it. Session names contain `:`, so the script targets them by id (`$N`). -**omp.** tmux `prefix a` runs `pj-palette --bg :omp omp`, so omp gets the same kind of background session and Running entry. Its popup docks in the bottom-right corner of the client, 35% wide and 60% tall. omp runs directly (no `[exit N]` prompt) and needs q, so its session uses the `pj-app` key table instead: ctrl-c hides the popup, ctrl-q kills the session (quits omp). `prefix a` inside any session with `@pj_task` also hides, which makes `prefix a` a toggle. The popup border shows only the session name. (Ghostty ctrl+shift+a opens the [Workmux palette](#workmux-palette) instead.) +**omp.** tmux `prefix a` runs `pj-palette --bg :omp omp`, so omp gets the same kind of background session and Running entry. Its popup docks in the bottom-right corner of the client, 35% wide and 60% tall. omp runs directly (no `[exit N]` prompt) and needs q, so its session uses the `pj-app` key table instead: ctrl-c hides the popup, ctrl-q kills the session (quits omp). `prefix a` inside any session with `@pj_task` also hides, which makes `prefix a` a toggle. The popup border shows only the session name. (Ghostty ctrl+shift+a toggles the workmux agent sidebar instead.) **omp palette.** `--omp` feeds `palettes/omp.json`, opened by the main palette's **omp** item. It lists every running `:omp` across tmux sessions, with a green icon and `open`/`hidden` state: **This session** first (or a grey `not running · start in ` item that starts it), then **Running** for the other tmux sessions' agents, then a **Quit** item per session (`kill-session`). @@ -486,7 +486,7 @@ workmux-palette --popup DIR CMD… workmux-palette --do DIR CMD… ``` -The source of the **Workmux** [tmux command palette](../terminal/tmux.md#command-palette) (`palettes/workmux.json`) for [workmux](../tools/workmux.md). Open it with tmux `prefix w`, Ghostty ctrl+shift+a, or the "Workmux" item in the main palette. +The source of the **Workmux** [tmux command palette](../terminal/tmux.md#command-palette) (`palettes/workmux.json`) for [workmux](../tools/workmux.md). Open it with tmux `prefix w`, ctrl+s in a workmux sidebar pane, or the "Workmux" item in the main palette. With no arguments it prints palette items as JSON, grouped by category: @@ -495,7 +495,7 @@ With no arguments it prints palette items as JSON, grouped by category: | Agents | Every agent `workmux status --all --json` tracks in this tmux server: waiting (yellow), done (green), working (blue), then idle, most recent first. Title `/`, description status, time since the change, and the pane title | `switch-client` to the agent's pane | | Worktrees: `` | The active pane's repo's worktrees (`workmux list --json`, main checkout left out): branch, open/closed, dirty, path. Open ones are green | `workmux open` (starts the session if closed) | | New | **New worktree from a prompt**, when the pane is in a repo | `--prompt` in a popup: `gum write` for the task, then `workmux add -A -p TASK` (omp names the branch, see [workmux](../tools/workmux.md#branch-names)) | -| Workmux | **Dashboard** (90% popup), **Sidebar** (toggle; also tmux `prefix S`, Ghostty ctrl+shift+s), **Last done** (`workmux last-done`) | | +| Workmux | **Dashboard** (90% popup), **Sidebar** (toggle; also tmux `prefix S`, Ghostty ctrl+shift+a / ctrl+shift+s), **Last done** (`workmux last-done`) | | | Close | One per open worktree | `workmux close`: ends the session, keeps worktree and branch | | Merge | One per worktree | `workmux merge` in a popup | | Remove | One per worktree | `workmux remove` in a popup (asks before deleting unmerged commits) | diff --git a/docs/terminal/ghostty.md b/docs/terminal/ghostty.md index 339cb09..a0b6c4c 100644 --- a/docs/terminal/ghostty.md +++ b/docs/terminal/ghostty.md @@ -67,7 +67,6 @@ Closing a window only detaches its session; the shells keep running in the tmux | `ctrl+shift+t` | `prefix c` | New window (tab) in pane cwd | | `ctrl+shift+p` / `ctrl+shift+space` | `prefix t` | Project Tasks palette (pj: install, dev, sync, make, every project task) | | `ctrl+backspace` | `prefix E` | [tmux-expose](tmux.md#keybindings): live thumbnails of every session; `ctrl+backspace` again closes it | -| `ctrl+shift+a` | `prefix w` | [Workmux palette](../shell/scripts.md#workmux-palette): agents by status, worktrees, new worktree from a prompt | | `ctrl+shift+f` | `prefix y` | Yazi in a new window, pane cwd | | `ctrl+shift+e` | `prefix BSpace` | Toggle the [treemux](tmux.md#treemux-file-tree-sidebar) Neo-tree sidebar and focus it | | `ctrl+shift+g` | `prefix g` | Lazygit in a 90% popup, pane cwd | @@ -84,7 +83,7 @@ Closing a window only detaches its session; the shells keep running in the tmux | `ctrl+shift+/` | `prefix ?` | Keybinding help popup | | `ctrl+shift+alt+,` | `prefix q` | Reload tmux config | | `ctrl+shift+n` | `prefix C` | New session | -| `ctrl+shift+s` | `prefix S` | Toggle the [workmux](../tools/workmux.md) agent sidebar (all sessions); the session/window tree stays on `prefix s` | +| `ctrl+shift+a`, `ctrl+shift+s` | `prefix S` | Toggle the [workmux](../tools/workmux.md) agent sidebar (all sessions); the session/window tree stays on `prefix s`. The [Workmux palette](../shell/scripts.md#workmux-palette) has no chord: `prefix w`, or `ctrl+s` inside the sidebar | | `ctrl+shift+q` | `prefix d` | Detach (closes the Ghostty window; the session lives on) | ## Themes diff --git a/docs/terminal/tmux.md b/docs/terminal/tmux.md index 3a1b5ce..bd3a23a 100644 --- a/docs/terminal/tmux.md +++ b/docs/terminal/tmux.md @@ -18,7 +18,7 @@ The prefix is `ctrl+b` (the byte Ghostty's `ctrl+shift` chords send). `ctrl+spac | Option | Value | | --- | --- | -| `default-command` | `exec fish -l`, or the login shell (`$SHELL -l`) where fish is missing. `default-shell` stays the login shell (bash), so `run-shell`, `if-shell` and `#()` jobs keep running under a POSIX shell | +| `default-command` | `exec fish -l`, or the login shell (`$SHELL -l`) where fish is missing. `default-shell` is `/bin/sh`, so `run-shell`, `if-shell`, `#()` jobs, popups and `split-window` commands run under a POSIX shell. Left to the login shell (fish), each of those paid `fish -c`'s ~55 ms config load and could not parse the sh syntax they are written in | | `default-terminal` | `tmux-256color`; `RGB` override for every terminal; `clipboard` and `hyperlinks` (OSC 8) features; `extkeys` for xterm-kitty. Features apply after `tmux kill-server` | | `extended-keys` | `on`, format `csi-u` | | `base-index` / `pane-base-index` | `1` / `1`; `renumber-windows on` | @@ -44,8 +44,8 @@ These settings are what [yazi](../tools/yazi.md) needs inside tmux. `allow-passt | `prefix o` | Sessions palette ([`tmux-sessions`](../shell/scripts.md#tmux-sessions)): fuzzy-find the other sessions, every window of every session, zoxide's and `~/.config`'s directories, and Rename/Kill items per session. Typed text that is not a session starts one by that name in its zoxide match | | `prefix E` | [tmux-expose](https://github.com/cesarferreira/tmux.expose) (cargo crate `tmux-expose`) in a full-screen popup, Ghostty `ctrl+backspace`: every session as a live, color-preserving thumbnail; arrows or click to select, typing fuzzy-filters, `Enter` switches, `Esc` closes. The popup gets `TMUX_EXPOSE_TOGGLE_KEY=E`, so pressing the chord again closes it unless you are typing a filter. Cards use cyberdream colors (selected `#5ea1ff`, attached `#5eff6c`, others `#7b8496`). Replaces tmux's `prefix E` (`select-layout -E`) | | `prefix t` | Project Tasks palette ([`pj-palette`](../shell/scripts.md#pj-palette)): install/dev/sync/make/compose quick actions plus every `pj` task. One-off tasks run in a full-width bottom split (25% of the window); dev servers and `docker compose up` run in a background `:` session shown in a popup (`q` hides, `ctrl-c` asks `y/n` then stops), listed under Running to reopen | -| `prefix w` | Workmux palette ([`workmux-palette`](../shell/scripts.md#workmux-palette)), Ghostty `ctrl+shift+a`: tracked agents by status, the repo's worktrees with Close/Merge/Remove, new worktree from the typed branch or a prompt, dashboard, sidebar, last-done. Replaces tmux's `choose-tree`, which the Sessions palette covers. See [workmux](../tools/workmux.md) | -| `prefix S` | Toggle workmux's live agent sidebar in every session (`workmux sidebar`), Ghostty `ctrl+shift+s`. tmux's session tree stays on `prefix s` | +| `prefix w` | Workmux palette ([`workmux-palette`](../shell/scripts.md#workmux-palette)), or `ctrl+s` in a workmux sidebar pane: tracked agents by status, the repo's worktrees with Close/Merge/Remove, new worktree from the typed branch or a prompt, dashboard, sidebar, last-done. Replaces tmux's `choose-tree`, which the Sessions palette covers. See [workmux](../tools/workmux.md) | +| `prefix S` | Toggle workmux's live agent sidebar in every session (`workmux sidebar`), Ghostty `ctrl+shift+a` or `ctrl+shift+s`. tmux's session tree stays on `prefix s`. In a sidebar pane, `ctrl+q` (root table) runs `workmux sidebar off`, closing every sidebar without workmux's "Quit sidebar?" prompt (workmux reads `ctrl+q` as `q`, which prompts, and has no option to skip it); other panes get `ctrl+q` unchanged. In a sidebar pane, `ctrl+g` opens `workmux dashboard` in a 90% popup (the sidebar would read it as `g`, jump to top); other panes get `ctrl+g` unchanged (nvim's git prefix). `ctrl+s` there opens the Workmux palette (the sidebar would read it as `s`, fold the group); other panes get `ctrl+s` unchanged | | `prefix y` / `prefix e` | Yazi / Neovim in a new window in the pane cwd (Ghostty `ctrl+shift+f`; `prefix e` has no chord) | | `prefix BSpace` / `prefix Tab` | Toggle the [treemux](#treemux-file-tree-sidebar) Neo-tree sidebar and focus it / keep focus in the pane (Ghostty and kitty-tmux `ctrl+shift+e` send `prefix BSpace`) | | `prefix g` | Lazygit in a 90% popup in the pane cwd (Ghostty `ctrl+shift+g`) | @@ -99,11 +99,11 @@ A window whose agent workmux tracks shows its status icon after the label (`#{@w | `tmux-plugins/tmux-resurrect` | `@resurrect-capture-pane-contents on` | | `tmux-plugins/tmux-continuum` | `@continuum-save-interval 10`, `@continuum-restore on` | | `prdlk/tmux-palette-plugin` | Fork of [eduwass/tmux-palette](https://github.com/eduwass/tmux-palette) that adds a custom palette `query` item (an item for the typed text, listed after the matches). `@palette-key C-Space` (root table, no prefix). Needs [Bun](https://bun.sh); tpm runs `bun install` on first load | -| `kiyoon/treemux` | Neo-tree sidebar, see [below](#treemux-file-tree-sidebar). `@treemux-tree-client neo-tree`, `@treemux-tree-position right`, `@treemux-tree-width 32`, `@treemux-nvim-command "NVIM_APPNAME=nvim-treemux nvim -u $HOME/.config/tmux/treemux_init.lua"`, `@treemux-refresh-interval-inactive-window 5` | +| `prdlk/treemux` | Fork of [kiyoon/treemux](https://github.com/kiyoon/treemux) whose right sidebar is a full-height column at the window's right edge, see [below](#treemux-file-tree-sidebar). `@treemux-tree-client neo-tree`, `@treemux-tree-position right`, `@treemux-tree-width 32`, `@treemux-nvim-command "NVIM_APPNAME=nvim-treemux nvim -u $HOME/.config/tmux/treemux_init.lua"`, `@treemux-refresh-interval 0.1` | ### treemux (file tree sidebar) -[treemux](https://github.com/kiyoon/treemux) opens a Neo-tree file explorer in a 32-column pane (the old in-nvim Neo-tree width; at most half the pane) right of the current one. It is the only file tree: nvim has Neo-tree disabled. `prefix BSpace` (Ghostty / kitty-tmux `ctrl+shift+e`) toggles it and moves focus into it; `prefix Tab` toggles it and leaves focus where it was. In nvim, `ctrl+e` focuses the window's sidebar (whichever pane it belongs to) or opens one; in the tree, `ctrl+e` goes back to the editor and `Q`, `ctrl+q`, `ZZ` or `alt+q` close it. The tree's root is the pane's git root (else its cwd), and it follows the shell: a `cd` reveals the new directory, and leaving the root re-roots the tree. The width is the same for every root: treemux's per-root width memory (`~/.local/share/tmux/treemux/directory_widths.txt`) is a symlink to `/dev/null`, created by `tmux.conf`, since treemux has no option to turn it off. +[treemux](https://github.com/kiyoon/treemux) opens a Neo-tree file explorer in a 32-column pane (the old in-nvim Neo-tree width; at most half the pane) at the window's right edge, spanning its full height, like workmux's agent sidebar on the left. The [prdlk/treemux](https://github.com/prdlk/treemux) fork creates it with `split-window -hf` (upstream splits the current pane, so it could land mid-window), and its `scripts/anchor_sidebar.sh` runs from global hooks (`after-split-window`, `after-select-layout`, `after-kill-pane`, `pane-exited`, index 73) to move it back to the edge and to 32 columns when a full-width split (pj-palette's task split), a new layout or a closing neighbour disturbs it; a manual `alt+h/l` resize lasts until the next such event. It is the only file tree: nvim has Neo-tree disabled. `prefix BSpace` (Ghostty / kitty-tmux `ctrl+shift+e`) toggles it and moves focus into it; `prefix Tab` toggles it and leaves focus where it was. In nvim, `ctrl+e` focuses the window's sidebar (whichever pane it belongs to) or opens one; in the tree, `ctrl+e` goes back to the editor and `Q`, `q`, `ctrl+q`, `ZZ` or `alt+q` close it (from any buffer there, not only the tree; they kill the pane directly, ~10 ms). The tree's root is the pane's git root (else its cwd), and it follows the shell: a `cd` reveals the new directory, and leaving the root re-roots the tree. The width is the same for every root: treemux's per-root width memory (`~/.local/share/tmux/treemux/directory_widths.txt`) is a symlink to `/dev/null`, created by `tmux.conf`, since treemux has no option to turn it off. In the tree, `Enter` opens a file in the nvim already running in the window ([nvim-tree-remote.nvim](https://github.com/kiyoon/nvim-tree-remote.nvim)), else in a new nvim split above the shell's pane (70%, focus moves to it; later files open in that same nvim), `t` opens it in the shell's pane without a split, `-` / `_` send the quoted absolute path under the cursor to the shell's pane with / without Enter (`N-` sends to pane N of the window instead), and `ctrl+_` copies it to a tmux buffer to paste with `prefix ]` ([tmux-send.nvim](https://github.com/kiyoon/tmux-send.nvim)). `ctrl+h/j/k/l` and `alt+h/j/k/l` leave and resize the sidebar like any nvim pane (smart-splits sets `@pane-is-vim`). @@ -111,7 +111,7 @@ The editor's keymap works in the tree. At startup the tree reads every normal-mo The sidebar's nvim runs `~/.config/tmux/treemux_init.lua` under `NVIM_APPNAME=nvim-treemux`, so its plugins, lockfile and state stay in `~/.local/share/nvim-treemux` and never touch the editor's `lazy-lock.json`. The init holds the whole Neo-tree setup (the editor no longer has one) and takes its filters from the editor's `config.ignore_patterns` (`~/.config/nvim/lua`, also used by the snacks pickers). Every plugin the editor also uses (smart-splits, snacks, cyberdream, mini.icons, plenary, nui) is pinned to the editor's `lazy-lock.json` commit; after `:Lazy update` in the editor, run `:Lazy sync` in the tree. Sidebar-specific choices: the root node is shown, `follow_current_file` and netrw hijacking are off. treemux reveals the cwd and, when the cursor misses it, assumes the directory is filtered and turns hidden files on; a hidden root node always misses. `follow_current_file` chased the directory buffer treemux starts nvim on and overflowed the stack. The colorscheme is cyberdream (muted, transparent). -Requirements: `python-pynvim` for `/usr/bin/python3` (treemux's default; the mise python on `PATH` has no pynvim) and `lsof`, both in `arch.pacman`. On the right, treemux drops `@treemux-tree-nvim-init-file`, so the `-u` init file is part of `@treemux-nvim-command`, which treemux pastes unquoted into a shell line (no spaces or commas in the path). `@treemux-refresh-interval-inactive-window` is set explicitly because treemux's default for it resolves to the option's name, which made the watcher's `sleep` fail and spin while another window was active. The first toggle on a new machine installs the tree's plugins. +Speed: opening takes ~100 ms to the drawn tree, closing ~10 ms, and a `cd` in the shell shows in the tree within ~40-110 ms (`@treemux-refresh-interval 0.1` while the shell or tree is focused; 2 s / 5 s otherwise). The fork's watcher reads the shell's cwd from `/proc` (`lsof` only where there is none), starts no process on an idle tick (inode comparison, `kill -0`, a `read -t` sleep, tmux asked for focus once a second), and moves the tree through `scripts/tree/follow.lua` over `nvim --server --remote-expr` (~2 ms) instead of upstream's Python/pynvim helpers (~60 ms each), so treemux needs neither pynvim nor `lsof`. smart-splits loads after the first paint. On the right, treemux drops `@treemux-tree-nvim-init-file`, so the `-u` init file is part of `@treemux-nvim-command`, which treemux pastes unquoted into a shell line (no spaces or commas in the path). The first toggle on a new machine installs the tree's plugins. ### Command palette @@ -122,7 +122,7 @@ Requirements: `python-pynvim` for `/usr/bin/python3` (treemux's default; the mis | `commands.json` | The kitty launchers ported as palette items: **Lazygit** (90% popup in the pane's cwd; kitty `ctrl+shift+g`), **Yazi** (new window; kitty `ctrl+shift+f`), **Neovim Split** (nvim in a split to the left, 60% of the pane; alias `nv`; kitty `ctrl+shift+e`), **Shell History (atuin)** (`atuin-pick` in a 25% split below; kitty `ctrl+shift+p`). Also **btop** (80% popup; aliases `top`, `htop`), **Lazydocker** (90% popup in the pane's cwd; alias `dd`), **mandible** (80% popup running [`mandible-pick`](../shell/scripts.md#mandible-pick); alias `man`), **television** (`tv channels`, the [channel picker](../tools/television.md), in a new window in the pane's cwd; alias `tv`), **gitframe** (git diff viewer in a new window in the pane's cwd; alias `gf`), **omp** (opens the omp palette; aliases `agent`, `ai`), **Workmux** (opens the workmux palette; aliases `wm`, `worktree`), **Project Tasks** (opens the tasks palette), **Sessions** (opens the sessions palette; aliases `sx`, `ss`), **Save Sessions**, and **Restore Sessions** (resurrect). Programs are started with `exec`, so the tab icon is the program's, not the shell's | | `palettes/tasks.json` | The **Project Tasks** palette (`prefix t`, Ghostty `ctrl+shift+p` / `ctrl+shift+space`), fed by [`pj-palette`](../shell/scripts.md#pj-palette): running background tasks under Running, then `bun install`, `bun run dev`, `uv sync`, `uv run python`, `make`, `go run .`, `cargo run`, `docker compose up` as Quick items when the project has them, then every task `pj` finds, grouped by tool. One-off tasks run in a full-width split along the bottom (25% of the window) in their directory; `ctrl-c` stops a running task, and once it has exited, `enter` or `ctrl-c` closes the pane. Dev servers (`dev`/`start`/`serve`/`watch`/`preview` tasks) and `docker compose up` run in a background session `:` shown in a popup: `q` hides it with the task still running, `ctrl-c` asks `Stop ? (y/n)` and on `y` stops the task and closes it | | `palettes/omp.json` | The **omp** palette, fed by [`pj-palette --omp`](../shell/scripts.md#pj-palette): this tmux session's `:omp` (open it, or start it when not running), every other tmux session's running omp, and a Quit item per session. Running agents have a green icon and show `open` or `hidden` | -| `palettes/workmux.json` | The **Workmux** palette (`prefix w`, Ghostty `ctrl+shift+a`), fed by [`workmux-palette`](../shell/scripts.md#workmux-palette): Agents (by status), Worktrees of the pane's repo, New, Workmux tools, Close, Merge, Remove. Its `query` item lists the typed text last; `enter` on it runs `workmux-palette --add ` (new worktree and session for that branch) | +| `palettes/workmux.json` | The **Workmux** palette (`prefix w`, or `ctrl+s` in a workmux sidebar pane), fed by [`workmux-palette`](../shell/scripts.md#workmux-palette): Agents (by status), Worktrees of the pane's repo, New, Workmux tools, Close, Merge, Remove. Its `query` item lists the typed text last; `enter` on it runs `workmux-palette --add ` (new worktree and session for that branch) | | `palettes/sessions.json` | The **Sessions** palette (`prefix o`, Ghostty `ctrl+shift+o`), fed by [`tmux-sessions`](../shell/scripts.md#tmux-sessions): Sessions (the last one first, attached ones green), Windows, Zoxide, Config, Rename, Kill. Its `query` item lists the typed text last; `enter` on it runs `tmux-sessions --new ` | | `hidden.json` | Hides the built-in **Switch Theme...** item, and with it the Appearance section: the palette stays on the fixed cyberdream `theme.json` | | `shortcuts.json` | Ghostty `ctrl+shift` chords shown next to the built-in items they trigger (New Window → `Ctrl+Shift+T`, …) | diff --git a/docs/tools/workmux.md b/docs/tools/workmux.md index 3fcede4..246f489 100644 --- a/docs/tools/workmux.md +++ b/docs/tools/workmux.md @@ -2,7 +2,7 @@ workmux global config: one git worktree and one tmux session per agent, driven from the Workmux palette. -[workmux](https://workmux.dev) pairs each git worktree with a tmux target and starts an agent in it. Here every worktree gets its own tmux session (an omp window and an nvim window), and the [Workmux palette](../shell/scripts.md#workmux-palette) (Ghostty `ctrl+shift+a`, tmux `prefix w`, or `ctrl+space` → Workmux) covers the lifecycle: open, new, close, merge, remove, and jumping to agents by status. +[workmux](https://workmux.dev) pairs each git worktree with a tmux target and starts an agent in it. Here every worktree gets its own tmux session (an omp window and an nvim window), and the [Workmux palette](../shell/scripts.md#workmux-palette) (tmux `prefix w`, `ctrl+s` in the agent sidebar, or `ctrl+space` → Workmux) covers the lifecycle: open, new, close, merge, remove, and jumping to agents by status. | | | | --- | --- |