Files
mesh-catalog/modules/zsh/README.md
T
mesh-tools 652b00b25b
mesh/merge-gate checking again: the gate refused `unknown` because the controller judged with a node-engine validator pinned before mesh-host #117; mesh-co…
mesh/repo-check checking again: the gate refused `unknown` because the controller judged with a node-engine validator pinned before mesh-host #117; mesh-co…
mesh/delivery-group group feat/owned-paths checking: 0 of 2 member(s) ready
mesh/delivery superseded: a newer head of the same pull request
Say on every directory how it treats files it does not know, and check it (issue 1024, ADR 0422)
Every directory and archive resource carries `unknown`: move-out for a home folder whose program writes nothing there (the node-engine, delivered in mesh-host #117, moves the rest to ~/.local/state/mesh-moved/<module>/ with a list), module for ~/.ssh and ~/.claude, program elsewhere; `knows` keeps what a program or the operator relies on (powerlevel10k's compiled files, i3's scripts and the asus/g14 drop-ins, dunst's slack rule, betterbird's records, node-env's forge credential, issue 1033). Two shared folders are no longer declared. Each module's README says it. checks/owned holds every manifest to it; checks/sshdir stays while main's merge check runs it (issue 1035). Tests that pin a manifest follow the new key only. Reviewed in three rounds.
2026-10-17 16:23:03 +00:00

103 lines
5.6 KiB
Markdown

# zsh
The login shell as a module (novox/hq ADR 0176, ADR 0204, to-be 41).
- Installs the `zsh` package and makes it the operator account's login shell through the `user`
shape. The host gives the found shell back when the module goes.
- Claims the mesh's `node-login-shell` seat and serves its verb `execute`: one command, run as the
account in a zsh login shell in the account's home. It is ended with everything it started after
20 s by default (25 s at most, below the runtime's 30 s call limit). Each stream is cut at 256 KiB
and the answer says so in `truncated`.
- **A machine may withhold `execute`** (hq ADR 0268). It runs any command as the operator account,
which can become root without a person. The setting `execute` is `serve` by default; a machine's
layer `withhold` (`mesh-controller.settings` with `module` zsh, `node` the machine, `values`
`{"execute":"withhold"}`, then a push) makes the runtime there offer no `execute` at all. The mesh
writes the value into a root-owned `tools.conf` in the module's directory, which the tools bundle
reads when the runtime starts it; a change restarts the runtime. Anything but `serve` (a wrong value,
no file) withholds it, and says why on stderr and in `zsh_config`'s `execute`. The control-node
withholds it until a call to it needs a person's approval (hq research 039).
- Its own tool `zsh_config` shows `~/.zshenv` and `~/.zshrc` as they are, with the mesh block's line
count in each, and whether this machine serves `execute`, and why.
- Contributes to the account's environment (ADR 0203): `EDITOR` and `VISUAL` (vim), `XDG_CONFIG_HOME`,
and `~/.local/bin`, `~/scripts`, `~/scripts/bin` at the start of `PATH`. The holder of
`node-environment` (`node-env`) writes them; this module writes no `export` of its own.
zsh owns no folder. It writes two blocks, one into `~/.zshrc` and one into `~/.zshenv`, and every line
outside them is the person's (ADR 0422, ADR 0416).
## The two blocks
Each block is the mesh's, between `# BEGIN mesh zsh.<id>` and `# END mesh zsh.<id>`. Every line
outside a block is yours, kept byte for byte, and given back when the module goes.
- **`~/.zshenv`, at the start:** sources `~/.config/mesh/environment.sh` if it is readable. Every zsh
reads this file: a login, a script, and `execute`.
- **`~/.zshrc`, at the start:** the defaults every machine shares, with the three slots other modules
fill (`first`, the defaults, `normal`, `last`). The defaults are the terminal title, seven
keybindings, the colour aliases, `ll`/`la`/`l`, `drun`, `disksize` and `sudo-disksize`. Your lines
below it run after it, so they win.
## The one-off migration (ADR 0182)
The mesh removes nothing it did not make. After the first push that assigns this module, the lines
below are in the block **and** in your own part of `~/.zshrc`. Until you delete your copies, they run
twice, which is harmless and visible. Deleting them is a person's act, once per machine.
**Delete once `zsh` is assigned.** The block or the environment now carries these:
1. `export EDITOR=vim`
2. `export VISUAL=vim`
3. `export XDG_CONFIG_HOME=$HOME/.config`
4. `export PATH="$HOME/.local/bin:$HOME/scripts:$HOME/scripts/bin:$HOME/.dotnet:$PATH"`. Keep the
one entry no module carries yet, as `export PATH="$HOME/.dotnet:$PATH"`.
5. The terminal title: `function set_terminal_title() { … }` and
`precmd_functions+=(set_terminal_title)`.
6. The seven `bindkey` lines (Home twice, Ctrl+A, End twice, Ctrl+E, Del).
7. `alias drun='docker run -it --rm'`, and the functions `disksize() { … }` and
`sudo-disksize() { … }`.
8. The `if [ -x /usr/bin/dircolors ]; then … fi` block, with its aliases `ls`, `dir`, `vdir`,
`grep`, `fgrep` and `egrep`.
9. `alias ll='ls -alhF'`, `alias la='ls -Ah'` and `alias l='ls -CFh'`.
**Delete once `powerlevel10k` is assigned.** Its contribution in the `normal` slot loads the prompt:
1. `#user_p10k_cache_file="${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${USER}.zsh"`, and the
`if [[ -r "$user_p10k_cache_file" ]]; then … fi` after it. It does nothing today, because the
variable is commented out.
2. `[[ ! -f ~/.zsh/themes/powerlevel10k/powerlevel10k.zsh-theme ]] || source …`
3. `[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh`
**Delete once `zsh-autosuggestions` / `zsh-syntax-highlighting` are assigned.** Each module loads
the distribution's copy from its own slot:
1. `[[ ! -f ~/.zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh ]] || source …`
2. `[[ ! -f ~/.zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh ]] || source …`
**What stays yours.** Keep these below the block until a module carries them:
- the `NVM_DIR` lines;
- `MY_KV_PATH` and `MY_LIB_PATH`;
- `CLAUDE_CODE_DISABLE_TERMINAL_TITLE`;
- the `killport` and `findport` aliases;
- the `zstyle` lines;
- the line sourcing `~/.zshrc.local`, and that file itself.
**Paths no longer used.** The predecessor cloned these and nothing of the mesh reads them. Remove
them by hand once the module that replaces each is assigned:
- `~/.zsh/themes/powerlevel10k`: replaced by `powerlevel10k`'s pinned copy in
`~/.local/share/powerlevel10k`;
- `~/.p10k.zsh`: replaced by `~/.config/powerlevel10k/p10k.zsh`, the same bytes, once
`powerlevel10k` is assigned;
- `~/.zsh/plugins/zsh-autosuggestions` and `~/.zsh/plugins/zsh-syntax-highlighting`: replaced by
the distribution's packages;
- `~/.zsh/plugins/zsh-autocomplete`: loaded by nothing today.
Anything else under `~/.zsh/` is yours.
## Files it does not know
Each directory or archive this module declares says how it treats a file it did not write (ADR 0422, ADR 0416).
- `${dir:state}`: everything in it is the program's; the mesh moves nothing out (ADR 0422 §2).