Skip to content

arena: stow cards - #13

Closed
drewjs wants to merge 4 commits into
mainfrom
arena/own-design
Closed

drewjs wants to merge 4 commits into
mainfrom
arena/own-design

Conversation

@drewjs

@drewjs drewjs commented Oct 17, 2026

Copy link
Copy Markdown
Owner

Why

Andrew installs this repo on more than one Mac, and some machines should not get every tool. setup installs Homebrew when the Mac does not already have it, then installs and stows only the tools chosen for that machine.

What changed

  • A tool is one card in cards/. setup has no per-tool branches.
  • The choice is saved at ~/Library/Application Support/dotfiles/selection. The next run reads that file.
  • GitHub Actions on macos-latest runs shellcheck, a full install, a subset install, a second run, and a check that unselected tools were not installed.

Tradeoffs

A manifest plus install.sh keeps the tool list in one file and the procedure in another. A tap, a cask, or a backup rule becomes another branch in the script, so adding a tool means editing both files. The subset is a flag you type again next time.

A card is the whole install record. Taps, formulas, and casks live in that one file, and the Stow package next to it is already the config. setup only reconciles the cards named in the selection file. Adding a tool means adding cards/<name>.

Chezmoi would replace these Stow packages with its own source tree and its own templates. The packages already mirror $HOME, and machine-specific values already belong in gitignored ~/.zshrc.local. Chezmoi also does not install Homebrew, so package installation would still be a second script. chezmoi apply writes over the file at the target path. setup copies an existing target aside before it replaces the target, and it leaves a correct symlink alone.

What it can remove or overwrite

  • If a path Stow needs already exists and is not the symlink this clone owns, setup copies that path to ~/Library/Application Support/dotfiles/backups/<timestamp>/ and then replaces it with the symlink.
  • If ~/.config or ~/.local is a regular file, setup backs that path up and replaces it with a directory.
  • If ~/.config or ~/.local is a symlink that points outside this repo, setup backs the symlink up and replaces it with a directory.
  • If several selected tools need ~/.config or ~/.local and that path is a symlink into this repo, setup backs the symlink up and replaces it with a directory. The files stay in the package.
  • If only one selected tool needs that path and the symlink already points at that package, setup leaves the symlink in place.
  • setup does not uninstall Homebrew packages, does not remove symlinks for tools dropped from the selection later, and does not run stow --adopt. Tracked files in the repo stay as they are.

Scope

Covers install, the remembered selection, backup, and the macOS workflow. It does not start yabai or skhd, and it does not change the login shell.

Blast radius

On a machine whose Stow links already point at this clone, a second setup changes nothing. A real file in the way is copied aside and then replaced.

Verification

  • Local run with a fake Homebrew and GNU Stow. Full install, subset install, second run, backup, and the unselected-link check all passed.
  • GitHub Actions on macos-latest runs the same checks against real Homebrew.
Open in Web Open in Cursor 

cursoragent and others added 2 commits October 17, 2026 22:16
setup installs and links only the tools chosen for this Mac, remembers that choice, and copies aside any path it has to replace.

Co-authored-by: drewjsdev <drewjsdev@pm.me>
Run shellcheck, a full install, a subset install, a second run, and a check that unselected tools stay absent.

Co-authored-by: drewjsdev <drewjsdev@pm.me>
@claude

claude Bot commented Oct 17, 2026

Copy link
Copy Markdown

Review. Solid design: card-per-tool, backups before overwrite, idempotent rerun, bash 3.2 safe. Issues, most important first:

  1. alacritty has no card. The package and README entry exist, but cards/alacritty is missing, so setup never installs or stows it. Add it (cask alacritty) or drop the package.
  2. HOMEBREW_CASK_OPTS=--no-quarantine (ensure_brew). Disables Gatekeeper checks for every cask, and recent Homebrew deprecates or removes the flag. Remove it or make it opt-in.
  3. CI install path is weakly tested. macos-latest preinstalls many formulas (jq, python@3, ...), so brew list succeeds and the install never runs. Uninstall them first or use ones not preinstalled.
  4. herdr formula. Confirm brew install herdr works without a tap. If not, add a tap line to cards/herdr.
  5. Dropped tools leave stale links. Narrowing the selection does not unstow, and --audit then fails with 'points at unselected package'. Add an unstow step or document it.
  6. --only names skip valid_name. write_selection checks cards/$name directly. Validate user-supplied names so something like ../x is rejected explicitly.
  7. Prompt typos. A bad name dies with nothing saved. Safe, but re-prompting is friendlier.

Nits:

  • snap() is duplicated verbatim in two CI jobs. Move it to a script.
  • AGENTS.md says do not edit setup, but .config, .local and .claude are hard-coded in prepare_shared and repo_links. A new shared top-level dir needs a script edit.
  • CI only plants a .zshrc. Planting a ~/.config symlink would exercise the riskiest branches (prepare_shared).

Fix 1 and 2 before merge. The rest are optional.

cursoragent and others added 2 commits October 17, 2026 22:19
Homebrew rejects --cask together with --installed-on-request. The baseline now uses brew list --cask.

Co-authored-by: drewjsdev <drewjsdev@pm.me>
Homebrew 6 refuses skhd and yabai until each formula is trusted. setup trusts the qualified formula, then installs it.

Co-authored-by: drewjsdev <drewjsdev@pm.me>
@drewjs drewjs closed this Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants