Skip to content

Add more apps and CLIs - #17

Merged
drewjs merged 2 commits into
mainfrom
add-chrome-1password
Oct 18, 2026
Merged

drewjs merged 2 commits into
mainfrom
add-chrome-1password

Conversation

@drewjs

@drewjs drewjs commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds Google Chrome, 1Password, and 1Password CLI as casks with no Stow package, plus the formulae gh, git-town, lazygit, and uv. Full includes them. They are not in minimal.
  • Installing those casks no longer fails when the app is already on the Mac outside Homebrew. A hand-installed Google Chrome.app or 1Password.app in /Applications or ~/Applications, or op already on PATH, is skipped with a message. --audit counts that app as present. Casks that are absent still go through brew install --cask.
  • fnm stays a formula on the zsh row. When that formula is selected, the installer runs the equivalent of fnm install --lts and fnm default lts-latest. If that LTS is already installed and is the default, it does nothing, so a second run prints Nothing to do. --audit reports Node LTS present or missing.

Before

brew install --cask failed when Chrome or 1Password was already in /Applications but not installed by Homebrew. fnm was installed with zsh, and Node was not.

After

A hand-installed Chrome is skipped (Skipping cask google-chrome: ...) and --audit treats it as present. The same applies to 1Password and op. A full install also installs gh, git-town, lazygit, and uv, and sets the latest Node LTS as the fnm default. CI creates a dummy /Applications/Google Chrome.app before install and checks that the second run prints Nothing to do.

Open in Web Open in Cursor 

Skip Chrome, 1Password, and the 1Password CLI when they are already on the
Mac, and install the latest Node LTS as the fnm default only when it is missing.

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

claude Bot commented Oct 18, 2026

Copy link
Copy Markdown

Review

Overall: clean, bash 3.2-safe, and the CI additions are good. Nothing blocking. Notes below.

Behavior

  • latest_node_lts (install.sh) hits nodejs.org on every run and every --audit. Offline, --audit reports "missing Node LTS", and a rerun reruns fnm install --lts and fnm default, so it isn't a no-op. Consider treating curl failure as "unknown" (skip with a warning) instead of "missing".
  • The dry run calls curl too, via node_lts_installed, when fnm is already present. It's harmless, but it's a network call in a mode that shouldn't need one.
  • fnm_base_dir guesses fnm's data dir. If none exists yet it returns 1, which is fine. If an old ~/.fnm exists but fnm now writes to ~/.local/share/fnm, or the reverse, the check can disagree with where fnm installs. Then the rerun isn't a no-op. Asking fnm directly would be more robust, e.g. fnm list and fnm current/fnm default. Or run fnm env and read FNM_DIR.
  • The readlink match on */node-versions/$NODE_LTS/installation assumes fnm's alias layout. A fnm layout change would silently loop into re-running fnm default. This is cheap and idempotent, but worth a comment.
  • fnm install --lts picks fnm's own idea of the latest LTS. latest_node_lts parses index.json separately. They can briefly disagree after a new release, so the "installed" check misses and the install reruns. Fine, but you could pass the resolved version explicitly: fnm install "$NODE_LTS" and fnm default "$NODE_LTS". That makes both sides consistent.
  • The minimal profile includes zsh, so minimal installs now also download Node. The PR text says only "Full includes them". Confirm that's intended, and mention it in the README.
  • 1password-cli is skipped if any op is on PATH. That includes a brew formula or a stray script. Probably fine.
  • cask_outside_brew skips permanently, so these casks never get brew upgrade management. Worth one README line.

Duplication

  • cask_present in verify-install.sh re-implements cask_outside_brew. The comment acknowledges it. A drift risk, but acceptable for an independent test oracle.
  • The awk JSON parse is hand-rolled. jq is already in the bin package, but it isn't guaranteed at bootstrap, so awk is defensible.

Nits

  • tools.txt: the 1password-cli row overflows its column, so alignment breaks. Widen the first column.
  • verify-preinstalled-cask.sh: grep -F ... >/dev/null can be grep -qF. The mktemp files are never cleaned up, so add a trap.
  • verify-preinstalled-cask.sh runs rm -rf "$HOME/Library/Application Support/dotfiles". That's fine on CI, but add a guard (e.g. [ "${CI:-}" = true ]) so it can't be run on a dev machine and wipe the saved selection.

Test coverage

  • Chrome skip, audit, and the noop rerun are covered. The 1password and 1password-cli paths aren't. A fake op in PATH would cover the latter cheaply.
  • There's no negative test that a missing cask still reaches brew install --cask. The existing full-install job likely covers this.
  • No test for the already-LTS-but-not-default path.

Security

  • The curl uses https with -fsSL, and the result is only used as a version string compared against paths. No injection risk found. $NODE_LTS is validated by the awk regex.

Follow the default symlink chain so a second install does nothing, and drop a
preinstalled google-chrome cask before the hand-installed app check.

Co-authored-by: drewjsdev <drewjsdev@pm.me>
@drewjs
drewjs marked this pull request as ready for review October 18, 2026 00:24
@drewjs
drewjs merged commit f15ea68 into main Oct 18, 2026
4 of 5 checks passed
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