Skip to content

feat(update): detect Homebrew installs and upgrade via brew#44

Merged
scottlovegrove merged 3 commits into
mainfrom
feat/update-homebrew-support
May 22, 2026
Merged

feat(update): detect Homebrew installs and upgrade via brew#44
scottlovegrove merged 3 commits into
mainfrom
feat/update-homebrew-support

Conversation

@scottlovegrove
Copy link
Copy Markdown
Collaborator

Summary

  • The update command previously defaulted any unrecognised install to npm i -g. On a Homebrew-installed CLI that creates a conflicting npm-global binary or fails with EACCES against the brew-owned node prefix.
  • Detect a brew install — the running script (process.argv[1]) resolves via symlink into a Homebrew Cellar (works on Apple Silicon /opt/homebrew, Intel /usr/local, Linuxbrew) — and delegate to brew upgrade <brewFormula> instead, inheriting brew's own progress output. Under --json/--ndjson brew's stdout is piped (not inherited) so it can't corrupt the machine-readable stream.
  • Adds an optional brewFormula consumer option (e.g. 'doist/tap/todoist-cli'). npm-only CLIs leave it unset; a brew install detected without it errors with a manual-brew upgrade hint rather than running npm.

The npm-registry dist-tag check still gates "is an update available". A brew formula can lag the npm publish, so brew upgrade may be a no-op until the formula is bumped — documented in the README and docstring.

Test plan

  • npm test — full suite (439 passing), incl. new brew cases: correct brew upgrade <formula> spawn with inherited stdio, non-zero exit → UPDATE_INSTALL_FAILED, and the no-formula guard refusing to fall back to npm
  • npm run type-check
  • npm run check (oxlint + oxfmt)
  • Manual sanity on a real brew install (macOS/Linuxbrew): <cli> update --check and <cli> update

🤖 Generated with Claude Code

The update command previously fell back to `npm i -g` for any install it
couldn't identify as pnpm. On a Homebrew-installed CLI that either creates a
conflicting npm-global binary or fails with EACCES against the brew-owned node
prefix. Detect a brew install (the running script resolves into a brew Cellar)
and delegate to `brew upgrade <brewFormula>` instead, inheriting brew's own
progress output. Adds an optional `brewFormula` option for brew-distributed
CLIs to set.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@scottlovegrove scottlovegrove self-assigned this May 21, 2026
Copy link
Copy Markdown
Member

@doistbot doistbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR thoughtfully improves the update command by detecting Homebrew environments and delegating to brew upgrade, which gracefully prevents permission errors and binary conflicts for macOS and Linuxbrew users. The approach significantly enhances the update experience while seamlessly preserving the existing npm workflow. A few areas need slight refinement before merging, specifically ensuring accurate success reporting when the brew formula lags the npm registry, failing faster on missing formulas to avoid unnecessary network calls, ensuring cross-platform test reliability, and consolidating some duplicated process-spawning logic.

Share FeedbackReview Logs

Comment thread src/commands/update.ts Outdated
Comment thread src/commands/update.ts Outdated
Comment thread src/commands/update.ts Outdated
Comment thread src/commands/update.ts Outdated
Comment thread src/commands/update.test.ts
Comment thread src/commands/update.test.ts Outdated
- Report a neutral brew result instead of claiming the npm dist-tag version
  was installed (brew owns versioning and can be a no-op when the formula lags).
- Fail fast on a brew install with no configured formula, before the registry
  round-trip.
- Consolidate the spinner call and extract a shared spawn+capture helper.
- Pin process.platform in brew tests for cross-OS determinism; add a quiet/JSON
  brew case asserting the piped stdio fallback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@scottlovegrove
Copy link
Copy Markdown
Collaborator Author

@doistbot /review

Copy link
Copy Markdown
Member

@doistbot doistbot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR introduces Homebrew detection to the update command, gracefully delegating to brew upgrade instead of defaulting to npm when a brew-managed installation is detected. This is a thoughtful addition that will significantly improve the update experience for macOS and Linuxbrew users by preventing permission errors and conflicting binaries. A few adjustments are needed to accurately reflect install status when a brew formula lags behind npm, stabilize the JSON output schema across package managers, consolidate duplicated code, and expand test coverage for spinner behavior and non-Homebrew fallback scenarios.

Share FeedbackReview Logs

Comment thread src/commands/update.ts Outdated
Comment thread src/commands/update.test.ts Outdated
Comment thread src/commands/update.ts Outdated
Comment thread src/commands/update.ts Outdated
Comment thread src/commands/update.ts Outdated
Comment thread src/commands/update.test.ts Outdated
Comment thread src/commands/update.test.ts Outdated
Round 2 of doistbot review:
- Read the on-disk version after `brew upgrade` (brew list --versions) and
  derive `installed` from it, so a no-op upgrade (formula lagging npm) no longer
  reports installed: true. Expose the applied version as `installedVersion`.
- Stable success envelope across installers: always carry `latestVersion` plus a
  `via` discriminator (npm | pnpm | brew) instead of dropping keys on brew.
- Evaluate `detectPackageManager()` unconditionally to drop the nullable union
  and `pm as string` cast; consolidate the summary/lines branches.
- Tests reuse `createProgram(overrides)`; add coverage for the no-op vs changed
  brew result, formula-set-but-npm-managed fallback, and brew spinner threading.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@scottlovegrove scottlovegrove merged commit a532a41 into main May 22, 2026
4 checks passed
@scottlovegrove scottlovegrove deleted the feat/update-homebrew-support branch May 22, 2026 09:53
doist-release-bot Bot added a commit that referenced this pull request May 22, 2026
## [0.21.0](v0.20.1...v0.21.0) (2026-05-22)

### Features

* **update:** detect Homebrew installs and upgrade via brew ([#44](#44)) ([a532a41](a532a41))
@doist-release-bot
Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 0.21.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants