all repos — dot @ dec2702337924b9a004acf2afa7574f95d349077

Shell, editor and terminal configuration, and the tools that go with them

link: a part named in ~/.config/dot/skip does nothing on that machine

A machine may need one of the parts left out: on a laptop it does not own,
~/.claude/settings.json is the owner's, holding their environment and plugins,
and linking this account's over it is wrong in both directions -- theirs is
lost, and anything of theirs worth keeping would have to be carried here, in
the repo every machine shares.

The file is hand-written and in no repo, like ~/.localenv, so the exception
stays on the machine that needs it. The check is in link/lib.sh, as each part
starts, rather than in link.sh's loop, so `link/claude.sh yes` obeys it too;
link.sh and other repos' link.sh source that file as well, and sit outside
link/, so their names can never be read as a part's.
Igor Soarez igor@soarez.org
Mon, 21 Sep 2026 14:09:58 +0300
commit

dec2702337924b9a004acf2afa7574f95d349077

parent

fec40208281589b70228802914e98b3b4823924b

3 files changed, 30 insertions(+), 0 deletions(-)

jump to
M CLAUDE.md → CLAUDE.md

@@ -129,6 +129,8 @@ The repository uses a centralized linking system where `link.sh` creates symlinks from `config/` files to their expected locations in `$HOME` and `$XDG_CONFIG_HOME`. This allows version control of dotfiles while maintaining standard file locations.

`link.sh` holds only the plain one-line links. Anything with logic of its own is a part in `link/` (`ssh`, `claude`, `pi`, `skills`, `icloud`, `hammerspoon`, `kwin`): a script with the same `[yes]` dry-run interface that decides for itself whether it applies, and can be run alone (`link/ssh.sh yes`). Shared helpers are in `link/lib.sh`. New logic goes in a part, not in `link.sh`. +A part named in `~/.config/dot/skip`, one per line, does nothing on that machine — whether it is reached through `link.sh` or run on its own. That file is hand-written and in no repo, like `~/.localenv`: it is for a machine where a part would do the wrong thing, such as one whose `~/.claude/settings.json` belongs to its owner rather than to this account, and it keeps that machine's exception out of this repo, which every machine shares. + ### Theme System A sophisticated theming system managed by `bin/theme` coordinates color schemes across multiple applications: - Supports both light and dark modes
M link.sh → link.sh

@@ -58,6 +58,8 @@ then

DOT_LINK_LIB="$dotfiles_dir/link/lib.sh" run_link "$cloud_setup/link.sh" fi +# A part named in ~/.config/dot/skip leaves this machine alone: link/lib.sh +# checks that as each part starts, so a part run on its own obeys it as well. for part in ssh claude pi skills icloud hammerspoon kwin do run_link "$dotfiles_dir/link/$part.sh"
M link/lib.sh → link/lib.sh

@@ -120,3 +120,29 @@ xdg_config_dir="${XDG_CONFIG_HOME:-$HOME/.config}"

# iCloud Drive, on a Mac signed into it; absent everywhere else. icloud_dir="$HOME/Library/Mobile Documents/com~apple~CloudDocs" + +# Machine-local opt-out: the name of a part, one per line, in +# ~/.config/dot/skip. For a machine where a part would do the wrong thing -- +# one whose ~/.claude/settings.json is its owner's rather than this account's, +# say -- without editing this repo, which every machine shares. Hand-written +# and in no repo, like ~/.localenv. +skip_file="$xdg_config_dir/dot/skip" + +part_skipped() { + # Whole-line match, so a blank or commented line cannot name a part. + [[ -r "$skip_file" ]] && grep -qxF "$1" "$skip_file" +} + +# A part skips itself here rather than in link.sh's loop, so that running one +# on its own (`link/claude.sh yes`) obeys the file too. Parts only: link.sh and +# other repos' link.sh source this as well, and sit outside link/, so their own +# names can never be read as a part's. +if [[ "$(basename "$(dirname "$(realpath "$0")")")" == "link" ]] +then + part_name="$(basename "$0" .sh)" + if part_skipped "$part_name" + then + yellow "link/$part_name.sh skipped by $skip_file" + exit 0 + fi +fi