From 58d11f64d482756cd029235e418c8beac147c236 Mon Sep 17 00:00:00 2001 From: froppa-agent <330570035+froppa-agent@users.noreply.github.com> Date: Mon, 12 Oct 2026 22:05:11 +0200 Subject: [PATCH 1/6] refactor: limit dotfiles updater to configuration --- README.md | 14 +-- .../systemd/user/follow-main.service | 2 +- .../tmux/scripts/executable_agent-state.sh | 2 +- home/dot_local/bin/executable_follow-main.sh | 85 ++++++------------- test.sh | 2 +- 5 files changed, 37 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index 98fbbda..2ef7bfb 100644 --- a/README.md +++ b/README.md @@ -196,8 +196,8 @@ connection dropped, a crashed TUI), the next prompt switches mouse, focus, and extended-key reporting off again, so clicks stop typing escape sequences. The hooks also record each session's state under -`~/.cache/agents/claude-`, which Verk reads to list a waiting -terminal session in Today and in its menu bar. Outside tmux, the same hooks +`~/.cache/agents/claude-` for terminal status consumers. +Outside tmux, the same hooks retitle the Ghostty tab with the session's state and directory (`โŸณ repo` working, `? repo` waiting for you, `ยท repo` idle), Claude Code rings the terminal bell when it needs attention, and Ghostty marks the tab. Starship's right prompt shows the @@ -247,9 +247,13 @@ Machine-specific overrides use unmanaged `*.local` files such as `.gitconfig.local`. Depot is installed separately with Cargo from `struktly/tools`. The managed -`~/.local/bin/depot` link points to `~/.cargo/bin/depot`, replacing the legacy -Verk entry point. Zsh loads completion from the installed Depot version after -completion initialization; no generated completion file needs updating. +`~/.local/bin/depot` link points to `~/.cargo/bin/depot`. Zsh loads completion +from the installed Depot version after completion initialization; no generated +completion file needs updating. + +The Linux `follow-main.timer` updates only this repository's managed +configuration through Chezmoi. Application installation and deployment belong +to their own repositories and machine setup. ## Where things live diff --git a/home/dot_config/systemd/user/follow-main.service b/home/dot_config/systemd/user/follow-main.service index 21d77a7..ed08bf6 100644 --- a/home/dot_config/systemd/user/follow-main.service +++ b/home/dot_config/systemd/user/follow-main.service @@ -1,5 +1,5 @@ [Unit] -Description=Follow main: dotfiles through chezmoi, then Verk through its installer +Description=Update managed configuration through chezmoi After=network-online.target [Service] diff --git a/home/dot_config/tmux/scripts/executable_agent-state.sh b/home/dot_config/tmux/scripts/executable_agent-state.sh index 1469c0d..0124c2b 100755 --- a/home/dot_config/tmux/scripts/executable_agent-state.sh +++ b/home/dot_config/tmux/scripts/executable_agent-state.sh @@ -5,7 +5,7 @@ # off (session ended). # # The state lands in a per-session file under ~/.cache/agents, named by the -# Claude session id so Verk can join it to the transcript it already lists: +# Claude session id so consumers can correlate it with their own state: # line 1 the state, line 2 the CLI's pid (the hook runs as a child of the # claude process, so $PPID is the session), line 3 the working directory. It also goes on the tmux pane as # @agent_state when inside tmux, and into the terminal tab title through the diff --git a/home/dot_local/bin/executable_follow-main.sh b/home/dot_local/bin/executable_follow-main.sh index 84fe5c8..78a74cf 100755 --- a/home/dot_local/bin/executable_follow-main.sh +++ b/home/dot_local/bin/executable_follow-main.sh @@ -1,63 +1,28 @@ #!/usr/bin/env sh -# Keep a Linux workstation (evo-dev) on the tip of main without a person at -# the keyboard: dotfiles through chezmoi, then Verk through its own guarded -# installer. Run by follow-main.timer (~/.config/systemd/user); by hand: -# follow-main.sh # both -# follow-main.sh dotfiles # or: verk -# Nothing here forces anything. A dirty or non-master dotfiles checkout is -# reported and left alone, and Verk's install-linux.sh refuses under a -# running chat turn (exit 3) or another install (exit 4); the next tick tries -# again. Logs: journalctl --user -u follow-main. +# Keep managed configuration current on a Linux workstation. +# Run by follow-main.timer, or by hand with follow-main.sh [dotfiles]. +# Dirty or non-master checkouts are left alone. set -eu -what=${1:-all} - -dotfiles() { - src=$(chezmoi source-path)/.. - if [ -n "$(git -C "$src" status --porcelain)" ]; then - echo "dotfiles: $src has local changes; not pulling" >&2 - return 0 - fi - if [ "$(git -C "$src" branch --show-current)" != master ]; then - echo "dotfiles: $src is not on master; not pulling" >&2 - return 0 - fi - before=$(git -C "$src" rev-parse HEAD) - # Install scripts stay excluded on Linux, as at bootstrap: the account has - # no sudo and package installs belong to the evo development role. - chezmoi update --exclude=scripts - after=$(git -C "$src" rev-parse HEAD) - if [ "$before" != "$after" ]; then - echo "dotfiles: $before -> $after applied" - systemctl --user daemon-reload - fi -} - -verk() { - repo="$HOME/code/verk" - [ -d "$repo/.git" ] || return 0 - if [ -n "$(git -C "$repo" status --porcelain)" ]; then - echo "verk: $repo has local changes; not pulling" >&2 - return 0 - fi - git -C "$repo" pull -q --ff-only - head=$(git -C "$repo" rev-parse HEAD) - if [ "$head" = "$(cat "$HOME/.verk/installed.commit" 2>/dev/null)" ]; then - return 0 - fi - echo "verk: installing $head" - # Builds go through Depot's cache; mise supplies the pinned Go and Bun. - rc=0 - (cd "$repo" && mise exec -- depot exec -- ./scripts/install-linux.sh) || rc=$? - case $rc in - 0) ;; - 3 | 4) echo "verk: install refused (exit $rc); trying again next tick" ;; - *) echo "verk: install failed (exit $rc)" >&2; return "$rc" ;; - esac -} - -case $what in - all) dotfiles; verk ;; - dotfiles) dotfiles ;; - verk) verk ;; - *) echo "usage: follow-main.sh [all|dotfiles|verk]" >&2; exit 2 ;; +case ${1:-dotfiles} in + dotfiles) ;; + *) echo "usage: follow-main.sh [dotfiles]" >&2; exit 2 ;; esac +[ "$#" -le 1 ] || { echo "usage: follow-main.sh [dotfiles]" >&2; exit 2; } + +src=$(git -C "$(chezmoi source-path)" rev-parse --show-toplevel) +if [ -n "$(git -C "$src" status --porcelain)" ]; then + echo "dotfiles: $src has local changes; not pulling" >&2 + exit 0 +fi +if [ "$(git -C "$src" branch --show-current)" != master ]; then + echo "dotfiles: $src is not on master; not pulling" >&2 + exit 0 +fi +before=$(git -C "$src" rev-parse HEAD) +# Package installs remain a separate machine bootstrap step. +chezmoi update --exclude=scripts +after=$(git -C "$src" rev-parse HEAD) +if [ "$before" != "$after" ]; then + echo "dotfiles: $before -> $after applied" + systemctl --user daemon-reload +fi diff --git a/test.sh b/test.sh index 956de49..18b46d2 100755 --- a/test.sh +++ b/test.sh @@ -94,7 +94,7 @@ grep -q '^personal = false$' "${rendered_work_config}" || fail "WORK=true should section "Checking safe adoption defaults" [[ -f home/dot_local/bin/symlink_depot.tmpl ]] || fail "Depot must resolve to the standalone Cargo installation" -grep -Fq '".cargo/bin/depot"' home/dot_local/bin/symlink_depot.tmpl || fail "Depot link must not target the legacy Verk binary" +grep -Fq '".cargo/bin/depot"' home/dot_local/bin/symlink_depot.tmpl || fail "Depot link must target the standalone installation" grep -Fq 'source <(depot completions zsh 2>/dev/null)' home/dot_zsh_completions || fail "Depot completion must follow the installed version" [[ -f home/create_dot_gitconfig.tmpl ]] || fail "Git defaults must be create-only" From b11e313580be8cd3757e855182397d3cfb1ceaed Mon Sep 17 00:00:00 2001 From: froppa-agent <330570035+froppa-agent@users.noreply.github.com> Date: Mon, 12 Oct 2026 22:11:53 +0200 Subject: [PATCH 2/6] refactor: remove personal infrastructure hooks --- README.md | 12 +- home/.chezmoiignore | 4 +- .../run_after_60-add-herdr-evo-dev.sh.tmpl | 19 - .../iterm2/com.googlecode.iterm2.plist | 1138 ----------------- .../scripts/executable_quick-capture.sh | 145 --- home/dot_config/zed/private_settings.json | 35 +- scripts/export-iterm2-prefs.sh | 15 - test.sh | 8 +- tests/test_ubuntu_bootstrap.py | 3 +- 9 files changed, 15 insertions(+), 1364 deletions(-) delete mode 100644 home/.chezmoiscripts/run_after_60-add-herdr-evo-dev.sh.tmpl delete mode 100644 home/dot_config/raycast/scripts/executable_quick-capture.sh delete mode 100755 scripts/export-iterm2-prefs.sh diff --git a/README.md b/README.md index 2ef7bfb..71de3f5 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ sh -c "$(curl -fsLS get.chezmoi.io)" -- -b "$HOME/.local/bin" export PATH="$HOME/.local/bin:$PATH" git clone https://github.com/froppa/dotfiles.git ~/.local/share/chezmoi cd ~/.local/share/chezmoi -chezmoi init --source="$PWD" --promptString 'name=sdf' +chezmoi init --source="$PWD" --promptString 'name=YOUR_NAME' chezmoi diff chezmoi apply -v ``` @@ -131,7 +131,6 @@ load the key on first use. Shell startup does not call `ssh-add`. | Component | Once per machine | | --- | --- | | Raycast | Configure Caps Lock as Hyper (`Control+Option+Command`, no Shift) | -| Raycast scripts | Add `~/.config/raycast/scripts/` as a Script Command directory | | Neovim | Open once to finish Lazy, Mason, and tree-sitter setup | | Ghostty | Launched from the Dock or Raycast it has launchd's PATH, so name tmux's absolute path in `~/.config/ghostty/config.local`: `command = direct:/opt/homebrew/bin/tmux new-session -A -s main` | @@ -262,7 +261,6 @@ to their own repositories and machine setup. | `home/dot_config/ghostty/` | Ghostty and Hyper mappings | | `home/dot_config/tmux/` | tmux, status scripts, and plugins | | `home/dot_local/bin/` | `clip-serve` (Mac) and the `wl-paste` shim (Linux) behind the ssht clipboard bridge | -| `home/dot_config/raycast/` | Raycast Script Commands | | `home/dot_config/zed/` | Zed settings and keybindings | | `home/dot_config/Code/User/` | VS Code XDG settings | | `home/dot_config/nvim/` | Neovim configuration | @@ -270,7 +268,7 @@ to their own repositories and machine setup. | `home/.chezmoiscripts/` | Ordered and change-triggered setup | | `home/.chezmoiexternal.toml` | Pinned shell and TPM sources | | `macos-scripts/` | Auditable macOS defaults | -| `scripts/` | Local SSH key generation, Claude Code hook install, and preference helpers | +| `scripts/` | Local SSH key generation and Claude Code hook install | ## macOS defaults @@ -288,3 +286,9 @@ macos-scripts/macos-defaults.sh --update # apply and update macOS The same ShellCheck, template, profile, and Chezmoi dry-run checks run in CI. Neovim reference: [docs/nvim-cheat-sheet.md](docs/nvim-cheat-sheet.md). + +Machine registration, private model endpoints, saved infrastructure SSH profiles, +and personal vault integrations are not managed here. Keep machine-specific SSH +settings in `~/.ssh/config.local` and tmux settings in the documented `*.local` +files. Application deployment and private infrastructure belong in their own +repositories. diff --git a/home/.chezmoiignore b/home/.chezmoiignore index 6184f6c..8bd1d6c 100644 --- a/home/.chezmoiignore +++ b/home/.chezmoiignore @@ -26,8 +26,8 @@ .config/iterm2 Library/LaunchAgents/com.froppa.clip-serve.plist .local/bin/clip-serve -# evo-dev runs the real Linux Depot binary the evo development role installs -# at ~/.local/bin/depot; the Cargo-install symlink must not replace it. +# Preserve a locally installed Linux Depot binary; the macOS Cargo-install +# symlink must not replace it. .local/bin/depot {{ end -}} diff --git a/home/.chezmoiscripts/run_after_60-add-herdr-evo-dev.sh.tmpl b/home/.chezmoiscripts/run_after_60-add-herdr-evo-dev.sh.tmpl deleted file mode 100644 index 1422dc2..0000000 --- a/home/.chezmoiscripts/run_after_60-add-herdr-evo-dev.sh.tmpl +++ /dev/null @@ -1,19 +0,0 @@ -{{ if and (eq .chezmoi.os "darwin") .personal -}} -#!/bin/sh -set -eu - -# Keep evo-dev in herdr's sidebar as a saved SSH machine. herdr stores -# machines in its own catalog, not config.toml, so apply registers it. -# froppa/evo installs the herdr it attaches to; without that, machine add -# would ask to install a self-updating copy there instead. - -command -v herdr >/dev/null 2>&1 || exit 0 -herdr machine list | cut -f3 | grep -qx evo-dev && exit 0 - -if ! ssh -o BatchMode=yes -o ConnectTimeout=5 evo-dev 'command -v herdr' >/dev/null 2>&1; then - echo "=> herdr: evo-dev unreachable or without herdr (froppa/evo installs it); skipping" >&2 - exit 0 -fi -herdr machine add evo-dev --label evo-dev || - echo "=> herdr: could not add evo-dev; run: herdr machine add evo-dev --label evo-dev" >&2 -{{ end -}} diff --git a/home/dot_config/iterm2/com.googlecode.iterm2.plist b/home/dot_config/iterm2/com.googlecode.iterm2.plist index 0fe4fba..3e65aff 100644 --- a/home/dot_config/iterm2/com.googlecode.iterm2.plist +++ b/home/dot_config/iterm2/com.googlecode.iterm2.plist @@ -1421,1144 +1421,6 @@ Working Directory ~ - - ASCII Anti Aliased - - Ambiguous Double Width - - Ansi 0 Color - - Alpha Component - 1 - Blue Component - 0.11764705926179886 - Color Space - sRGB - Green Component - 0.098039217293262482 - Red Component - 0.078431375324726105 - - Ansi 0 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.11764705926179886 - Color Space - sRGB - Green Component - 0.098039217293262482 - Red Component - 0.078431375324726105 - - Ansi 0 Color (Light) - - Alpha Component - 1 - Blue Component - 0.11764705926179886 - Color Space - sRGB - Green Component - 0.098039217293262482 - Red Component - 0.078431375324726105 - - Ansi 1 Color - - Alpha Component - 1 - Blue Component - 0.16300037503242493 - Color Space - sRGB - Green Component - 0.23660069704055786 - Red Component - 0.7074432373046875 - - Ansi 1 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.16300037503242493 - Color Space - sRGB - Green Component - 0.23660069704055786 - Red Component - 0.7074432373046875 - - Ansi 1 Color (Light) - - Alpha Component - 1 - Blue Component - 0.16300037503242493 - Color Space - sRGB - Green Component - 0.23660069704055786 - Red Component - 0.7074432373046875 - - Ansi 10 Color - - Alpha Component - 1 - Blue Component - 0.56541937589645386 - Color Space - sRGB - Green Component - 0.9042816162109375 - Red Component - 0.3450070321559906 - - Ansi 10 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.56541937589645386 - Color Space - sRGB - Green Component - 0.9042816162109375 - Red Component - 0.3450070321559906 - - Ansi 10 Color (Light) - - Alpha Component - 1 - Blue Component - 0.56541937589645386 - Color Space - sRGB - Green Component - 0.9042816162109375 - Red Component - 0.3450070321559906 - - Ansi 11 Color - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.8833775520324707 - Red Component - 0.9259033203125 - - Ansi 11 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.8833775520324707 - Red Component - 0.9259033203125 - - Ansi 11 Color (Light) - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.8833775520324707 - Red Component - 0.9259033203125 - - Ansi 12 Color - - Alpha Component - 1 - Blue Component - 0.9485321044921875 - Color Space - sRGB - Green Component - 0.67044717073440552 - Red Component - 0.65349078178405762 - - Ansi 12 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.9485321044921875 - Color Space - sRGB - Green Component - 0.67044717073440552 - Red Component - 0.65349078178405762 - - Ansi 12 Color (Light) - - Alpha Component - 1 - Blue Component - 0.9485321044921875 - Color Space - sRGB - Green Component - 0.67044717073440552 - Red Component - 0.65349078178405762 - - Ansi 13 Color - - Alpha Component - 1 - Blue Component - 0.8821563720703125 - Color Space - sRGB - Green Component - 0.4927266538143158 - Red Component - 0.8821563720703125 - - Ansi 13 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.8821563720703125 - Color Space - sRGB - Green Component - 0.4927266538143158 - Red Component - 0.8821563720703125 - - Ansi 13 Color (Light) - - Alpha Component - 1 - Blue Component - 0.8821563720703125 - Color Space - sRGB - Green Component - 0.4927266538143158 - Red Component - 0.8821563720703125 - - Ansi 14 Color - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 0.99263292551040649 - Red Component - 0.37597531080245972 - - Ansi 14 Color (Dark) - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 0.99263292551040649 - Red Component - 0.37597531080245972 - - Ansi 14 Color (Light) - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 0.99263292551040649 - Red Component - 0.37597531080245972 - - Ansi 15 Color - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 1 - Red Component - 0.99999600648880005 - - Ansi 15 Color (Dark) - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 1 - Red Component - 0.99999600648880005 - - Ansi 15 Color (Light) - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 1 - Red Component - 0.99999600648880005 - - Ansi 2 Color - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.7607843279838562 - Red Component - 0.0 - - Ansi 2 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.7607843279838562 - Red Component - 0.0 - - Ansi 2 Color (Light) - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.7607843279838562 - Red Component - 0.0 - - Ansi 3 Color - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.76959484815597534 - Red Component - 0.78058648109436035 - - Ansi 3 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.76959484815597534 - Red Component - 0.78058648109436035 - - Ansi 3 Color (Light) - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.76959484815597534 - Red Component - 0.78058648109436035 - - Ansi 4 Color - - Alpha Component - 1 - Blue Component - 0.78216177225112915 - Color Space - sRGB - Green Component - 0.26474356651306152 - Red Component - 0.15404300391674042 - - Ansi 4 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.78216177225112915 - Color Space - sRGB - Green Component - 0.26474356651306152 - Red Component - 0.15404300391674042 - - Ansi 4 Color (Light) - - Alpha Component - 1 - Blue Component - 0.78216177225112915 - Color Space - sRGB - Green Component - 0.26474356651306152 - Red Component - 0.15404300391674042 - - Ansi 5 Color - - Alpha Component - 1 - Blue Component - 0.74494361877441406 - Color Space - sRGB - Green Component - 0.24931684136390686 - Red Component - 0.752197265625 - - Ansi 5 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.74494361877441406 - Color Space - sRGB - Green Component - 0.24931684136390686 - Red Component - 0.752197265625 - - Ansi 5 Color (Light) - - Alpha Component - 1 - Blue Component - 0.74494361877441406 - Color Space - sRGB - Green Component - 0.24931684136390686 - Red Component - 0.752197265625 - - Ansi 6 Color - - Alpha Component - 1 - Blue Component - 0.78166204690933228 - Color Space - sRGB - Green Component - 0.77425903081893921 - Red Component - 0.0 - - Ansi 6 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.78166204690933228 - Color Space - sRGB - Green Component - 0.77425903081893921 - Red Component - 0.0 - - Ansi 6 Color (Light) - - Alpha Component - 1 - Blue Component - 0.78166204690933228 - Color Space - sRGB - Green Component - 0.77425903081893921 - Red Component - 0.0 - - Ansi 7 Color - - Alpha Component - 1 - Blue Component - 0.78104829788208008 - Color Space - sRGB - Green Component - 0.78105825185775757 - Red Component - 0.7810397744178772 - - Ansi 7 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.78104829788208008 - Color Space - sRGB - Green Component - 0.78105825185775757 - Red Component - 0.7810397744178772 - - Ansi 7 Color (Light) - - Alpha Component - 1 - Blue Component - 0.78104829788208008 - Color Space - sRGB - Green Component - 0.78105825185775757 - Red Component - 0.7810397744178772 - - Ansi 8 Color - - Alpha Component - 1 - Blue Component - 0.4078223705291748 - Color Space - sRGB - Green Component - 0.40782788395881653 - Red Component - 0.40781760215759277 - - Ansi 8 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.4078223705291748 - Color Space - sRGB - Green Component - 0.40782788395881653 - Red Component - 0.40781760215759277 - - Ansi 8 Color (Light) - - Alpha Component - 1 - Blue Component - 0.4078223705291748 - Color Space - sRGB - Green Component - 0.40782788395881653 - Red Component - 0.40781760215759277 - - Ansi 9 Color - - Alpha Component - 1 - Blue Component - 0.45833224058151245 - Color Space - sRGB - Green Component - 0.47524076700210571 - Red Component - 0.8659515380859375 - - Ansi 9 Color (Dark) - - Alpha Component - 1 - Blue Component - 0.45833224058151245 - Color Space - sRGB - Green Component - 0.47524076700210571 - Red Component - 0.8659515380859375 - - Ansi 9 Color (Light) - - Alpha Component - 1 - Blue Component - 0.45833224058151245 - Color Space - sRGB - Green Component - 0.47524076700210571 - Red Component - 0.8659515380859375 - - BM Growl - - Background Color - - Alpha Component - 1 - Blue Component - 0.97999999999999998 - Color Space - sRGB - Green Component - 0.97999999999999998 - Red Component - 0.97999999999999998 - - Background Color (Dark) - - Alpha Component - 1 - Blue Component - 0.12103271484375 - Color Space - sRGB - Green Component - 0.099111050367355347 - Red Component - 0.0806884765625 - - Background Color (Light) - - Alpha Component - 1 - Blue Component - 0.97999999999999998 - Color Space - sRGB - Green Component - 0.97999999999999998 - Red Component - 0.97999999999999998 - - Background Image Location - - Badge Color - - Alpha Component - 0.5 - Blue Component - 0.11610633134841919 - Color Space - sRGB - Green Component - 0.11610633134841919 - Red Component - 0.74613857269287109 - - Badge Color (Dark) - - Alpha Component - 0.5 - Blue Component - 0.65218597462148864 - Color Space - sRGB - Green Component - 0.65218597462148864 - Red Component - 0.9787440299987793 - - Badge Color (Light) - - Alpha Component - 0.5 - Blue Component - 0.11610633058398889 - Color Space - sRGB - Green Component - 0.11610633058398889 - Red Component - 0.74613857269287109 - - Blinking Cursor - - Blur - - Bold Color - - Alpha Component - 1 - Blue Component - 0.062745101749897003 - Color Space - sRGB - Green Component - 0.062745101749897003 - Red Component - 0.062745101749897003 - - Bold Color (Dark) - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 1 - Red Component - 0.99999600648880005 - - Bold Color (Light) - - Alpha Component - 1 - Blue Component - 0.062745098039215685 - Color Space - sRGB - Green Component - 0.062745098039215685 - Red Component - 0.062745098039215685 - - Bound Hosts - - Character Encoding - 4 - Close Sessions On End - - Columns - 80 - Command - sdf@192.168.1.100 - Cursor Color - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.0 - Red Component - 0.0 - - Cursor Color (Dark) - - Alpha Component - 1 - Blue Component - 0.99998724460601807 - Color Space - sRGB - Green Component - 1 - Red Component - 0.99997633695602417 - - Cursor Color (Light) - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.0 - Red Component - 0.0 - - Cursor Guide Color - - Alpha Component - 0.25 - Blue Component - 0.85319280624389648 - Color Space - sRGB - Green Component - 0.77217715978622437 - Red Component - 0.52338260412216187 - - Cursor Guide Color (Dark) - - Alpha Component - 0.25 - Blue Component - 0.94099044799804688 - Color Space - sRGB - Green Component - 0.80232617749205526 - Red Component - 0.37649588016392954 - - Cursor Guide Color (Light) - - Alpha Component - 0.25 - Blue Component - 0.85319280624389648 - Color Space - sRGB - Green Component - 0.77217718629089516 - Red Component - 0.52338262643729649 - - Cursor Text Color - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 1 - Red Component - 1 - - Cursor Text Color (Dark) - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.0 - Red Component - 0.0 - - Cursor Text Color (Light) - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 1 - Red Component - 1 - - Custom Command - SSH - Custom Directory - Yes - Default Bookmark - No - Description - Default - Disable Window Resizing - - Flashing Bell - - Foreground Color - - Alpha Component - 1 - Blue Component - 0.062745101749897003 - Color Space - sRGB - Green Component - 0.062745101749897003 - Red Component - 0.062745101749897003 - - Foreground Color (Dark) - - Alpha Component - 1 - Blue Component - 0.86198854446411133 - Color Space - sRGB - Green Component - 0.86199951171875 - Red Component - 0.86197912693023682 - - Foreground Color (Light) - - Alpha Component - 1 - Blue Component - 0.062745098039215685 - Color Space - sRGB - Green Component - 0.062745098039215685 - Red Component - 0.062745098039215685 - - Guid - 39C392D7-5D94-4E52-852A-32EE2A9BA5C5 - Horizontal Spacing - 1 - Icon - 1 - Idle Code - 0 - Jobs to Ignore - - rlogin - ssh - slogin - telnet - - Keyboard Map - - Link Color - - Alpha Component - 1 - Blue Component - 0.9337158203125 - Color Space - sRGB - Green Component - 0.55789834260940552 - Red Component - 0.19802422821521759 - - Link Color (Dark) - - Alpha Component - 1 - Blue Component - 0.9337158203125 - Color Space - sRGB - Green Component - 0.55789834260940552 - Red Component - 0.19802422821521759 - - Link Color (Light) - - Alpha Component - 1 - Blue Component - 0.9337158203125 - Color Space - sRGB - Green Component - 0.55789834260940552 - Red Component - 0.19802422821521759 - - Load Shell Integration Automatically - - Mouse Reporting - - Name - HomeAssistant :22 - Non Ascii Font - Monaco 12 - Non-ASCII Anti Aliased - - Normal Font - Monaco 14 - Option Key Sends - 0 - Prompt Before Closing 2 - - Right Option Key Sends - 0 - Rows - 25 - SSH - - environmentVariablesToCopy - - filesToCopy - - sshIntegration - - - Screen - -1 - Scrollback Lines - 0 - Selected Text Color - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.0 - Red Component - 0.0 - - Selected Text Color (Dark) - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.0 - Red Component - 0.0 - - Selected Text Color (Light) - - Alpha Component - 1 - Blue Component - 0.0 - Color Space - sRGB - Green Component - 0.0 - Red Component - 0.0 - - Selection Color - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 0.84313726425170898 - Red Component - 0.70196080207824707 - - Selection Color (Dark) - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 0.84313726425170898 - Red Component - 0.70196080207824707 - - Selection Color (Light) - - Alpha Component - 1 - Blue Component - 1 - Color Space - sRGB - Green Component - 0.84313726425170898 - Red Component - 0.70196080207824707 - - Send Code When Idle - - Shortcut - P - Show Mark Indicators - - Silence Bell - - Sync Title - - Tags - - Terminal Type - xterm-256color - Title Components - 964 - Transparency - 0.021276595744680851 - Unlimited Scrollback - - Use Bold Font - - Use Bright Bold - - Use Italic Font - - Use Non-ASCII Font - - Use Separate Colors for Light and Dark Mode - - Vertical Spacing - 1 - Visual Bell - - Window Type - 0 - Working Directory - / - OnlyWhenMoreTabs diff --git a/home/dot_config/raycast/scripts/executable_quick-capture.sh b/home/dot_config/raycast/scripts/executable_quick-capture.sh deleted file mode 100644 index fc3dbca..0000000 --- a/home/dot_config/raycast/scripts/executable_quick-capture.sh +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env bash -# -# @raycast.schemaVersion 1 -# @raycast.title Quick Capture -# @raycast.mode compact -# @raycast.packageName Personal Productivity -# @raycast.icon ๐Ÿ“ -# @raycast.description Capture a todo, reminder, or note from Raycast quickly. -# -# @raycast.argument1 { "type": "text", "placeholder": "What needs to be captured?" } -# @raycast.argument2 { "type": "dropdown", "placeholder": "Type", "default": "todo", "data": [{"title": "Todo", "value": "todo"}, {"title": "Reminder", "value": "reminder"}, {"title": "Note", "value": "note"}] } -# @raycast.argument3 { "type": "text", "placeholder": "Due date/time (optional for reminders, e.g. tomorrow 9am)", "optional": true } - -set -euo pipefail - -CONTENT="${1:-}" -TYPE="${2:-todo}" -DUE_RAW="${3:-}" - -if [[ -z "$CONTENT" ]]; then - echo "No content provided." - exit 1 -fi - -normalize_type() { - local t="$1" - case "$t" in - todo|todo*) echo todo ;; - rem* ) echo reminder ;; - note*|memo* ) echo note ;; - * ) echo "$t" ;; - esac -} - -TYPE="$(normalize_type "$TYPE")" - -VAULT="${AGENT_WORKSPACE_VAULT:-$HOME/code/froppa/agent-workspace}" -INBOX_DIR="$VAULT/Inbox" -DATE_ONLY="$(date '+%Y-%m-%d')" -STAMP="$(date '+%Y-%m-%d-%H%M')" - -slugify() { - local s="$1" - s="$(printf '%s' "$s" | tr '\n' ' ')" - s="$(printf '%s' "$s" | sed -E 's#[/:*?"<>|]#-#g; s/[[:space:]]+/ /g; s/^[[:space:]-]+//; s/[[:space:]-]+$//')" - s="${s:0:60}" - [[ -z "$s" ]] && s="capture" - printf '%s' "$s" -} - -create_inbox_note() { - local kind="$1" - local title="$2" - local slug file - slug="$(slugify "$title")" - file="$INBOX_DIR/${STAMP} ${slug}.md" - mkdir -p "$INBOX_DIR" - - case "$kind" in - note) - cat >"$file" <"$file" <//tasks/.md\` using - \`templates/task.md\`, or drop this note. -TASK - ;; - esac -} - -case "$TYPE" in - todo) - create_inbox_note "task" "$CONTENT" - echo "โœ… Task captured: $CONTENT" - ;; - - note) - create_inbox_note "note" "$CONTENT" - echo "๐Ÿ“ Note captured: $CONTENT" - ;; - - reminder) - osascript - "$CONTENT" "$DUE_RAW" <<'APPLESCRIPT' -on run argv - set reminderText to item 1 of argv - set dueText to item 2 of argv - - tell application "Reminders" - if (count of lists whose name is "Raycast") = 0 then - make new list with properties {name:"Raycast"} - end if - set reminderList to first list whose name is "Raycast" - - if dueText is not "" then - try - set dueDate to date dueText - make new reminder in reminderList with properties {name:reminderText, due date:dueDate} - on error - make new reminder in reminderList with properties {name:reminderText, body:dueText} - end try - else - make new reminder in reminderList with properties {name:reminderText} - end if - end tell -end run -APPLESCRIPT - echo "โฐ Reminder set: $CONTENT" - ;; - - *) - echo "Invalid capture type: $TYPE" - exit 1 - ;; -esac - -exit 0 diff --git a/home/dot_config/zed/private_settings.json b/home/dot_config/zed/private_settings.json index 6f9f02a..275d64c 100644 --- a/home/dot_config/zed/private_settings.json +++ b/home/dot_config/zed/private_settings.json @@ -1,25 +1,4 @@ { - "language_models": { - "openai_compatible": { - "evo-dev": { - "api_url": "http://127.0.0.1:28090/v1", - "available_models": [ - { - "name": "local-evo/qwen3-coder-30b-a3b", - "display_name": "Qwen3-Coder 30B (evo)", - "max_tokens": 32768, - "max_output_tokens": 4096, - "capabilities": { - "tools": true, - "images": false, - "parallel_tool_calls": true, - "prompt_cache_key": true - } - } - ] - } - } - }, "markdown_preview": { "font_size": 14.0, "limit_content_width": false @@ -256,13 +235,6 @@ } }, "agent": { - "favorite_models": [ - { - "provider": "evo-dev", - "model": "local-evo/qwen3-coder-30b-a3b", - "enable_thinking": false - } - ], "tool_permissions": { "tools": { "terminal": { @@ -278,12 +250,7 @@ "provider": "openai", "model": "gpt-5.6-terra" }, - "default_profile": "write", - "default_model": { - "enable_thinking": false, - "provider": "evo-dev", - "model": "local-evo/qwen3-coder-30b-a3b" - } + "default_profile": "write" }, "inlay_hints": { "enabled": false, diff --git a/scripts/export-iterm2-prefs.sh b/scripts/export-iterm2-prefs.sh deleted file mode 100755 index d0f69a5..0000000 --- a/scripts/export-iterm2-prefs.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -[[ "${OSTYPE}" != darwin* ]] && exit 0 - -# Export straight into the chezmoi source so `chezmoi diff` stays clean and -# the change can be committed. Applying deploys it to ~/.config/iterm2. -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SOURCE_PLIST="${SCRIPT_DIR}/../home/dot_config/iterm2/com.googlecode.iterm2.plist" - -defaults export com.googlecode.iterm2 "${SOURCE_PLIST}" -plutil -convert xml1 "${SOURCE_PLIST}" - -echo "Exported iTerm2 preferences to ${SOURCE_PLIST}" -echo "Run 'chezmoi apply' to sync ~/.config/iterm2, then commit the change." diff --git a/test.sh b/test.sh index 18b46d2..472843f 100755 --- a/test.sh +++ b/test.sh @@ -108,8 +108,6 @@ grep -Fq "alias confgit='chezmoi edit --apply ~/.config/git/dotfiles.gitconfig'" [[ -f home/dot_config/ghostty/config ]] || fail "Ghostty config must be named config, the one path every Ghostty version reads" grep -Fqx '.config/ghostty/config.ghostty' home/.chezmoiremove || fail "a stale config.ghostty would load beside the managed config" grep -Fqx "alias ch='chezmoi'" home/dot_aliases || fail "ch must alias chezmoi" -grep -Fq 'herdr machine add evo-dev' home/.chezmoiscripts/run_after_60-add-herdr-evo-dev.sh.tmpl || fail "apply must register evo-dev as a saved herdr machine" -grep -Fq '{{ if and (eq .chezmoi.os "darwin") .personal -}}' home/.chezmoiscripts/run_after_60-add-herdr-evo-dev.sh.tmpl || fail "only the personal Mac may attach evo-dev" grep -Fq 'command = /bin/zsh' home/dot_config/ghostty/config || fail "Ghostty must launch zsh; herdr is started on demand" grep -Fq 'config-file = ?config.local' home/dot_config/ghostty/config || fail "Ghostty must load the optional machine-local override last" ! grep -qE '^keybind = (performable:)?ctrl\+alt\+super\+[^=]+=text:' home/dot_config/ghostty/config || fail "Hyper chords must reach herdr, not be rewritten into tmux prefix bytes" @@ -129,14 +127,14 @@ grep -Fq 'xterm-ghostty:RGB:extkeys' home/dot_config/tmux/tmux.conf || fail "Gho grep -Fq 'set -s extended-keys on' home/dot_config/tmux/tmux.conf || fail "tmux must pass modified keys to Claude Code" grep -Fq 'set -g focus-events on' home/dot_config/tmux/tmux.conf || fail "tmux must pass focus events to Claude Code" grep -Fq 'set -g assume-paste-time 0' home/dot_config/tmux/tmux.conf || fail "tmux must disable paste timing as a global session option" -grep -Fq '.local/bin/depot' home/.chezmoiignore || fail "the Depot symlink must not replace evo-dev's real binary on Linux" +grep -Fq '.local/bin/depot' home/.chezmoiignore || fail "the Depot symlink must not replace a locally installed binary on Linux" sed -n '/ne .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq 'Library/LaunchAgents/com.froppa.clip-serve.plist' || fail "the clipboard LaunchAgent is macOS-only" sed -n '/eq .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq '.local/bin/wl-paste' || fail "the wl-paste shim must not land on the Mac" -[[ -x home/dot_local/bin/executable_follow-main.sh && -f home/dot_config/systemd/user/follow-main.timer ]] || fail "follow-main must ship its script and timer for evo-dev" +[[ -x home/dot_local/bin/executable_follow-main.sh && -f home/dot_config/systemd/user/follow-main.timer ]] || fail "follow-main must ship its script and timer for Linux" sed -n '/eq .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq '.config/systemd' || fail "systemd user units must not be applied on macOS" grep -Fq 'MouseDragEnd1Pane send -X copy-selection' home/dot_config/tmux/tmux.conf || fail "mouse selection must not snap the view back to the bottom" grep -Fq 'xterm-ghostty:RGB:extkeys:hyperlinks' home/dot_config/tmux/tmux.conf || fail "tmux must pass OSC 8 hyperlinks through to Ghostty" -! grep -rqE '(^|[^a-z])evo(-|[^a-z]|$)|192\.168|100\.[0-9]+\.' home/dot_config/tmux || fail "host names and addresses belong in the unmanaged tmux *.local files" +! grep -rqE '192\.168|100\.[0-9]+\.' home/dot_config/tmux || fail "host names and addresses belong in the unmanaged tmux *.local files" if find home/private_dot_ssh -type f ! -name private_config.tmpl -print -quit | grep -q .; then fail "SSH key material must not be managed" fi diff --git a/tests/test_ubuntu_bootstrap.py b/tests/test_ubuntu_bootstrap.py index d32285d..49561ff 100644 --- a/tests/test_ubuntu_bootstrap.py +++ b/tests/test_ubuntu_bootstrap.py @@ -146,8 +146,7 @@ def test_managed_files_exclude_mac_only_apps_on_linux(self): "--destination", str(self.base), "--override-data", json.dumps(data), "managed", "--exclude=externals", "--path-style=relative"], text=True) paths = output.splitlines() - for app in (".hammerspoon/init.lua", ".config/iterm2/com.googlecode.iterm2.plist", - ".config/raycast/scripts/quick-capture.sh"): + for app in (".hammerspoon/init.lua", ".config/iterm2/com.googlecode.iterm2.plist"): self.assertEqual(app in paths, system == "darwin", app) self.assertIn(".config/nvim/init.lua", paths) self.assertIn(".config/ghostty/config", paths) From bbc01df7feb13ffcebdf36a98da9448be6772f3b Mon Sep 17 00:00:00 2001 From: froppa-agent <330570035+froppa-agent@users.noreply.github.com> Date: Mon, 12 Oct 2026 22:33:34 +0200 Subject: [PATCH 3/6] refactor: simplify workstation defaults --- README.md | 79 +- home/.chezmoi.toml.tmpl | 9 - home/.chezmoidata/20-features.yml | 3 +- home/.chezmoidata/40-packages.yml | 1 - home/.chezmoiignore | 9 +- .../run_once_after_50-configure-iterm2.sh | 10 - ..._onchange_after_45-load-clip-serve.sh.tmpl | 14 +- home/dot_aws/cli/alias | 2 +- home/dot_config/Code/User/launch.json | 37 +- home/dot_config/ghostty/config | 67 +- home/dot_config/git/dotfiles.gitconfig.tmpl | 1 - home/dot_config/herdr/config.toml | 46 - .../iterm2/com.googlecode.iterm2.plist | 1534 ----------------- home/dot_config/nvim/lua/config/keymaps.lua | 2 +- home/dot_config/starship.toml | 4 +- home/dot_config/zed/private_settings.json | 4 - home/dot_exports.tmpl | 1 - home/dot_hammerspoon/init.lua | 8 - home/dot_local/bin/executable_clip-serve | 2 +- home/dot_local/bin/symlink_depot.tmpl | 1 - home/dot_zsh_completions | 5 - home/dot_zshrc | 29 - ...l => local.dotfiles.clip-serve.plist.tmpl} | 2 +- home/private_dot_ssh/private_config.tmpl | 11 +- scripts/check-public-config.py | 79 + test.sh | 19 +- tests/test_public_config.py | 40 + tests/test_ubuntu_bootstrap.py | 33 +- 28 files changed, 218 insertions(+), 1834 deletions(-) delete mode 100644 home/.chezmoiscripts/run_once_after_50-configure-iterm2.sh delete mode 100644 home/dot_config/herdr/config.toml delete mode 100644 home/dot_config/iterm2/com.googlecode.iterm2.plist delete mode 100644 home/dot_local/bin/symlink_depot.tmpl rename home/private_Library/private_LaunchAgents/{com.froppa.clip-serve.plist.tmpl => local.dotfiles.clip-serve.plist.tmpl} (94%) create mode 100644 scripts/check-public-config.py create mode 100644 tests/test_public_config.py diff --git a/README.md b/README.md index 71de3f5..2c60c85 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,10 @@ are shared across both systems. | Area | Configuration | | --- | --- | -| Terminal | Ghostty opens the persistent tmux session `main`; `ssht ` nests a persistent remote one; the tmux status bar shows where the active pane runs, running agents, and Claude and Codex limits | -| Shell | Zsh, Oh My Zsh, Starship, fzf, mise, and direnv | +| Terminal | Ghostty native panes and tabs, optional tmux sessions, and SSH helpers | +| Shell | Zsh, Starship, fzf, mise, and direnv | | Editors | Zed, VS Code, Vim, and Neovim | -| Shortcuts | Raycast Caps Lock Hyper translated by Ghostty into tmux commands | +| Shortcuts | Hyper shortcuts for terminal panes and tabs | | Packages | Homebrew profiles on macOS; common native apt packages on Ubuntu | | SSH | Portable client config; keys stay local to each machine | | macOS | Dock, Finder, keyboard, Safari, and general defaults | @@ -68,7 +68,7 @@ If already cloned, use that checkout instead of cloning again. Ubuntu setup installs missing packages with apt and never installs or updates Linuxbrew. An existing Linuxbrew installation is left on disk, but managed Zsh startup no longer adds it to PATH. Personal and work profiles currently share the same -Ubuntu package set. Raycast, Hammerspoon, and iTerm2 configuration is macOS-only. +Ubuntu package set. Raycast and Hammerspoon configuration is macOS-only. The native set covers shell, editor, Git, and common build tools. It does not add third-party repositories or install mise, Codex, Claude Code, Docker, @@ -111,8 +111,8 @@ gh auth login --web This does not authenticate automatically or copy credentials from your Mac. Codex is pinned to the validated CLI version in the script. Runtime installation -is separate; do not run source-building plugin installers until the required -Depot build wrapper is available on the machine. +is separate; install the required runtimes and build tools before running +source-building plugin installers. ### SSH @@ -142,50 +142,41 @@ session restoration. ## Terminal shortcuts -Raycast owns Caps Lock and emits `Ctrl+Option+Command`. Ghostty converts the -following chords to tmux commands. Right Option remains available for Danish -symbols. +Configure Caps Lock as Hyper (`Ctrl+Option+Command`) in Raycast. Ghostty uses +these chords for native panes and tabs; Right Option remains available for +keyboard symbols. | Shortcut | Action | | --- | --- | -| `Command+K` | Clear the active application screen through tmux | -| `Shift+Enter` | Insert a newline in Claude Code and shell prompts | -| `Caps+C` | New window | +| `Command+K` | Clear the active application screen | +| `Shift+Enter` | Let the active application handle newlines | +| `Caps+C` | New tab | | `Caps+I` | Side-by-side pane | | `Caps+-` | Stacked pane | | `Caps+Arrow` | Move between panes | | `Caps+Shift+Arrow` | Resize pane | | `Caps+=` | Spread the panes evenly | -| `Caps+0โ€ฆ9` | Select window | +| `Caps+1โ€ฆ9` | Select tab | | `Caps+Z` | Toggle pane zoom | -| `Caps+R` | Reload tmux | -| `Caps+X` / `Caps+W` | Kill pane after confirmation | -| `Caps+,` | Rename window | -| `Caps+Shift+,` / `Caps+Shift+.` | Move window left / right | -| `Caps+N` / `Caps+P` / `Caps+Tab` | Next, previous, last window | -| `Caps+F` | Pick a window from a list | -| `Caps+B` | Break the pane out into its own window | -| `Caps+J` / `Caps+M` | Join a pane from, or move this pane to, another window | -| `Caps+U` | Pick a URL from the pane history and open it | -| `Caps+H` | tmux cheat sheet; the bottom status row carries the hint | -| `Caps+Space` | The local tmux prefix; press the key after it | - -Every chord is the tmux prefix `Ctrl-a` plus the same key, so it also works -from a plain keyboard. Windows are named after their directory or ssh host; -rename one and the name sticks. Mouse drag, double-click, and triple-click copy -to the clipboard without leaving copy mode; `Cmd+V` pastes; `Cmd+click` opens -a link; hold Shift to let Ghostty select text itself. `tm` attaches the same -session from any other terminal. +| `Caps+X` | Close the active surface | +| `Caps+,` | Rename tab | +| `Caps+Shift+,` / `Caps+Shift+.` | Move tab left / right | +| `Caps+N` / `Caps+P` | Next / previous tab | + +tmux uses the prefix `Ctrl-a`. Its cheat sheet lists window, pane, and copying +commands. Windows are named after their directory or SSH host; a manual name +persists. Mouse drag, double-click, and triple-click copy without leaving copy +mode. Hold Shift to let Ghostty select text itself. `tm` attaches a persistent +session from another terminal. `ssht [session]` attaches a persistent tmux session on a remote machine -inside the current pane. While it runs there, the Caps chords drive the remote -tmux; `Caps+Space` or `Ctrl-a` and then the key still reach the local one, as -does a click on the local status bar. Run outside tmux, `ssht` instead tints +inside the current pane. Use tmux's prefix commands to control its windows +and panes. Run outside tmux, `ssht` instead tints Ghostty's background in the host's colour and titles the tab after it until the connection ends. `ssht` also forwards the Mac's clipboard socket, which the -`com.froppa.clip-serve` LaunchAgent serves. The `wl-paste` shim on the remote +`local.dotfiles.clip-serve` LaunchAgent serves. The `wl-paste` shim on the remote host reads it, so a screenshot copied on the Mac (`Cmd+Ctrl+Shift+4`) pastes into a remote Claude Code with `Ctrl+V`. Only images cross; text still pastes with `Cmd+V`. Plain `ssh` does not carry it. @@ -222,8 +213,8 @@ status line keeps only model, effort, and context left. Claude Code keeps `~/.claude/settings.json` itself, so the tab-state hooks are installed once per machine with `scripts/claude-tmux-hooks.sh`, which merges -them idempotently. Two unmanaged files under `~/.config/tmux/` keep host -details out of this repository: +them idempotently. Two local configuration files under `~/.config/tmux/` +customize SSH status: | File | Content | | --- | --- | @@ -245,14 +236,8 @@ Machine-specific overrides use unmanaged `*.local` files such as `.zshrc.local`, `.exports.local`, `.aliases.local`, `.functions.local`, and `.gitconfig.local`. -Depot is installed separately with Cargo from `struktly/tools`. The managed -`~/.local/bin/depot` link points to `~/.cargo/bin/depot`. Zsh loads completion -from the installed Depot version after completion initialization; no generated -completion file needs updating. - The Linux `follow-main.timer` updates only this repository's managed -configuration through Chezmoi. Application installation and deployment belong -to their own repositories and machine setup. +configuration through Chezmoi. ## Where things live @@ -286,9 +271,3 @@ macos-scripts/macos-defaults.sh --update # apply and update macOS The same ShellCheck, template, profile, and Chezmoi dry-run checks run in CI. Neovim reference: [docs/nvim-cheat-sheet.md](docs/nvim-cheat-sheet.md). - -Machine registration, private model endpoints, saved infrastructure SSH profiles, -and personal vault integrations are not managed here. Keep machine-specific SSH -settings in `~/.ssh/config.local` and tmux settings in the documented `*.local` -files. Application deployment and private infrastructure belong in their own -repositories. diff --git a/home/.chezmoi.toml.tmpl b/home/.chezmoi.toml.tmpl index 77fc6d6..9b903fd 100644 --- a/home/.chezmoi.toml.tmpl +++ b/home/.chezmoi.toml.tmpl @@ -1,10 +1,3 @@ -{{ $computerName := "" }} -{{ if eq .chezmoi.os "darwin" }} -{{ $computerName = (output "scutil" "--get" "ComputerName" | trim) }} -{{ else }} -{{ $computerName = (output "hostname" | trim) }} -{{ end }} - {{ $name := promptStringOnce . "name" "name" }} {{ $email := promptStringOnce . "email" "email" }} {{/* WORK=true selects the work machine setup; anything else (incl. PERSONAL=true) is personal. */}} @@ -16,8 +9,6 @@ email = {{ $email | quote }} profile = {{ ternary "work" "personal" $work | quote }} work = {{ $work }} personal = {{ not $work }} -computerName = {{ $computerName | quote }} -hostname = {{ $computerName | quote }} [github] refreshPeriod = "12h" diff --git a/home/.chezmoidata/20-features.yml b/home/.chezmoidata/20-features.yml index 38e9688..6df7428 100644 --- a/home/.chezmoidata/20-features.yml +++ b/home/.chezmoidata/20-features.yml @@ -1,5 +1,4 @@ --- features: - # Gates the Homebrew env block (incl. 1Password token lookup) in dot_exports.tmpl. - # Requires a working `op` CLI session when enabled. + # Gates optional Homebrew environment preferences in dot_exports.tmpl. brew: false diff --git a/home/.chezmoidata/40-packages.yml b/home/.chezmoidata/40-packages.yml index f113427..c23ce18 100644 --- a/home/.chezmoidata/40-packages.yml +++ b/home/.chezmoidata/40-packages.yml @@ -170,7 +170,6 @@ packages: - cocoapods - age-plugin-se - libimobiledevice - - herdr # Serial and embedded hardware # - minicom # - libftdi diff --git a/home/.chezmoiignore b/home/.chezmoiignore index 8bd1d6c..49f9bcc 100644 --- a/home/.chezmoiignore +++ b/home/.chezmoiignore @@ -14,8 +14,7 @@ **/.DS_Store {{ if eq .chezmoi.os "darwin" -}} -# The follow-main timer keeps a Linux workstation on main; the Mac has no -# systemd and is where the changes are made. +# User timers are available only on Linux. .config/systemd .local/bin/follow-main.sh {{ end -}} @@ -23,12 +22,8 @@ {{ if ne .chezmoi.os "darwin" -}} .hammerspoon .config/raycast -.config/iterm2 -Library/LaunchAgents/com.froppa.clip-serve.plist +Library/LaunchAgents/local.dotfiles.clip-serve.plist .local/bin/clip-serve -# Preserve a locally installed Linux Depot binary; the macOS Cargo-install -# symlink must not replace it. -.local/bin/depot {{ end -}} {{ if eq .chezmoi.os "darwin" -}} diff --git a/home/.chezmoiscripts/run_once_after_50-configure-iterm2.sh b/home/.chezmoiscripts/run_once_after_50-configure-iterm2.sh deleted file mode 100644 index 30cfb94..0000000 --- a/home/.chezmoiscripts/run_once_after_50-configure-iterm2.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -euo pipefail -[[ "${OSTYPE}" != darwin* ]] && exit 0 - -PREFS_CUSTOM_FOLDER="${HOME}/.config/iterm2" - -defaults write com.googlecode.iterm2 PrefsCustomFolder -string "${PREFS_CUSTOM_FOLDER}" -defaults write com.googlecode.iterm2 LoadPrefsFromCustomFolder -bool true - -echo "iTerm2 configured to load prefs from ${PREFS_CUSTOM_FOLDER}" diff --git a/home/.chezmoiscripts/run_onchange_after_45-load-clip-serve.sh.tmpl b/home/.chezmoiscripts/run_onchange_after_45-load-clip-serve.sh.tmpl index d477294..f16ae21 100755 --- a/home/.chezmoiscripts/run_onchange_after_45-load-clip-serve.sh.tmpl +++ b/home/.chezmoiscripts/run_onchange_after_45-load-clip-serve.sh.tmpl @@ -3,10 +3,20 @@ set -eu # Reload the clipboard bridge whenever its LaunchAgent changes. -# plist-sha256: {{ include "private_Library/private_LaunchAgents/com.froppa.clip-serve.plist.tmpl" | sha256sum }} +# plist-sha256: {{ include "private_Library/private_LaunchAgents/local.dotfiles.clip-serve.plist.tmpl" | sha256sum }} -label=com.froppa.clip-serve +label=local.dotfiles.clip-serve mkdir -p "$HOME/.cache" +# Retire another label only when it launches this exact managed command. +for plist in "$HOME/Library/LaunchAgents/"*.plist; do + [ -f "$plist" ] || continue + program=$(plutil -extract ProgramArguments.0 raw -o - "$plist" 2>/dev/null) || continue + [ "$program" = "$HOME/.local/bin/clip-serve" ] || continue + previous=$(plutil -extract Label raw -o - "$plist" 2>/dev/null) || continue + [ "$previous" != "$label" ] || continue + launchctl bootout "gui/$(id -u)/$previous" 2>/dev/null || true + rm -f "$plist" +done launchctl bootout "gui/$(id -u)/$label" 2>/dev/null || true # bootout returns before teardown finishes; a lost race must not abort apply. launchctl bootstrap "gui/$(id -u)" "$HOME/Library/LaunchAgents/$label.plist" 2>/dev/null || diff --git a/home/dot_aws/cli/alias b/home/dot_aws/cli/alias index 0865b73..9f54a9c 100644 --- a/home/dot_aws/cli/alias +++ b/home/dot_aws/cli/alias @@ -32,7 +32,7 @@ start = start-query --log-group-name query = get-query-results --query-id # Example: -# aws logs insights "/ecs/ch-prod-my-service" "fields @timestamp, @message | sort @timestamp desc | limit 50" +# aws logs insights "/ecs/example-service" "fields @timestamp, @message | sort @timestamp desc | limit 50" # Every continuation line MUST be indented. This is an INI file: a line at # column 0 is a new key, not part of the value above it, and the whole # file fails to parse. The parser strips the indentation before the shell diff --git a/home/dot_config/Code/User/launch.json b/home/dot_config/Code/User/launch.json index ca91913..4754397 100644 --- a/home/dot_config/Code/User/launch.json +++ b/home/dot_config/Code/User/launch.json @@ -1,25 +1,6 @@ { "version": "0.2.0", "configurations": [ - { - "presentation": { - "hidden": false, - "group": "services", - "order": 1 - }, - "name": "Go: Service xxx", - "type": "go", - "request": "launch", - "mode": "debug", - "program": "${workspaceFolder}/service/xxx", - "cwd": "${workspaceFolder}", - "buildFlags": "-ldflags '-X pkg/meta.Name=serviceName'", - "args": ["serve"], - "env": { - "TEMPORAL_DEBUG": "1", - "GODEBUG": "execerrdot=0" - } - }, { "name": "Go: Current Package", "type": "go", @@ -34,23 +15,23 @@ "request": "launch", "program": "${file}", "cwd": "${workspaceFolder}", - "skipFiles": ["/**"] + "skipFiles": [ + "/**" + ] }, { "name": "Node: pnpm dev", "type": "node", "request": "launch", "runtimeExecutable": "pnpm", - "runtimeArgs": ["dev"], + "runtimeArgs": [ + "dev" + ], "cwd": "${workspaceFolder}", "console": "integratedTerminal", - "skipFiles": ["/**"] - } - ], - "compounds": [ - { - "name": "Go + Node", - "configurations": ["Go: Service xxx", "Node: pnpm dev"] + "skipFiles": [ + "/**" + ] } ] } diff --git a/home/dot_config/ghostty/config b/home/dot_config/ghostty/config index a15c759..1b9321e 100644 --- a/home/dot_config/ghostty/config +++ b/home/dot_config/ghostty/config @@ -114,10 +114,7 @@ shell-integration-features = cursor,title,ssh-env,path # Native panes and tabs (Hyper = Caps) # ======================================= -# Same chords as Herdr's [keys], so muscle memory carries over. -# While Herdr runs, the `herdr` key table below hands them to it. -# performable: keeps them off the menu bar; a menu shortcut fires before -# any key table, so the table could never hand it to Herdr. +# Hyper chords control native panes and tabs. keybind = performable:ctrl+alt+super+i=new_split:right keybind = performable:ctrl+alt+super+-=new_split:down @@ -151,70 +148,10 @@ keybind = performable:ctrl+alt+super+digit_7=goto_tab:7 keybind = performable:ctrl+alt+super+digit_8=goto_tab:8 keybind = performable:ctrl+alt+super+digit_9=goto_tab:9 -# Herdr-only chords: swallowed outside Herdr instead of reaching zsh -# as escape/control sequences. -keybind = ctrl+alt+super+w=ignore -keybind = ctrl+alt+super+digit_0=ignore -keybind = ctrl+alt+super+tab=ignore -keybind = ctrl+alt+super+b=ignore -keybind = ctrl+alt+super+j=ignore -keybind = ctrl+alt+super+m=ignore -keybind = ctrl+alt+super+u=ignore - - -# ======================================= -# Herdr key table -# ======================================= - -# Herdr is NOT Ghostty's shell. The zsh `herdr` wrapper activates this -# table on its surface through Ghostty's AppleScript `perform action` -# and deactivates it when Herdr exits. `unbind` cannot work here: it -# empties the table entry and the lookup falls through to the default -# bindings. Re-activating the already-innermost table is a no-op, so the -# performable binding matches, does nothing, and Ghostty sends the chord -# to the pty for Herdr. Hyper-= still equalizes Ghostty splits. - -keybind = herdr/ -keybind = herdr/performable:ctrl+alt+super+i=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+-=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+z=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+x=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+arrow_left=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+arrow_down=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+arrow_up=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+arrow_right=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+shift+arrow_left=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+shift+arrow_down=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+shift+arrow_up=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+shift+arrow_right=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+c=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+p=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+n=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+comma=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+shift+comma=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+shift+period=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+digit_1=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+digit_2=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+digit_3=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+digit_4=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+digit_5=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+digit_6=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+digit_7=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+digit_8=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+digit_9=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+w=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+digit_0=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+tab=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+b=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+j=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+m=activate_key_table:herdr -keybind = herdr/performable:ctrl+alt+super+u=activate_key_table:herdr - - # ======================================= # Machine-local overrides # ======================================= # Optional. Keep command=/bin/zsh unless you explicitly # want a machine to launch something else. -# config-file = ?config.local \ No newline at end of file +config-file = ?config.local diff --git a/home/dot_config/git/dotfiles.gitconfig.tmpl b/home/dot_config/git/dotfiles.gitconfig.tmpl index dab0d48..cc7b9dc 100644 --- a/home/dot_config/git/dotfiles.gitconfig.tmpl +++ b/home/dot_config/git/dotfiles.gitconfig.tmpl @@ -38,7 +38,6 @@ fup1 = commit --fixup HEAD~1 fup2 = commit --fixup HEAD~2 fup3 = commit --fixup HEAD~3 - signlast = "!~/.local/bin/git-signlast" ss = commit --message "chore: snapshot" --no-gpg-sign unamend = reset --mixed HEAD@{1} diff --git a/home/dot_config/herdr/config.toml b/home/dot_config/herdr/config.toml deleted file mode 100644 index df62ac3..0000000 --- a/home/dot_config/herdr/config.toml +++ /dev/null @@ -1,46 +0,0 @@ -onboarding = false -# ~/.config/herdr/config.toml - -[keys] -# Hyper-Space, as in tmux. Not Ctrl-a: Ghostty sends Command-Left as Ctrl-a. -prefix = "ctrl+alt+cmd+space" -help = "ctrl+alt+cmd+h" - -new_tab = "ctrl+alt+cmd+c" - -split_vertical = "ctrl+alt+cmd+i" -split_horizontal = "ctrl+alt+cmd+minus" -zoom = "ctrl+alt+cmd+z" -resize_mode = "ctrl+alt+cmd+r" -close_pane = "ctrl+alt+cmd+x" - -focus_pane_left = "ctrl+alt+cmd+left" -focus_pane_down = "ctrl+alt+cmd+down" -focus_pane_up = "ctrl+alt+cmd+up" -focus_pane_right = "ctrl+alt+cmd+right" - -resize_pane_left = "ctrl+alt+cmd+shift+left" -resize_pane_down = "ctrl+alt+cmd+shift+down" -resize_pane_up = "ctrl+alt+cmd+shift+up" -resize_pane_right = "ctrl+alt+cmd+shift+right" - -switch_tab = "ctrl+alt+cmd+1..9" - -previous_tab = "ctrl+alt+cmd+p" -next_tab = "ctrl+alt+cmd+n" - -rename_tab = "ctrl+alt+cmd+comma" -move_tab_previous = "ctrl+alt+cmd+shift+comma" -move_tab_next = "ctrl+alt+cmd+shift+period" - -goto = "ctrl+alt+cmd+f" - -[ui.sound] -enabled = false - -[theme] -name = "catppuccin" -auto_switch = false - -[ui.toast] -delivery = "herdr" diff --git a/home/dot_config/iterm2/com.googlecode.iterm2.plist b/home/dot_config/iterm2/com.googlecode.iterm2.plist deleted file mode 100644 index 3e65aff..0000000 --- a/home/dot_config/iterm2/com.googlecode.iterm2.plist +++ /dev/null @@ -1,1534 +0,0 @@ - - - - - AIFeatureFunctionCalling - - AIFeatureHostedCodeInterpeter - - AIFeatureHostedFileSearch - - AIFeatureHostedWebSearch - - AIFeatureStreamingResponses - - AITermAPI - 2 - AIVectorStore - 0 - AdjustWindowForFontSizeChange - - AiMaxTokens - 1050000 - AiModel - gpt-5.5 - AiResponseMaxTokens - 128000 - AitermURL - https://api.openai.com/v1/responses - AllowClipboardAccess - - AlwaysOpenWindowAtStartup - - ClickToSelectCommand - - Compress History - - Default Bookmark Guid - 3712D82E-60F8-4B0B-9F2E-5F21BC701367 - DefaultTabBarHeight - 28 - DimBackgroundWindows - - DimInactiveSplitPanes - - DimOnlyText - - DisableFullscreenTransparency - - DisableTopRightIndicators - - DoubleClickPerformsSmartSelection - - EnableAPIServer - - EnableDivisionView - - EnableProxyIcon - - EnableRendezvous - - EnterCopyModeAutomatically - - FallbackLCCType - - FocusFollowsMouse - - FocusOnRightOrMiddleClick - - HTMLTabTitles - - HapticFeedbackForEsc - - HideActivityIndicator - - HideMenuBarInFullscreen - - HideScrollbar - - HideTab - - Hotkey - - HotkeyChar - 0 - HotkeyCode - 0 - HotkeyMigratedFromSingleToMulti - - HotkeyModifiers - 0 - IRMemory - 4 - NeverBlockSystemShutdown - - New Bookmarks - - - ASCII Anti Aliased - - ASCII Ligatures - - AWDS Pane Directory - - AWDS Pane Option - Recycle - AWDS Tab Directory - - AWDS Tab Option - No - AWDS Window Directory - - AWDS Window Option - No - Allow modifyOtherKeys - - Ambiguous Double Width - - Animate Movement - - Ansi 0 Color - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Ansi 0 Color (Dark) - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Ansi 0 Color (Light) - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Ansi 1 Color - - Blue Component - 0 - Green Component - 0 - Red Component - 0.8 - - Ansi 1 Color (Dark) - - Blue Component - 0 - Green Component - 0 - Red Component - 0.8 - - Ansi 1 Color (Light) - - Blue Component - 0 - Green Component - 0 - Red Component - 0.8 - - Ansi 10 Color - - Blue Component - 0.2039216 - Green Component - 0.8862745 - Red Component - 0.5411764999999999 - - Ansi 10 Color (Dark) - - Blue Component - 0.2039216 - Green Component - 0.8862745 - Red Component - 0.5411764999999999 - - Ansi 10 Color (Light) - - Blue Component - 0.2039216 - Green Component - 0.8862745 - Red Component - 0.5411764999999999 - - Ansi 11 Color - - Blue Component - 0.3098039 - Green Component - 0.9137255 - Red Component - 0.9882353 - - Ansi 11 Color (Dark) - - Blue Component - 0.3098039 - Green Component - 0.9137255 - Red Component - 0.9882353 - - Ansi 11 Color (Light) - - Blue Component - 0.3098039 - Green Component - 0.9137255 - Red Component - 0.9882353 - - Ansi 12 Color - - Blue Component - 0.8117647 - Green Component - 0.6235294 - Red Component - 0.4470588 - - Ansi 12 Color (Dark) - - Blue Component - 0.8117647 - Green Component - 0.6235294 - Red Component - 0.4470588 - - Ansi 12 Color (Light) - - Blue Component - 0.8117647 - Green Component - 0.6235294 - Red Component - 0.4470588 - - Ansi 13 Color - - Blue Component - 0.6588235 - Green Component - 0.4980392 - Red Component - 0.6784314 - - Ansi 13 Color (Dark) - - Blue Component - 0.6588235 - Green Component - 0.4980392 - Red Component - 0.6784314 - - Ansi 13 Color (Light) - - Blue Component - 0.6588235 - Green Component - 0.4980392 - Red Component - 0.6784314 - - Ansi 14 Color - - Blue Component - 0.8862745 - Green Component - 0.8862745 - Red Component - 0.2039216 - - Ansi 14 Color (Dark) - - Blue Component - 0.8862745 - Green Component - 0.8862745 - Red Component - 0.2039216 - - Ansi 14 Color (Light) - - Blue Component - 0.8862745 - Green Component - 0.8862745 - Red Component - 0.2039216 - - Ansi 15 Color - - Blue Component - 0.9254902 - Green Component - 0.9333333 - Red Component - 0.9333333 - - Ansi 15 Color (Dark) - - Blue Component - 0.9254902 - Green Component - 0.9333333 - Red Component - 0.9333333 - - Ansi 15 Color (Light) - - Blue Component - 0.9254902 - Green Component - 0.9333333 - Red Component - 0.9333333 - - Ansi 2 Color - - Blue Component - 0.02352941 - Green Component - 0.6039215999999999 - Red Component - 0.3058824 - - Ansi 2 Color (Dark) - - Blue Component - 0.02352941 - Green Component - 0.6039215999999999 - Red Component - 0.3058824 - - Ansi 2 Color (Light) - - Blue Component - 0.02352941 - Green Component - 0.6039215999999999 - Red Component - 0.3058824 - - Ansi 3 Color - - Blue Component - 0 - Green Component - 0.627451 - Red Component - 0.7686275 - - Ansi 3 Color (Dark) - - Blue Component - 0 - Green Component - 0.627451 - Red Component - 0.7686275 - - Ansi 3 Color (Light) - - Blue Component - 0 - Green Component - 0.627451 - Red Component - 0.7686275 - - Ansi 4 Color - - Blue Component - 0.6431373 - Green Component - 0.3960784 - Red Component - 0.2039216 - - Ansi 4 Color (Dark) - - Blue Component - 0.6431373 - Green Component - 0.3960784 - Red Component - 0.2039216 - - Ansi 4 Color (Light) - - Blue Component - 0.6431373 - Green Component - 0.3960784 - Red Component - 0.2039216 - - Ansi 5 Color - - Blue Component - 0.4823529 - Green Component - 0.3137255 - Red Component - 0.4588235 - - Ansi 5 Color (Dark) - - Blue Component - 0.4823529 - Green Component - 0.3137255 - Red Component - 0.4588235 - - Ansi 5 Color (Light) - - Blue Component - 0.4823529 - Green Component - 0.3137255 - Red Component - 0.4588235 - - Ansi 6 Color - - Blue Component - 0.6039215999999999 - Green Component - 0.5960785 - Red Component - 0.02352941 - - Ansi 6 Color (Dark) - - Blue Component - 0.6039215999999999 - Green Component - 0.5960785 - Red Component - 0.02352941 - - Ansi 6 Color (Light) - - Blue Component - 0.6039215999999999 - Green Component - 0.5960785 - Red Component - 0.02352941 - - Ansi 7 Color - - Blue Component - 0.8117647 - Green Component - 0.8431373 - Red Component - 0.827451 - - Ansi 7 Color (Dark) - - Blue Component - 0.8117647 - Green Component - 0.8431373 - Red Component - 0.827451 - - Ansi 7 Color (Light) - - Blue Component - 0.8117647 - Green Component - 0.8431373 - Red Component - 0.827451 - - Ansi 8 Color - - Blue Component - 0.3254902 - Green Component - 0.3411765 - Red Component - 0.3333333 - - Ansi 8 Color (Dark) - - Blue Component - 0.3254902 - Green Component - 0.3411765 - Red Component - 0.3333333 - - Ansi 8 Color (Light) - - Blue Component - 0.3254902 - Green Component - 0.3411765 - Red Component - 0.3333333 - - Ansi 9 Color - - Blue Component - 0.1607843 - Green Component - 0.1607843 - Red Component - 0.9372549 - - Ansi 9 Color (Dark) - - Blue Component - 0.1607843 - Green Component - 0.1607843 - Red Component - 0.9372549 - - Ansi 9 Color (Light) - - Blue Component - 0.1607843 - Green Component - 0.1607843 - Red Component - 0.9372549 - - BM Growl - - Background Color - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Background Color (Dark) - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Background Color (Light) - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Background Image Location - - Background Image Mode - 1 - Badge Color - - Alpha Component - 0.5 - Blue Component - 0.13960540294647217 - Color Space - P3 - Green Component - 0.25479039549827576 - Red Component - 0.92929404973983765 - - Badge Color (Dark) - - Alpha Component - 0.5 - Blue Component - 0.13960540294647217 - Color Space - P3 - Green Component - 0.25479039549827576 - Red Component - 0.92929404973983765 - - Badge Color (Light) - - Alpha Component - 0.5 - Blue Component - 0.13960540294647217 - Color Space - P3 - Green Component - 0.25479039549827576 - Red Component - 0.92929404973983765 - - Blink Allowed - - Blinking Cursor - - Blur - - Bold Color - - Blue Component - 1 - Green Component - 1 - Red Component - 1 - - Bold Color (Dark) - - Blue Component - 1 - Green Component - 1 - Red Component - 1 - - Bold Color (Light) - - Blue Component - 1 - Green Component - 1 - Red Component - 1 - - Character Encoding - 4 - Close Sessions On End - - Columns - 80 - Command - - Cursor Boost (Dark) - 0.01 - Cursor Color - - Blue Component - 1 - Green Component - 1 - Red Component - 1 - - Cursor Color (Dark) - - Blue Component - 1 - Green Component - 1 - Red Component - 1 - - Cursor Color (Light) - - Blue Component - 1 - Green Component - 1 - Red Component - 1 - - Cursor Guide Color - - Alpha Component - 0.25 - Blue Component - 0.99125725030899048 - Color Space - P3 - Green Component - 0.92047786712646484 - Red Component - 0.74862593412399292 - - Cursor Guide Color (Dark) - - Alpha Component - 0.25 - Blue Component - 0.99125725030899048 - Color Space - P3 - Green Component - 0.92047786712646484 - Red Component - 0.74862593412399292 - - Cursor Guide Color (Light) - - Alpha Component - 0.25 - Blue Component - 0.99125725030899048 - Color Space - P3 - Green Component - 0.92047786712646484 - Red Component - 0.74862593412399292 - - Cursor Shadow - - Cursor Text Color - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Cursor Text Color (Dark) - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Cursor Text Color (Light) - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Cursor Type - 1 - Custom Command - No - Custom Directory - Advanced - Default Bookmark - No - Description - Default - Disable Window Resizing - - Draw Powerline Glyphs - - Enable Progress Bars - - Faint Text Alpha - 1 - Faint Text Alpha (Dark) - 1 - Flashing Bell - - Foreground Color - - Blue Component - 1 - Green Component - 1 - Red Component - 1 - - Foreground Color (Dark) - - Blue Component - 1 - Green Component - 1 - Red Component - 1 - - Foreground Color (Light) - - Blue Component - 1 - Green Component - 1 - Red Component - 1 - - Guid - 3712D82E-60F8-4B0B-9F2E-5F21BC701367 - Has Hotkey - - Horizontal Spacing - 1 - HotKey Activated By Modifier - - HotKey Alternate Shortcuts - - HotKey Characters - - HotKey Characters Ignoring Modifiers - - HotKey Key Code - 0 - HotKey Modifier Activation - 0 - HotKey Modifier Flags - 0 - HotKey Window Animates - - HotKey Window AutoHides - - HotKey Window Dock Click Action - 0 - HotKey Window Floats - - HotKey Window Reopens On Activation - - Icon - 1 - Idle Code - 0 - Initial Use Transparency - - Jobs to Ignore - - rlogin - ssh - slogin - telnet - - Keyboard Map - - 0x2d-0x100000-0x2c - - Action - 28 - Apply Mode - 0 - Escaping - 2 - Text - 3712D82E-60F8-4B0B-9F2E-5F21BC701367 - Version - 2 - - 0x68-0x100000-0x4 - - Action - 28 - Apply Mode - 0 - Escaping - 2 - Text - 3712D82E-60F8-4B0B-9F2E-5F21BC701367 - Version - 2 - - 0xf700-0x300000-0x7e - - Action - 20 - Apply Mode - 0 - Escaping - 2 - Text - - Version - 2 - - 0xf701-0x300000-0x7d - - Action - 21 - Apply Mode - 0 - Escaping - 2 - Text - - Version - 2 - - 0xf702-0x300000-0x7b - - Action - 18 - Apply Mode - 0 - Escaping - 2 - Text - - Version - 2 - - 0xf703-0x300000-0x7c - - Action - 19 - Apply Mode - 0 - Escaping - 2 - Text - - Version - 2 - - - Link Color - - Alpha Component - 1 - Blue Component - 0.7093239426612854 - Color Space - P3 - Green Component - 0.35333043336868286 - Red Component - 0.14513972401618958 - - Link Color (Dark) - - Alpha Component - 1 - Blue Component - 0.7093239426612854 - Color Space - P3 - Green Component - 0.35333043336868286 - Red Component - 0.14513972401618958 - - Link Color (Light) - - Alpha Component - 1 - Blue Component - 0.7093239426612854 - Color Space - P3 - Green Component - 0.35333043336868286 - Red Component - 0.14513972401618958 - - Load Shell Integration Automatically - - Match Background Color - - Alpha Component - 1 - Blue Component - 0.32116127014160156 - Color Space - P3 - Green Component - 0.98600882291793823 - Red Component - 0.99697142839431763 - - Match Background Color (Dark) - - Alpha Component - 1 - Blue Component - 0.32116127014160156 - Color Space - P3 - Green Component - 0.98600882291793823 - Red Component - 0.99697142839431763 - - Match Background Color (Light) - - Alpha Component - 1 - Blue Component - 0.32116127014160156 - Color Space - P3 - Green Component - 0.98600882291793823 - Red Component - 0.99697142839431763 - - Minimum Contrast - 0.0 - Mouse Reporting - - Name - Zsh - Non Ascii Font - Monaco 12 - Non-ASCII Anti Aliased - - Normal Font - MesloLGS-NF-Regular 14 - Only The Default BG Color Uses Transparency - - Open Password Manager Automatically - - Open Toolbelt - - Option Key Sends - 0 - Prompt Before Closing 2 - 2 - Right Option Key Sends - 0 - Rows - 25 - Screen - -2 - Scrollback Lines - 0 - Selected Text Color - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Selected Text Color (Dark) - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Selected Text Color (Light) - - Blue Component - 0 - Green Component - 0 - Red Component - 0 - - Selection Color - - Blue Component - 1 - Green Component - 0.8353 - Red Component - 0.7098 - - Selection Color (Dark) - - Blue Component - 1 - Green Component - 0.8353 - Red Component - 0.7098 - - Selection Color (Light) - - Blue Component - 1 - Green Component - 0.8353 - Red Component - 0.7098 - - Send Code When Idle - - Set Local Environment Vars - 0 - Shortcut - - Show Mark Indicators - - Show Offscreen Command line - - Show Status Bar - - Show Timestamps - 0 - Silence Bell - - Space - 0 - Status Bar Layout - - advanced configuration - - algorithm - 1 - auto-rainbow style - 3 - font - .AppleSystemUIFont 12 - remove empty components - - - components - - - class - iTermStatusBarJobComponent - configuration - - knobs - - base: compression resistance - 1 - base: priority - 5 - maxwidth - +infinity - minwidth - 0 - shared text color - - Alpha Component - 1 - Blue Component - 0.63590961694717407 - Color Space - P3 - Green Component - 0.6414334774017334 - Red Component - 0.86000317335128784 - - - layout advanced configuration dictionary value - - algorithm - 1 - auto-rainbow style - 3 - font - .AppleSystemUIFont 12 - remove empty components - - - - - - class - iTermStatusBarSpringComponent - configuration - - knobs - - base: compression resistance - 1 - base: priority - 5 - iTermStatusBarSpringComponentSizeMultipleKey - 1 - iTermStatusBarSpringComponentSpringConstantKey - 0.01 - shared text color - - Alpha Component - 1 - Blue Component - 0.65958398580551147 - Color Space - P3 - Green Component - 0.89919322729110718 - Red Component - 0.8796347975730896 - - - layout advanced configuration dictionary value - - algorithm - 1 - auto-rainbow style - 3 - font - .AppleSystemUIFont 12 - remove empty components - - - - - - class - iTermStatusBarSpringComponent - configuration - - knobs - - base: compression resistance - 1 - base: priority - 5 - iTermStatusBarSpringComponentSizeMultipleKey - 1 - iTermStatusBarSpringComponentSpringConstantKey - 0.01 - shared text color - - Alpha Component - 1 - Blue Component - 0.69797295331954956 - Color Space - P3 - Green Component - 0.89270001649856567 - Red Component - 0.68831330537796021 - - - layout advanced configuration dictionary value - - algorithm - 1 - auto-rainbow style - 3 - font - .AppleSystemUIFont 12 - remove empty components - - - - - - class - iTermStatusBarNetworkUtilizationComponent - configuration - - knobs - - base: priority - 5 - shared text color - - Alpha Component - 1 - Blue Component - 0.89110654592514038 - Color Space - P3 - Green Component - 0.81993860006332397 - Red Component - 0.67023450136184692 - - - layout advanced configuration dictionary value - - algorithm - 1 - auto-rainbow style - 3 - font - .AppleSystemUIFont 12 - remove empty components - - - - - - class - iTermStatusBarMemoryUtilizationComponent - configuration - - knobs - - base: priority - 5 - shared text color - - Alpha Component - 1 - Blue Component - 0.88136154413223267 - Color Space - P3 - Green Component - 0.63362252712249756 - Red Component - 0.71302109956741333 - - - layout advanced configuration dictionary value - - algorithm - 1 - auto-rainbow style - 3 - font - .AppleSystemUIFont 12 - remove empty components - - - - - - class - iTermStatusBarCPUUtilizationComponent - configuration - - knobs - - base: compression resistance - 1 - base: priority - 5 - shared text color - - Alpha Component - 1 - Blue Component - 0.76881867647171021 - Color Space - P3 - Green Component - 0.64143049716949463 - Red Component - 0.86000508069992065 - - - layout advanced configuration dictionary value - - algorithm - 1 - auto-rainbow style - 3 - font - .AppleSystemUIFont 12 - remove empty components - - - - - - - Sync Title - - Tab Color - - Alpha Component - 1 - Blue Component - 0.5542144775390625 - Color Space - P3 - Green Component - 0.2049407958984375 - Red Component - 0.0 - - Tags - - Terminal Type - xterm-256color - Thin Strokes - 4 - Title Components - 6 - Transparency - 0.48736702127659576 - Unicode Normalization - 0 - Unlimited Scrollback - - Use Bold Font - - Use Bright Bold - - Use Italic Font - - Use Non-ASCII Font - - Use Separate Colors for Light and Dark Mode - - Use Tab Color - - Use Tab Color (Dark) - - Use Underline Color (Dark) - - Vertical Spacing - 1 - Visual Bell - - Window Type - 0 - Working Directory - ~ - - - OnlyWhenMoreTabs - - OpenArrangementAtStartup - - OpenNoWindowsAtStartup - - PerPaneBackgroundImage - - PointerActions - - Button,1,1,, - - Action - kContextMenuPointerAction - - Button,2,1,, - - Action - kPasteFromClipboardPointerAction - - Gesture,ThreeFingerSwipeDown,, - - Action - kPrevWindowPointerAction - - Gesture,ThreeFingerSwipeLeft,, - - Action - kPrevTabPointerAction - - Gesture,ThreeFingerSwipeRight,, - - Action - kNextTabPointerAction - - Gesture,ThreeFingerSwipeUp,, - - Action - kNextWindowPointerAction - - - Print In Black And White - - PromptOnQuit - - QuitWhenAllWindowsClosed - - RestoreWindowsToSameSpaces - - SavePasteHistory - - SeparateStatusBarsPerPane - - ShowFullScreenTabBar - - ShowPaneTitles - - ShowPaneTitlesEvenIfOnlyOnePane - - ShowSecureKeyboardEntryIndicator - - SmartPlacement - - SoundForEsc - - SplitPaneDimmingAmount - 0.32218959603658537 - StatusBarPosition - 1 - StretchTabsToFillBar - - SwitchPaneModifier - 6 - SwitchWindowModifier - 9 - TabStyleWithAutomaticOption - 5 - TabViewType - 0 - TerminalMargin - 10 - TerminalVMargin - 10 - TmuxSyncClipboard - - URLHandlersByGuid - - https - 3712D82E-60F8-4B0B-9F2E-5F21BC701367 - - UseBorder - - UseMetal - - UseSystemCursorWhenPossible - - VisualIndicatorForEsc - - WindowNumber - - findMode_iTerm - 0 - kCPKSelectionViewPreferredModeKey - 7 - kCPKSelectionViewShowHSBTextFieldsKey - - metalMaximizeThroughput - - - diff --git a/home/dot_config/nvim/lua/config/keymaps.lua b/home/dot_config/nvim/lua/config/keymaps.lua index 1110868..b22d7e1 100644 --- a/home/dot_config/nvim/lua/config/keymaps.lua +++ b/home/dot_config/nvim/lua/config/keymaps.lua @@ -27,7 +27,7 @@ map("i", "", "^", { desc = "Line Start" }) map("i", "", "", { desc = "Line End" }) map("c", "", "", { desc = "Line Start" }) --- Cmd chords reach Nvim inside herdr (kitty keyboard protocol); tmux drops Cmd. +-- Command shortcuts for terminals that support the kitty keyboard protocol. map("n", "", "", { remap = true, desc = "Find Files" }) map({ "n", "i", "x" }, "", "w", { desc = "Save File" }) map("n", "", "gcc", { remap = true, desc = "Toggle Comment" }) diff --git a/home/dot_config/starship.toml b/home/dot_config/starship.toml index 91ef207..71976dd 100644 --- a/home/dot_config/starship.toml +++ b/home/dot_config/starship.toml @@ -8,11 +8,11 @@ add_newline = false format = '$directory$git_branch$git_status$git_state$direnv$jobs$character ' right_format = '($username$hostname )$cmd_duration$status' -palette = 'froppa' +palette = 'default' # โ”€โ”€ Palette โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ -[palettes.froppa] +[palettes.default] blue = '#5f87d7' light = '#87afff' purple = '#d75fd7' diff --git a/home/dot_config/zed/private_settings.json b/home/dot_config/zed/private_settings.json index 275d64c..ddbc978 100644 --- a/home/dot_config/zed/private_settings.json +++ b/home/dot_config/zed/private_settings.json @@ -246,10 +246,6 @@ "sidebar_side": "right", "button": true, "dock": "right", - "inline_assistant_model": { - "provider": "openai", - "model": "gpt-5.6-terra" - }, "default_profile": "write" }, "inlay_hints": { diff --git a/home/dot_exports.tmpl b/home/dot_exports.tmpl index 2c9ff39..bc71867 100644 --- a/home/dot_exports.tmpl +++ b/home/dot_exports.tmpl @@ -12,7 +12,6 @@ export MANPAGER='less -X' {{- if and (eq .chezmoi.os "darwin") .features.brew }} export HOMEBREW_BAT=1 -export HOMEBREW_GITHUB_API_TOKEN={{ onepasswordRead "op://Personal/Homebrew GitHub API Token/credential" | trim }} export HOMEBREW_NO_AUTO_UPDATE=1 export HOMEBREW_NO_ENV_HINTS=1 {{- end }} diff --git a/home/dot_hammerspoon/init.lua b/home/dot_hammerspoon/init.lua index 014bc42..7cdd267 100644 --- a/home/dot_hammerspoon/init.lua +++ b/home/dot_hammerspoon/init.lua @@ -133,12 +133,4 @@ Keep.ghostty = hs.eventtap.new({ hs.eventtap.event.types.keyDown }, function(eve return true end):start() --- โ”€โ”€ VS Code: open ~/work โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - -hs.hotkey.bind({ "cmd", "shift" }, "ยด", function() - hs.osascript.applescript('tell application "System Events" to keystroke "o" using {command down}') - hs.osascript.applescript('tell application "System Events" to keystroke "~/work"') - hs.osascript.applescript('tell application "System Events" to key code 36') -- Enter -end) - hs.alert.show("Hammerspoon config reloaded") diff --git a/home/dot_local/bin/executable_clip-serve b/home/dot_local/bin/executable_clip-serve index dfd2456..15aefb5 100644 --- a/home/dot_local/bin/executable_clip-serve +++ b/home/dot_local/bin/executable_clip-serve @@ -1,6 +1,6 @@ #!/bin/sh # launchd starts one copy per connection to ~/.cache/clip.sock (see -# com.froppa.clip-serve.plist) with the socket as stdin, stdout and stderr. +# local.dotfiles.clip-serve.plist) with the socket as stdin, stdout and stderr. # It writes the clipboard image as PNG, or nothing when there is none; text # never leaves this way. ssht forwards the socket, and the wl-paste shim on # the far side reads it for Claude Code's Ctrl-V image paste. diff --git a/home/dot_local/bin/symlink_depot.tmpl b/home/dot_local/bin/symlink_depot.tmpl deleted file mode 100644 index 0497361..0000000 --- a/home/dot_local/bin/symlink_depot.tmpl +++ /dev/null @@ -1 +0,0 @@ -{{ joinPath .chezmoi.homeDir ".cargo/bin/depot" }} diff --git a/home/dot_zsh_completions b/home/dot_zsh_completions index 1d433d3..85b86cc 100644 --- a/home/dot_zsh_completions +++ b/home/dot_zsh_completions @@ -41,8 +41,3 @@ fi if (( $+commands[gh] )); then source <(gh completion -s zsh 2>/dev/null) fi - -# Generated by the installed Depot version; no stale completion file to refresh. -if (( $+commands[depot] )); then - source <(depot completions zsh 2>/dev/null) -fi diff --git a/home/dot_zshrc b/home/dot_zshrc index ef67cde..5cdb4cd 100644 --- a/home/dot_zshrc +++ b/home/dot_zshrc @@ -139,35 +139,6 @@ _source_plugin() { _source_plugin fzf-tab _source_plugin zsh-autosuggestions -# โ”€โ”€ Herdr โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - -# Ghostty binds the same Hyper chords as Herdr. While Herdr runs, switch -# this surface to Ghostty's `herdr` key table so the chords reach Herdr. -# Skipped inside Herdr panes: a nested client must not reset the table. -if [[ $OSTYPE == darwin* && $TERM_PROGRAM == ghostty ]] && - (( $+commands[herdr] && $+commands[osascript] )); then - herdr() { - [[ -n $HERDR_ENV ]] && { command herdr "$@"; return } - local id rc - id=$(osascript -e 'tell application "Ghostty" - set t to focused terminal of selected tab of front window - perform action "activate_key_table:herdr" on t - return id of t - end tell' 2>&1) || { - # Usually Automation denied (-1743); macOS then never asks again. - print -u2 "herdr: Ghostty keeps the Hyper chords: ${id##*: }" - print -u2 "herdr: run 'tccutil reset AppleEvents com.mitchellh.ghostty', then herdr again and allow" - id= - } - command herdr "$@" - rc=$? - [[ -n $id ]] && osascript -e 'on run argv - tell application "Ghostty" to perform action "deactivate_all_key_tables" on terminal id (item 1 of argv) - end run' "$id" >/dev/null 2>&1 - return rc - } -fi - # โ”€โ”€ Prompt โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (( $+commands[starship] )) && diff --git a/home/private_Library/private_LaunchAgents/com.froppa.clip-serve.plist.tmpl b/home/private_Library/private_LaunchAgents/local.dotfiles.clip-serve.plist.tmpl similarity index 94% rename from home/private_Library/private_LaunchAgents/com.froppa.clip-serve.plist.tmpl rename to home/private_Library/private_LaunchAgents/local.dotfiles.clip-serve.plist.tmpl index e960660..b06f111 100644 --- a/home/private_Library/private_LaunchAgents/com.froppa.clip-serve.plist.tmpl +++ b/home/private_Library/private_LaunchAgents/local.dotfiles.clip-serve.plist.tmpl @@ -5,7 +5,7 @@ Label - com.froppa.clip-serve + local.dotfiles.clip-serve ProgramArguments {{ .chezmoi.homeDir }}/.local/bin/clip-serve diff --git a/home/private_dot_ssh/private_config.tmpl b/home/private_dot_ssh/private_config.tmpl index 6d7e986..90ddb60 100644 --- a/home/private_dot_ssh/private_config.tmpl +++ b/home/private_dot_ssh/private_config.tmpl @@ -10,18 +10,9 @@ Include ~/.ssh/config.local HashKnownHosts no # Defaults for every host that config.local does not pin. No IdentitiesOnly -# here: agent keys (local or 1Password) are offered alongside the default file. +# here: local agent keys are offered alongside the default file. Host * IgnoreUnknown UseKeychain AddKeysToAgent yes UseKeychain yes IdentityFile ~/.ssh/id_ed25519 - -# Agent selection: the local agent behind SSH_AUTH_SOCK wins whenever it holds -# keys; 1Password's agent is the fallback. ssh-add exits 0 only when the agent -# has identities, and ssh keeps the first IdentityAgent it matches. -Match exec "ssh-add -l >/dev/null 2>&1" - IdentityAgent SSH_AUTH_SOCK - -Host * - IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock" diff --git a/scripts/check-public-config.py b/scripts/check-public-config.py new file mode 100644 index 0000000..84e09fe --- /dev/null +++ b/scripts/check-public-config.py @@ -0,0 +1,79 @@ +"""Keep tracked workstation configuration free of machine and credential data.""" + +import ipaddress +import json +from pathlib import Path +import re +import subprocess + + +ROOT = Path(__file__).resolve().parents[1] +CONFIG_APPS = { + "Code", "ghostty", "git", "mise", "nvim", "starship.toml", + "systemd", "tmux", "zed", "zsh", +} +MANAGED_COMMANDS = {"clip-serve", "follow-main.sh", "wl-paste"} +PATTERNS = { + "machine home path": r"/(?:Users|home)/(?!linuxbrew(?:/|\b))[A-Za-z0-9_.-]+/", + "password-manager item": r"op://[^\s\"']+", + "private key": r"-----BEGIN (?:[A-Z0-9]+ )?PRIVATE KEY-----", + "credential value": r"\b(?:gh[pousr]_[A-Za-z0-9]{20,}|sk-(?:proj-)?[A-Za-z0-9_-]{20,}|AKIA[A-Z0-9]{16})\b", +} + + +def findings(path, text): + """Return categories only, so a CI failure never prints confidential values.""" + issues = [] + for category, pattern in PATTERNS.items(): + if re.search(pattern, text): + issues.append(category) + for value in re.findall(r"\b[A-Za-z0-9_.-]+@(?:[A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]+", text): + if value not in {"git@github.com", "ci@example.invalid"}: + issues.append("literal user or SSH identity") + break + for value in re.findall(r"(?/dev/null 2>&1 || fail "chezmoi is required" command -v python3 >/dev/null 2>&1 || fail "python3 is required" command -v zsh >/dev/null 2>&1 || fail "zsh is required" +section "Checking public configuration boundaries" +python3 scripts/check-public-config.py + section "Running shellcheck" # No mapfile: must also run on macOS' bash 3.2 @@ -66,7 +69,7 @@ chezmoi execute-template \ < home/.chezmoi.toml.tmpl \ > "${rendered_config}" -cat "${rendered_config}" + chezmoi --config "${rendered_config}" data >/dev/null @@ -93,9 +96,6 @@ grep -q '^personal = false$' "${rendered_work_config}" || fail "WORK=true should section "Checking safe adoption defaults" -[[ -f home/dot_local/bin/symlink_depot.tmpl ]] || fail "Depot must resolve to the standalone Cargo installation" -grep -Fq '".cargo/bin/depot"' home/dot_local/bin/symlink_depot.tmpl || fail "Depot link must target the standalone installation" -grep -Fq 'source <(depot completions zsh 2>/dev/null)' home/dot_zsh_completions || fail "Depot completion must follow the installed version" [[ -f home/create_dot_gitconfig.tmpl ]] || fail "Git defaults must be create-only" [[ ! -e home/dot_gitconfig.tmpl ]] || fail "Git config must not overwrite an existing setup" @@ -108,14 +108,7 @@ grep -Fq "alias confgit='chezmoi edit --apply ~/.config/git/dotfiles.gitconfig'" [[ -f home/dot_config/ghostty/config ]] || fail "Ghostty config must be named config, the one path every Ghostty version reads" grep -Fqx '.config/ghostty/config.ghostty' home/.chezmoiremove || fail "a stale config.ghostty would load beside the managed config" grep -Fqx "alias ch='chezmoi'" home/dot_aliases || fail "ch must alias chezmoi" -grep -Fq 'command = /bin/zsh' home/dot_config/ghostty/config || fail "Ghostty must launch zsh; herdr is started on demand" grep -Fq 'config-file = ?config.local' home/dot_config/ghostty/config || fail "Ghostty must load the optional machine-local override last" -! grep -qE '^keybind = (performable:)?ctrl\+alt\+super\+[^=]+=text:' home/dot_config/ghostty/config || fail "Hyper chords must reach herdr, not be rewritten into tmux prefix bytes" -! grep -qE '^keybind = ctrl\+alt\+super\+[^=]+=[^i]' home/dot_config/ghostty/config || fail "Hyper actions must be performable: a menu shortcut fires before the herdr key table" -grep -q 'activate_key_table:herdr' home/dot_zshrc || fail "the herdr wrapper must hand Ghostty's Hyper chords to herdr" -[[ "$(grep -oE '^keybind = (performable:)?ctrl\+alt\+super\+[^=]+' home/dot_config/ghostty/config | sed -E 's/^keybind = (performable:)?//' | grep -v '+equal$')" == "$(grep -E '^keybind = herdr/performable:.+=activate_key_table:herdr$' home/dot_config/ghostty/config | sed 's/^keybind = herdr\/performable://; s/=activate_key_table:herdr$//')" ]] || fail "the herdr key table must pass every Hyper chord Ghostty binds through to herdr" -! grep -qE '^keybind = herdr/.+=unbind$' home/dot_config/ghostty/config || fail "unbind in a key table falls through to the default binding; use a performable no-op" -[[ ! -e home/dot_config/ghostty/herdr.ghostty ]] || fail "herdr is the default; the herdr.ghostty overlay is gone" grep -Fq "bind -n M-C-a if -F '#{@ssht}' 'send-keys M-C-a' 'switch-client -T prefix'" home/dot_config/tmux/tmux.conf || fail "Hyper chords must drive the remote tmux in an ssht pane" grep -Fq 'tmux*:RGB:extkeys' home/dot_config/tmux/tmux.conf || fail "a remote tmux nested by ssht must get extended keys for Claude Code's Shift-Enter" grep -Fq 'add-zsh-hook precmd _terminal_modes_reset' home/dot_config/zsh/terminal.zsh || fail "the prompt must switch off mouse and key reporting a dead program left on" @@ -127,14 +120,12 @@ grep -Fq 'xterm-ghostty:RGB:extkeys' home/dot_config/tmux/tmux.conf || fail "Gho grep -Fq 'set -s extended-keys on' home/dot_config/tmux/tmux.conf || fail "tmux must pass modified keys to Claude Code" grep -Fq 'set -g focus-events on' home/dot_config/tmux/tmux.conf || fail "tmux must pass focus events to Claude Code" grep -Fq 'set -g assume-paste-time 0' home/dot_config/tmux/tmux.conf || fail "tmux must disable paste timing as a global session option" -grep -Fq '.local/bin/depot' home/.chezmoiignore || fail "the Depot symlink must not replace a locally installed binary on Linux" -sed -n '/ne .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq 'Library/LaunchAgents/com.froppa.clip-serve.plist' || fail "the clipboard LaunchAgent is macOS-only" +sed -n '/ne .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq 'Library/LaunchAgents/local.dotfiles.clip-serve.plist' || fail "the clipboard LaunchAgent is macOS-only" sed -n '/eq .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq '.local/bin/wl-paste' || fail "the wl-paste shim must not land on the Mac" [[ -x home/dot_local/bin/executable_follow-main.sh && -f home/dot_config/systemd/user/follow-main.timer ]] || fail "follow-main must ship its script and timer for Linux" sed -n '/eq .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq '.config/systemd' || fail "systemd user units must not be applied on macOS" grep -Fq 'MouseDragEnd1Pane send -X copy-selection' home/dot_config/tmux/tmux.conf || fail "mouse selection must not snap the view back to the bottom" grep -Fq 'xterm-ghostty:RGB:extkeys:hyperlinks' home/dot_config/tmux/tmux.conf || fail "tmux must pass OSC 8 hyperlinks through to Ghostty" -! grep -rqE '192\.168|100\.[0-9]+\.' home/dot_config/tmux || fail "host names and addresses belong in the unmanaged tmux *.local files" if find home/private_dot_ssh -type f ! -name private_config.tmpl -print -quit | grep -q .; then fail "SSH key material must not be managed" fi diff --git a/tests/test_public_config.py b/tests/test_public_config.py new file mode 100644 index 0000000..412b987 --- /dev/null +++ b/tests/test_public_config.py @@ -0,0 +1,40 @@ +"""Exercise publication boundaries without using real machine or secret data.""" + +import importlib.util +from pathlib import Path +import unittest + + +spec = importlib.util.spec_from_file_location( + "public_config", Path(__file__).resolve().parents[1] / "scripts/check-public-config.py" +) +check = importlib.util.module_from_spec(spec) +spec.loader.exec_module(check) + + +class PublicConfigTests(unittest.TestCase): + def test_rejects_machine_and_credential_data(self): + for text in ( + "/Users/" + "example/private/config", "/home/" + "example/private/config", + "op" + "://example/item/password", "ssh example@" + "host.example.invalid", + "https://192.0." + "2.123/api", "100.64." + "0.42", + "-----BEGIN " + "PRIVATE KEY-----", "ghp_" + "x" * 30, + ): + with self.subTest(text=text): + self.assertTrue(check.findings("README.md", text)) + + def test_allows_portable_paths_and_local_socket_bindings(self): + self.assertFalse(check.findings( + "README.md", "$HOME/.ssh/config.local /home/linuxbrew/.linuxbrew 127.0.0.1" + )) + + def test_requires_review_for_new_managed_apps_and_commands(self): + self.assertTrue(check.findings("home/dot_config/example/config.toml", "")) + self.assertTrue(check.findings("home/dot_local/bin/executable_example", "")) + self.assertFalse(check.findings("home/dot_config/tmux/tmux.conf", "")) + + def test_model_selection_stays_unmanaged(self): + path = "home/dot_config/zed/private_settings.json" + self.assertTrue(check.findings(path, '{"language_models": {}}')) + self.assertTrue(check.findings(path, '{"agent": {"default_model": {}}}')) + self.assertFalse(check.findings(path, '{"agent": {"button": true}}')) diff --git a/tests/test_ubuntu_bootstrap.py b/tests/test_ubuntu_bootstrap.py index 49561ff..5f769d0 100644 --- a/tests/test_ubuntu_bootstrap.py +++ b/tests/test_ubuntu_bootstrap.py @@ -87,6 +87,37 @@ def test_linux_never_bootstraps_homebrew(self): self.assertEqual(result.returncode, 0, result.stderr) self.assertEqual(self.commands(), "") + def test_clipboard_reload_retires_only_its_previous_service(self): + agents = self.base / "Library/LaunchAgents" + agents.mkdir(parents=True) + previous = agents / "local.previous.clip-serve.plist" + current = agents / "local.dotfiles.clip-serve.plist" + unrelated = agents / "local.example.plist" + for path in (previous, current, unrelated): + path.touch() + self.stub("plutil", ''' +case "$6" in + */local.previous.clip-serve.plist) label=local.previous.clip-serve ;; + */local.dotfiles.clip-serve.plist) label=local.dotfiles.clip-serve ;; + *) exit 1 ;; +esac +case "$2" in + ProgramArguments.0) printf '%s\\n' "$HOME/.local/bin/clip-serve" ;; + Label) printf '%s\\n' "$label" ;; +esac +''') + self.stub("launchctl", 'printf "launchctl %s\\n" "$*" >> "$TEST_LOG"\n') + result = self.execute(self.render( + "home/.chezmoiscripts/run_onchange_after_45-load-clip-serve.sh.tmpl", system="darwin")) + self.assertEqual(result.returncode, 0, result.stderr) + self.assertFalse(previous.exists()) + self.assertTrue(current.exists()) + self.assertTrue(unrelated.exists()) + commands = self.commands() + self.assertIn("/local.previous.clip-serve", commands) + self.assertIn("launchctl bootstrap", commands) + self.assertNotIn("local.example", commands) + def test_darwin_preserves_brew_profiles(self): for work in (False, True): with self.subTest(work=work): @@ -146,7 +177,7 @@ def test_managed_files_exclude_mac_only_apps_on_linux(self): "--destination", str(self.base), "--override-data", json.dumps(data), "managed", "--exclude=externals", "--path-style=relative"], text=True) paths = output.splitlines() - for app in (".hammerspoon/init.lua", ".config/iterm2/com.googlecode.iterm2.plist"): + for app in (".hammerspoon/init.lua",): self.assertEqual(app in paths, system == "darwin", app) self.assertIn(".config/nvim/init.lua", paths) self.assertIn(".config/ghostty/config", paths) From 950794d52d17a465f04e72bf01968a750db788db Mon Sep 17 00:00:00 2001 From: froppa-agent <330570035+froppa-agent@users.noreply.github.com> Date: Mon, 12 Oct 2026 22:34:23 +0200 Subject: [PATCH 4/6] fix: avoid matching checker patterns --- scripts/check-public-config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/check-public-config.py b/scripts/check-public-config.py index 84e09fe..fd764b4 100644 --- a/scripts/check-public-config.py +++ b/scripts/check-public-config.py @@ -15,7 +15,7 @@ MANAGED_COMMANDS = {"clip-serve", "follow-main.sh", "wl-paste"} PATTERNS = { "machine home path": r"/(?:Users|home)/(?!linuxbrew(?:/|\b))[A-Za-z0-9_.-]+/", - "password-manager item": r"op://[^\s\"']+", + "password-manager item": r"\bop[:][/]{2}[^\s\"']+", "private key": r"-----BEGIN (?:[A-Z0-9]+ )?PRIVATE KEY-----", "credential value": r"\b(?:gh[pousr]_[A-Za-z0-9]{20,}|sk-(?:proj-)?[A-Za-z0-9_-]{20,}|AKIA[A-Z0-9]{16})\b", } From 78c5468ad11e4c65fd4d54d28ef91f4f4110de15 Mon Sep 17 00:00:00 2001 From: froppa-agent <330570035+froppa-agent@users.noreply.github.com> Date: Mon, 12 Oct 2026 23:06:26 +0200 Subject: [PATCH 5/6] refactor: retain portable workstation features --- home/.chezmoi.toml.tmpl | 4 +- home/.chezmoidata/40-packages.yml | 1 + home/.chezmoiignore | 2 +- .../run_onchange_20-install-pkgs.sh.tmpl | 2 +- ..._onchange_after_45-load-clip-serve.sh.tmpl | 14 +- home/dot_aws/cli/alias | 274 ------------------ home/dot_aws/config | 2 - home/dot_config/ghostty/config | 65 ++++- home/dot_config/git/dotfiles.gitconfig.tmpl | 1 + home/dot_config/herdr/config.toml | 46 +++ home/dot_config/nvim/lua/config/keymaps.lua | 2 +- home/dot_config/starship.toml | 4 +- home/dot_local/bin/executable_clip-serve | 2 +- home/dot_local/bin/executable_git-signlast | 16 + home/dot_zshrc | 29 ++ ....tmpl => com.froppa.clip-serve.plist.tmpl} | 2 +- home/private_dot_ssh/private_config.tmpl | 13 +- scripts/check-public-config.py | 79 ----- test.sh | 20 +- tests/test_public_config.py | 40 --- tests/test_ubuntu_bootstrap.py | 35 +-- 21 files changed, 192 insertions(+), 461 deletions(-) delete mode 100644 home/dot_aws/cli/alias delete mode 100644 home/dot_aws/config create mode 100644 home/dot_config/herdr/config.toml create mode 100644 home/dot_local/bin/executable_git-signlast rename home/private_Library/private_LaunchAgents/{local.dotfiles.clip-serve.plist.tmpl => com.froppa.clip-serve.plist.tmpl} (94%) delete mode 100644 scripts/check-public-config.py delete mode 100644 tests/test_public_config.py diff --git a/home/.chezmoi.toml.tmpl b/home/.chezmoi.toml.tmpl index 9b903fd..8924842 100644 --- a/home/.chezmoi.toml.tmpl +++ b/home/.chezmoi.toml.tmpl @@ -1,14 +1,12 @@ {{ $name := promptStringOnce . "name" "name" }} {{ $email := promptStringOnce . "email" "email" }} -{{/* WORK=true selects the work machine setup; anything else (incl. PERSONAL=true) is personal. */}} +{{/* WORK=true selects the work package set. */}} {{ $work := eq (env "WORK" | lower) "true" }} [data] name = {{ $name | quote }} email = {{ $email | quote }} -profile = {{ ternary "work" "personal" $work | quote }} work = {{ $work }} -personal = {{ not $work }} [github] refreshPeriod = "12h" diff --git a/home/.chezmoidata/40-packages.yml b/home/.chezmoidata/40-packages.yml index c23ce18..f113427 100644 --- a/home/.chezmoidata/40-packages.yml +++ b/home/.chezmoidata/40-packages.yml @@ -170,6 +170,7 @@ packages: - cocoapods - age-plugin-se - libimobiledevice + - herdr # Serial and embedded hardware # - minicom # - libftdi diff --git a/home/.chezmoiignore b/home/.chezmoiignore index 49f9bcc..5629097 100644 --- a/home/.chezmoiignore +++ b/home/.chezmoiignore @@ -22,7 +22,7 @@ {{ if ne .chezmoi.os "darwin" -}} .hammerspoon .config/raycast -Library/LaunchAgents/local.dotfiles.clip-serve.plist +Library/LaunchAgents/com.froppa.clip-serve.plist .local/bin/clip-serve {{ end -}} diff --git a/home/.chezmoiscripts/run_onchange_20-install-pkgs.sh.tmpl b/home/.chezmoiscripts/run_onchange_20-install-pkgs.sh.tmpl index 07e23a3..ef8fd40 100644 --- a/home/.chezmoiscripts/run_onchange_20-install-pkgs.sh.tmpl +++ b/home/.chezmoiscripts/run_onchange_20-install-pkgs.sh.tmpl @@ -25,7 +25,7 @@ brew "{{ . }}" cask "{{ . }}" {{ end -}} {{ end -}} -{{ if .personal -}} +{{ if not .work -}} {{ range .packages.personal.brews -}} brew "{{ . }}" {{ end -}} diff --git a/home/.chezmoiscripts/run_onchange_after_45-load-clip-serve.sh.tmpl b/home/.chezmoiscripts/run_onchange_after_45-load-clip-serve.sh.tmpl index f16ae21..d477294 100755 --- a/home/.chezmoiscripts/run_onchange_after_45-load-clip-serve.sh.tmpl +++ b/home/.chezmoiscripts/run_onchange_after_45-load-clip-serve.sh.tmpl @@ -3,20 +3,10 @@ set -eu # Reload the clipboard bridge whenever its LaunchAgent changes. -# plist-sha256: {{ include "private_Library/private_LaunchAgents/local.dotfiles.clip-serve.plist.tmpl" | sha256sum }} +# plist-sha256: {{ include "private_Library/private_LaunchAgents/com.froppa.clip-serve.plist.tmpl" | sha256sum }} -label=local.dotfiles.clip-serve +label=com.froppa.clip-serve mkdir -p "$HOME/.cache" -# Retire another label only when it launches this exact managed command. -for plist in "$HOME/Library/LaunchAgents/"*.plist; do - [ -f "$plist" ] || continue - program=$(plutil -extract ProgramArguments.0 raw -o - "$plist" 2>/dev/null) || continue - [ "$program" = "$HOME/.local/bin/clip-serve" ] || continue - previous=$(plutil -extract Label raw -o - "$plist" 2>/dev/null) || continue - [ "$previous" != "$label" ] || continue - launchctl bootout "gui/$(id -u)/$previous" 2>/dev/null || true - rm -f "$plist" -done launchctl bootout "gui/$(id -u)/$label" 2>/dev/null || true # bootout returns before teardown finishes; a lost race must not abort apply. launchctl bootstrap "gui/$(id -u)" "$HOME/Library/LaunchAgents/$label.plist" 2>/dev/null || diff --git a/home/dot_aws/cli/alias b/home/dot_aws/cli/alias deleted file mode 100644 index 9f54a9c..0000000 --- a/home/dot_aws/cli/alias +++ /dev/null @@ -1,274 +0,0 @@ -[toplevel] -id = sts get-caller-identity -region = configure get region -regions = ec2 describe-regions --query 'sort_by(Regions, &RegionName)[].RegionName' --output text - -cw = cloudwatch -logs = logs -ecs = ecs -sqs = sqs -sns = sns -s3 = s3 - -ls = !grep '^[^[:space:]#].*=' "${HOME}/.aws/cli/alias" | sort - -[command logs] -groups = describe-log-groups --query 'logGroups[].logGroupName' -groups-short = describe-log-groups --query 'logGroups[].logGroupName' --output text - -streams = describe-log-streams --log-group-name -streams-recent = describe-log-streams --log-group-name --order-by LastEventTime --descending - -tail = tail --follow --log-group-name -tail-since = tail --follow --since 30m --log-group-name -tail-short = tail --since 30m --log-group-name - -filter = filter-log-events --log-group-name -errors = filter-log-events \ - --log-group-name \ - --filter-pattern '?ERROR ?Error ?error ?FATAL ?Fatal ?panic ?PANIC ?exception' - -start = start-query --log-group-name -query = get-query-results --query-id - -# Example: -# aws logs insights "/ecs/example-service" "fields @timestamp, @message | sort @timestamp desc | limit 50" -# Every continuation line MUST be indented. This is an INI file: a line at -# column 0 is a new key, not part of the value above it, and the whole -# file fails to parse. The parser strips the indentation before the shell -# sees the alias, so the heredoc terminators below still reach the shell -# at column 0, where a <<'PY' heredoc needs them. -insights = !f() { - group=${1:?expected log group} - query=${2:?expected insights query} - start=$(date -u -d '30 minutes ago' '+%s' 2>/dev/null || python3 - <<'PY' - import time - print(int(time.time()) - 1800) - PY - ) - end=$(date -u '+%s' 2>/dev/null || python3 - <<'PY' - import time - print(int(time.time())) - PY - ) - aws logs start-query \ - --log-group-name "$group" \ - --start-time "$start" \ - --end-time "$end" \ - --query-string "$query" - }; f - -[command cloudwatch] -alarms = describe-alarms --query 'MetricAlarms[].{Name:AlarmName,State:StateValue,Metric:MetricName,Namespace:Namespace}' -alarms-alarm = describe-alarms --state-value ALARM --query 'MetricAlarms[].{Name:AlarmName,State:StateValue,Metric:MetricName,Namespace:Namespace}' -alarm = describe-alarms --alarm-names -history = describe-alarm-history --alarm-name - -metrics = list-metrics -metrics-ns = list-metrics --namespace -namespaces = list-metrics --query 'Metrics[].Namespace' --output text - -# Example: -# aws cw stat AWS/ECS CPUUtilization ClusterName=my-cluster,ServiceName=my-service Average 300 3600 -stat = !f() { - namespace=${1:?expected namespace} - metric=${2:?expected metric name} - dimensions=${3:-} - stat=${4:-Average} - period=${5:-300} - window=${6:-3600} - - end=$(date -u '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || python3 - <<'PY' - from datetime import datetime, timezone - print(datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')) - PY - ) - start=$(date -u -d "${window} seconds ago" '+%Y-%m-%dT%H:%M:%SZ' 2>/dev/null || python3 - <", "^", { desc = "Line Start" }) map("i", "", "", { desc = "Line End" }) map("c", "", "", { desc = "Line Start" }) --- Command shortcuts for terminals that support the kitty keyboard protocol. +-- Cmd chords reach Nvim inside herdr (kitty keyboard protocol); tmux drops Cmd. map("n", "", "", { remap = true, desc = "Find Files" }) map({ "n", "i", "x" }, "", "w", { desc = "Save File" }) map("n", "", "gcc", { remap = true, desc = "Toggle Comment" }) diff --git a/home/dot_config/starship.toml b/home/dot_config/starship.toml index 71976dd..91ef207 100644 --- a/home/dot_config/starship.toml +++ b/home/dot_config/starship.toml @@ -8,11 +8,11 @@ add_newline = false format = '$directory$git_branch$git_status$git_state$direnv$jobs$character ' right_format = '($username$hostname )$cmd_duration$status' -palette = 'default' +palette = 'froppa' # โ”€โ”€ Palette โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ -[palettes.default] +[palettes.froppa] blue = '#5f87d7' light = '#87afff' purple = '#d75fd7' diff --git a/home/dot_local/bin/executable_clip-serve b/home/dot_local/bin/executable_clip-serve index 15aefb5..dfd2456 100644 --- a/home/dot_local/bin/executable_clip-serve +++ b/home/dot_local/bin/executable_clip-serve @@ -1,6 +1,6 @@ #!/bin/sh # launchd starts one copy per connection to ~/.cache/clip.sock (see -# local.dotfiles.clip-serve.plist) with the socket as stdin, stdout and stderr. +# com.froppa.clip-serve.plist) with the socket as stdin, stdout and stderr. # It writes the clipboard image as PNG, or nothing when there is none; text # never leaves this way. ssht forwards the socket, and the wl-paste shim on # the far side reads it for Claude Code's Ctrl-V image paste. diff --git a/home/dot_local/bin/executable_git-signlast b/home/dot_local/bin/executable_git-signlast new file mode 100644 index 0000000..e78f5f0 --- /dev/null +++ b/home/dot_local/bin/executable_git-signlast @@ -0,0 +1,16 @@ +#!/bin/sh +# Sign the latest commit, or the latest N commits, using this repository's key. +set -eu +count=${1:-1} +case $count in ''|*[!0-9]*|0) echo 'usage: git signlast [count]' >&2; exit 2 ;; esac +[ "$#" -le 1 ] || { echo 'usage: git signlast [count]' >&2; exit 2; } +[ -z "$(git status --porcelain)" ] || { echo 'Commit or stash local changes first.' >&2; exit 1; } +if [ "$count" -eq 1 ]; then + exec git commit --amend --no-edit -S +fi +total=$(git rev-list --count HEAD) +[ "$count" -le "$total" ] || { echo 'Count exceeds the available commits.' >&2; exit 2; } +if [ "$count" -eq "$total" ]; then + exec git rebase --force-rebase --root --exec 'git commit --amend --no-edit -S' +fi +exec git rebase --force-rebase --exec 'git commit --amend --no-edit -S' "HEAD~$count" diff --git a/home/dot_zshrc b/home/dot_zshrc index 5cdb4cd..ef67cde 100644 --- a/home/dot_zshrc +++ b/home/dot_zshrc @@ -139,6 +139,35 @@ _source_plugin() { _source_plugin fzf-tab _source_plugin zsh-autosuggestions +# โ”€โ”€ Herdr โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + +# Ghostty binds the same Hyper chords as Herdr. While Herdr runs, switch +# this surface to Ghostty's `herdr` key table so the chords reach Herdr. +# Skipped inside Herdr panes: a nested client must not reset the table. +if [[ $OSTYPE == darwin* && $TERM_PROGRAM == ghostty ]] && + (( $+commands[herdr] && $+commands[osascript] )); then + herdr() { + [[ -n $HERDR_ENV ]] && { command herdr "$@"; return } + local id rc + id=$(osascript -e 'tell application "Ghostty" + set t to focused terminal of selected tab of front window + perform action "activate_key_table:herdr" on t + return id of t + end tell' 2>&1) || { + # Usually Automation denied (-1743); macOS then never asks again. + print -u2 "herdr: Ghostty keeps the Hyper chords: ${id##*: }" + print -u2 "herdr: run 'tccutil reset AppleEvents com.mitchellh.ghostty', then herdr again and allow" + id= + } + command herdr "$@" + rc=$? + [[ -n $id ]] && osascript -e 'on run argv + tell application "Ghostty" to perform action "deactivate_all_key_tables" on terminal id (item 1 of argv) + end run' "$id" >/dev/null 2>&1 + return rc + } +fi + # โ”€โ”€ Prompt โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ (( $+commands[starship] )) && diff --git a/home/private_Library/private_LaunchAgents/local.dotfiles.clip-serve.plist.tmpl b/home/private_Library/private_LaunchAgents/com.froppa.clip-serve.plist.tmpl similarity index 94% rename from home/private_Library/private_LaunchAgents/local.dotfiles.clip-serve.plist.tmpl rename to home/private_Library/private_LaunchAgents/com.froppa.clip-serve.plist.tmpl index b06f111..e960660 100644 --- a/home/private_Library/private_LaunchAgents/local.dotfiles.clip-serve.plist.tmpl +++ b/home/private_Library/private_LaunchAgents/com.froppa.clip-serve.plist.tmpl @@ -5,7 +5,7 @@ Label - local.dotfiles.clip-serve + com.froppa.clip-serve ProgramArguments {{ .chezmoi.homeDir }}/.local/bin/clip-serve diff --git a/home/private_dot_ssh/private_config.tmpl b/home/private_dot_ssh/private_config.tmpl index 90ddb60..c963344 100644 --- a/home/private_dot_ssh/private_config.tmpl +++ b/home/private_dot_ssh/private_config.tmpl @@ -10,9 +10,20 @@ Include ~/.ssh/config.local HashKnownHosts no # Defaults for every host that config.local does not pin. No IdentitiesOnly -# here: local agent keys are offered alongside the default file. +# here: agent keys (local or 1Password) are offered alongside the default file. Host * IgnoreUnknown UseKeychain AddKeysToAgent yes UseKeychain yes IdentityFile ~/.ssh/id_ed25519 + +# Agent selection: the local agent behind SSH_AUTH_SOCK wins whenever it holds +# keys; 1Password's agent is the fallback. ssh-add exits 0 only when the agent +# has identities, and ssh keeps the first IdentityAgent it matches. +Match exec "ssh-add -l >/dev/null 2>&1" + IdentityAgent SSH_AUTH_SOCK + +{{ if eq .chezmoi.os "darwin" -}} +Match exec 'test -S "$HOME/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"' + IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock" +{{ end -}} diff --git a/scripts/check-public-config.py b/scripts/check-public-config.py deleted file mode 100644 index fd764b4..0000000 --- a/scripts/check-public-config.py +++ /dev/null @@ -1,79 +0,0 @@ -"""Keep tracked workstation configuration free of machine and credential data.""" - -import ipaddress -import json -from pathlib import Path -import re -import subprocess - - -ROOT = Path(__file__).resolve().parents[1] -CONFIG_APPS = { - "Code", "ghostty", "git", "mise", "nvim", "starship.toml", - "systemd", "tmux", "zed", "zsh", -} -MANAGED_COMMANDS = {"clip-serve", "follow-main.sh", "wl-paste"} -PATTERNS = { - "machine home path": r"/(?:Users|home)/(?!linuxbrew(?:/|\b))[A-Za-z0-9_.-]+/", - "password-manager item": r"\bop[:][/]{2}[^\s\"']+", - "private key": r"-----BEGIN (?:[A-Z0-9]+ )?PRIVATE KEY-----", - "credential value": r"\b(?:gh[pousr]_[A-Za-z0-9]{20,}|sk-(?:proj-)?[A-Za-z0-9_-]{20,}|AKIA[A-Z0-9]{16})\b", -} - - -def findings(path, text): - """Return categories only, so a CI failure never prints confidential values.""" - issues = [] - for category, pattern in PATTERNS.items(): - if re.search(pattern, text): - issues.append(category) - for value in re.findall(r"\b[A-Za-z0-9_.-]+@(?:[A-Za-z0-9_-]+\.)+[A-Za-z0-9_-]+", text): - if value not in {"git@github.com", "ci@example.invalid"}: - issues.append("literal user or SSH identity") - break - for value in re.findall(r"(?/dev/null 2>&1 || fail "chezmoi is required" command -v python3 >/dev/null 2>&1 || fail "python3 is required" command -v zsh >/dev/null 2>&1 || fail "zsh is required" -section "Checking public configuration boundaries" -python3 scripts/check-public-config.py - section "Running shellcheck" # No mapfile: must also run on macOS' bash 3.2 @@ -69,16 +66,15 @@ chezmoi execute-template \ < home/.chezmoi.toml.tmpl \ > "${rendered_config}" - +cat "${rendered_config}" chezmoi --config "${rendered_config}" data >/dev/null grep -q '^name = "CI"$' "${rendered_config}" || fail "generated config missing CI name" grep -q '^email = "ci@example.invalid"$' "${rendered_config}" || fail "generated config missing CI email" -grep -q '^personal = true$' "${rendered_config}" || fail "default profile should be personal" grep -q '^work = false$' "${rendered_config}" || fail "work should default to false" -section "Testing WORK profile selection" +section "Testing WORK package selection" rendered_work_config="$(mktemp "${TMPDIR:-/tmp}/chezmoi-work.XXXXXX").toml" @@ -90,9 +86,7 @@ WORK=true chezmoi execute-template \ < home/.chezmoi.toml.tmpl \ > "${rendered_work_config}" -grep -q '^profile = "work"$' "${rendered_work_config}" || fail "WORK=true should select the work profile" grep -q '^work = true$' "${rendered_work_config}" || fail "WORK=true should set work = true" -grep -q '^personal = false$' "${rendered_work_config}" || fail "WORK=true should set personal = false" section "Checking safe adoption defaults" @@ -108,7 +102,14 @@ grep -Fq "alias confgit='chezmoi edit --apply ~/.config/git/dotfiles.gitconfig'" [[ -f home/dot_config/ghostty/config ]] || fail "Ghostty config must be named config, the one path every Ghostty version reads" grep -Fqx '.config/ghostty/config.ghostty' home/.chezmoiremove || fail "a stale config.ghostty would load beside the managed config" grep -Fqx "alias ch='chezmoi'" home/dot_aliases || fail "ch must alias chezmoi" +grep -Fq 'command = /bin/zsh' home/dot_config/ghostty/config || fail "Ghostty must launch zsh; herdr is started on demand" grep -Fq 'config-file = ?config.local' home/dot_config/ghostty/config || fail "Ghostty must load the optional machine-local override last" +! grep -qE '^keybind = (performable:)?ctrl\+alt\+super\+[^=]+=text:' home/dot_config/ghostty/config || fail "Hyper chords must reach herdr, not be rewritten into tmux prefix bytes" +! grep -qE '^keybind = ctrl\+alt\+super\+[^=]+=[^i]' home/dot_config/ghostty/config || fail "Hyper actions must be performable: a menu shortcut fires before the herdr key table" +grep -q 'activate_key_table:herdr' home/dot_zshrc || fail "the herdr wrapper must hand Ghostty's Hyper chords to herdr" +[[ "$(grep -oE '^keybind = (performable:)?ctrl\+alt\+super\+[^=]+' home/dot_config/ghostty/config | sed -E 's/^keybind = (performable:)?//' | grep -v '+equal$')" == "$(grep -E '^keybind = herdr/performable:.+=activate_key_table:herdr$' home/dot_config/ghostty/config | sed 's/^keybind = herdr\/performable://; s/=activate_key_table:herdr$//')" ]] || fail "the herdr key table must pass every Hyper chord Ghostty binds through to herdr" +! grep -qE '^keybind = herdr/.+=unbind$' home/dot_config/ghostty/config || fail "unbind in a key table falls through to the default binding; use a performable no-op" +[[ ! -e home/dot_config/ghostty/herdr.ghostty ]] || fail "herdr is the default; the herdr.ghostty overlay is gone" grep -Fq "bind -n M-C-a if -F '#{@ssht}' 'send-keys M-C-a' 'switch-client -T prefix'" home/dot_config/tmux/tmux.conf || fail "Hyper chords must drive the remote tmux in an ssht pane" grep -Fq 'tmux*:RGB:extkeys' home/dot_config/tmux/tmux.conf || fail "a remote tmux nested by ssht must get extended keys for Claude Code's Shift-Enter" grep -Fq 'add-zsh-hook precmd _terminal_modes_reset' home/dot_config/zsh/terminal.zsh || fail "the prompt must switch off mouse and key reporting a dead program left on" @@ -120,12 +121,13 @@ grep -Fq 'xterm-ghostty:RGB:extkeys' home/dot_config/tmux/tmux.conf || fail "Gho grep -Fq 'set -s extended-keys on' home/dot_config/tmux/tmux.conf || fail "tmux must pass modified keys to Claude Code" grep -Fq 'set -g focus-events on' home/dot_config/tmux/tmux.conf || fail "tmux must pass focus events to Claude Code" grep -Fq 'set -g assume-paste-time 0' home/dot_config/tmux/tmux.conf || fail "tmux must disable paste timing as a global session option" -sed -n '/ne .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq 'Library/LaunchAgents/local.dotfiles.clip-serve.plist' || fail "the clipboard LaunchAgent is macOS-only" +sed -n '/ne .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq 'Library/LaunchAgents/com.froppa.clip-serve.plist' || fail "the clipboard LaunchAgent is macOS-only" sed -n '/eq .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq '.local/bin/wl-paste' || fail "the wl-paste shim must not land on the Mac" [[ -x home/dot_local/bin/executable_follow-main.sh && -f home/dot_config/systemd/user/follow-main.timer ]] || fail "follow-main must ship its script and timer for Linux" sed -n '/eq .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq '.config/systemd' || fail "systemd user units must not be applied on macOS" grep -Fq 'MouseDragEnd1Pane send -X copy-selection' home/dot_config/tmux/tmux.conf || fail "mouse selection must not snap the view back to the bottom" grep -Fq 'xterm-ghostty:RGB:extkeys:hyperlinks' home/dot_config/tmux/tmux.conf || fail "tmux must pass OSC 8 hyperlinks through to Ghostty" +! grep -rqE '(^|[^a-z])evo(-|[^a-z]|$)|192\.168|100\.[0-9]+\.' home/dot_config/tmux || fail "host names and addresses belong in the unmanaged tmux *.local files" if find home/private_dot_ssh -type f ! -name private_config.tmpl -print -quit | grep -q .; then fail "SSH key material must not be managed" fi diff --git a/tests/test_public_config.py b/tests/test_public_config.py deleted file mode 100644 index 412b987..0000000 --- a/tests/test_public_config.py +++ /dev/null @@ -1,40 +0,0 @@ -"""Exercise publication boundaries without using real machine or secret data.""" - -import importlib.util -from pathlib import Path -import unittest - - -spec = importlib.util.spec_from_file_location( - "public_config", Path(__file__).resolve().parents[1] / "scripts/check-public-config.py" -) -check = importlib.util.module_from_spec(spec) -spec.loader.exec_module(check) - - -class PublicConfigTests(unittest.TestCase): - def test_rejects_machine_and_credential_data(self): - for text in ( - "/Users/" + "example/private/config", "/home/" + "example/private/config", - "op" + "://example/item/password", "ssh example@" + "host.example.invalid", - "https://192.0." + "2.123/api", "100.64." + "0.42", - "-----BEGIN " + "PRIVATE KEY-----", "ghp_" + "x" * 30, - ): - with self.subTest(text=text): - self.assertTrue(check.findings("README.md", text)) - - def test_allows_portable_paths_and_local_socket_bindings(self): - self.assertFalse(check.findings( - "README.md", "$HOME/.ssh/config.local /home/linuxbrew/.linuxbrew 127.0.0.1" - )) - - def test_requires_review_for_new_managed_apps_and_commands(self): - self.assertTrue(check.findings("home/dot_config/example/config.toml", "")) - self.assertTrue(check.findings("home/dot_local/bin/executable_example", "")) - self.assertFalse(check.findings("home/dot_config/tmux/tmux.conf", "")) - - def test_model_selection_stays_unmanaged(self): - path = "home/dot_config/zed/private_settings.json" - self.assertTrue(check.findings(path, '{"language_models": {}}')) - self.assertTrue(check.findings(path, '{"agent": {"default_model": {}}}')) - self.assertFalse(check.findings(path, '{"agent": {"button": true}}')) diff --git a/tests/test_ubuntu_bootstrap.py b/tests/test_ubuntu_bootstrap.py index 5f769d0..7685b08 100644 --- a/tests/test_ubuntu_bootstrap.py +++ b/tests/test_ubuntu_bootstrap.py @@ -43,7 +43,7 @@ def stub(self, name, body): def render(self, name, system="linux", distro="ubuntu", work=False): data = {"chezmoi": {"os": system, "osRelease": {"id": distro}}, - "personal": not work, "work": work} + "work": work} return subprocess.check_output([ CHEZMOI, "--source", str(ROOT), "--config", str(self.config), "--override-data", json.dumps(data), "execute-template", "--file", @@ -87,37 +87,6 @@ def test_linux_never_bootstraps_homebrew(self): self.assertEqual(result.returncode, 0, result.stderr) self.assertEqual(self.commands(), "") - def test_clipboard_reload_retires_only_its_previous_service(self): - agents = self.base / "Library/LaunchAgents" - agents.mkdir(parents=True) - previous = agents / "local.previous.clip-serve.plist" - current = agents / "local.dotfiles.clip-serve.plist" - unrelated = agents / "local.example.plist" - for path in (previous, current, unrelated): - path.touch() - self.stub("plutil", ''' -case "$6" in - */local.previous.clip-serve.plist) label=local.previous.clip-serve ;; - */local.dotfiles.clip-serve.plist) label=local.dotfiles.clip-serve ;; - *) exit 1 ;; -esac -case "$2" in - ProgramArguments.0) printf '%s\\n' "$HOME/.local/bin/clip-serve" ;; - Label) printf '%s\\n' "$label" ;; -esac -''') - self.stub("launchctl", 'printf "launchctl %s\\n" "$*" >> "$TEST_LOG"\n') - result = self.execute(self.render( - "home/.chezmoiscripts/run_onchange_after_45-load-clip-serve.sh.tmpl", system="darwin")) - self.assertEqual(result.returncode, 0, result.stderr) - self.assertFalse(previous.exists()) - self.assertTrue(current.exists()) - self.assertTrue(unrelated.exists()) - commands = self.commands() - self.assertIn("/local.previous.clip-serve", commands) - self.assertIn("launchctl bootstrap", commands) - self.assertNotIn("local.example", commands) - def test_darwin_preserves_brew_profiles(self): for work in (False, True): with self.subTest(work=work): @@ -171,7 +140,7 @@ def test_managed_files_exclude_mac_only_apps_on_linux(self): for system in ("darwin", "linux"): with self.subTest(system=system): data = {"chezmoi": {"os": system, "osRelease": {"id": "ubuntu"}}, - "name": "CI", "email": "ci@example.invalid", "personal": True, "work": False} + "name": "CI", "email": "ci@example.invalid", "work": False} output = subprocess.check_output([ CHEZMOI, "--source", str(ROOT), "--config", str(self.config), "--destination", str(self.base), "--override-data", json.dumps(data), From cac60ec6a64ee7015d74058562695b3ecf4bb5a8 Mon Sep 17 00:00:00 2001 From: froppa-agent <330570035+froppa-agent@users.noreply.github.com> Date: Mon, 12 Oct 2026 23:28:37 +0200 Subject: [PATCH 6/6] refactor: remove configuration updater --- README.md | 3 -- home/.chezmoiignore | 6 +--- .../systemd/user/follow-main.service | 9 ------ .../dot_config/systemd/user/follow-main.timer | 11 -------- home/dot_local/bin/executable_follow-main.sh | 28 ------------------- test.sh | 2 -- 6 files changed, 1 insertion(+), 58 deletions(-) delete mode 100644 home/dot_config/systemd/user/follow-main.service delete mode 100644 home/dot_config/systemd/user/follow-main.timer delete mode 100755 home/dot_local/bin/executable_follow-main.sh diff --git a/README.md b/README.md index 2c60c85..8a2732d 100644 --- a/README.md +++ b/README.md @@ -236,9 +236,6 @@ Machine-specific overrides use unmanaged `*.local` files such as `.zshrc.local`, `.exports.local`, `.aliases.local`, `.functions.local`, and `.gitconfig.local`. -The Linux `follow-main.timer` updates only this repository's managed -configuration through Chezmoi. - ## Where things live | Path | Purpose | diff --git a/home/.chezmoiignore b/home/.chezmoiignore index 5629097..060f951 100644 --- a/home/.chezmoiignore +++ b/home/.chezmoiignore @@ -13,11 +13,7 @@ # read as a file to delete on the next apply. **/.DS_Store -{{ if eq .chezmoi.os "darwin" -}} -# User timers are available only on Linux. -.config/systemd -.local/bin/follow-main.sh -{{ end -}} + {{ if ne .chezmoi.os "darwin" -}} .hammerspoon diff --git a/home/dot_config/systemd/user/follow-main.service b/home/dot_config/systemd/user/follow-main.service deleted file mode 100644 index ed08bf6..0000000 --- a/home/dot_config/systemd/user/follow-main.service +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -Description=Update managed configuration through chezmoi -After=network-online.target - -[Service] -Type=oneshot -# systemd --user starts with a compiled-in PATH; name where the tools are. -Environment=PATH=%h/.local/bin:%h/.local/share/mise/shims:/usr/local/bin:/usr/bin:/bin -ExecStart=%h/.local/bin/follow-main.sh diff --git a/home/dot_config/systemd/user/follow-main.timer b/home/dot_config/systemd/user/follow-main.timer deleted file mode 100644 index b61379d..0000000 --- a/home/dot_config/systemd/user/follow-main.timer +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -Description=Follow main every 15 minutes - -[Timer] -OnBootSec=2min -OnUnitActiveSec=15min -RandomizedDelaySec=1min -Persistent=true - -[Install] -WantedBy=timers.target diff --git a/home/dot_local/bin/executable_follow-main.sh b/home/dot_local/bin/executable_follow-main.sh deleted file mode 100755 index 78a74cf..0000000 --- a/home/dot_local/bin/executable_follow-main.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env sh -# Keep managed configuration current on a Linux workstation. -# Run by follow-main.timer, or by hand with follow-main.sh [dotfiles]. -# Dirty or non-master checkouts are left alone. -set -eu -case ${1:-dotfiles} in - dotfiles) ;; - *) echo "usage: follow-main.sh [dotfiles]" >&2; exit 2 ;; -esac -[ "$#" -le 1 ] || { echo "usage: follow-main.sh [dotfiles]" >&2; exit 2; } - -src=$(git -C "$(chezmoi source-path)" rev-parse --show-toplevel) -if [ -n "$(git -C "$src" status --porcelain)" ]; then - echo "dotfiles: $src has local changes; not pulling" >&2 - exit 0 -fi -if [ "$(git -C "$src" branch --show-current)" != master ]; then - echo "dotfiles: $src is not on master; not pulling" >&2 - exit 0 -fi -before=$(git -C "$src" rev-parse HEAD) -# Package installs remain a separate machine bootstrap step. -chezmoi update --exclude=scripts -after=$(git -C "$src" rev-parse HEAD) -if [ "$before" != "$after" ]; then - echo "dotfiles: $before -> $after applied" - systemctl --user daemon-reload -fi diff --git a/test.sh b/test.sh index 6a73eec..d65346b 100755 --- a/test.sh +++ b/test.sh @@ -123,8 +123,6 @@ grep -Fq 'set -g focus-events on' home/dot_config/tmux/tmux.conf || fail "tmux m grep -Fq 'set -g assume-paste-time 0' home/dot_config/tmux/tmux.conf || fail "tmux must disable paste timing as a global session option" sed -n '/ne .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq 'Library/LaunchAgents/com.froppa.clip-serve.plist' || fail "the clipboard LaunchAgent is macOS-only" sed -n '/eq .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq '.local/bin/wl-paste' || fail "the wl-paste shim must not land on the Mac" -[[ -x home/dot_local/bin/executable_follow-main.sh && -f home/dot_config/systemd/user/follow-main.timer ]] || fail "follow-main must ship its script and timer for Linux" -sed -n '/eq .chezmoi.os "darwin"/,/end/p' home/.chezmoiignore | grep -Fq '.config/systemd' || fail "systemd user units must not be applied on macOS" grep -Fq 'MouseDragEnd1Pane send -X copy-selection' home/dot_config/tmux/tmux.conf || fail "mouse selection must not snap the view back to the bottom" grep -Fq 'xterm-ghostty:RGB:extkeys:hyperlinks' home/dot_config/tmux/tmux.conf || fail "tmux must pass OSC 8 hyperlinks through to Ghostty" ! grep -rqE '(^|[^a-z])evo(-|[^a-z]|$)|192\.168|100\.[0-9]+\.' home/dot_config/tmux || fail "host names and addresses belong in the unmanaged tmux *.local files"