feat: "newer version available" notice on pcr runs + start CHANGELOG.md#87
Merged
Conversation
Adds a best-effort background update check that prints a soft "X is available — run: brew upgrade pcr" notice at the end of every interactive `pcr` command when a newer `pcr-dev` ships on npm. Modeled on the `update-notifier` npm package and `cargo`'s own behaviour: - Background thread fires off a 3-second-timeout GET against https://registry.npmjs.org/pcr-dev/latest at the *start* of the command, runs concurrently with the command itself, and writes the result to `~/.pcr-dev/update-check.json` regardless of whether the foreground command has exited. The thread is intentionally not joined — network failures, captive portals, slow DNS never delay the user's primary signal. - At the *end* of the command, the cached file is read and a one-line notice is printed to stderr if (a) the cached version is greater than `CARGO_PKG_VERSION` under naive `major.minor.patch` semver, and (b) we haven't shown the notice in the last hour (so back-to- back `pcr log; pcr show` doesn't double-print). - Suggested upgrade command is install-method-aware: inspects `current_exe()` for `/Cellar/`, `/opt/homebrew/`, or `/node_modules/` and prints `brew upgrade pcr`, `npm i -g pcr-dev@latest`, or a generic `https://pcr.dev/install` link respectively. - Hard skips: `--json` output, the hidden `hook` + `mcp` subcommands (they're stdio JSON-RPC / Stop-hook channels), `CI=*` env, and `PCR_NO_UPDATE_CHECK=1` for users who want to opt out. 6 new unit tests cover semver comparison (including prerelease suffixes), forward-compatible cache deserialisation (older payloads without `last_notice_unix` decode cleanly), and the quiet-subcommand skip list. Workspace tests: 134 passed (was 128 on this main baseline). Also adds CHANGELOG.md (none previously existed in this repo) seeded with an Unreleased section that catalogues this feature plus the in-flight fixes from PRs #85 (vscode dual-watch dedup) and #86 (watcher correctness + perf) so they have a single grep-able home when those PRs merge. Independent of PR #85 / #86 — touches `lib.rs`, `entry.rs`, and a new file. Safe to merge in any order. Made with [Cursor](https://cursor.com) Co-authored-by: Cursor <cursoragent@cursor.com>
PR #86 changed `config::pcr_dir()` to return `Result<PathBuf>` so that auth + SQLite + watcher state never silently fall back to `/tmp` when neither `$HOME` nor `%USERPROFILE%` resolves. The update-notifier is best-effort, so it absorbs the Err the same way it absorbs every other failure: collapse to `None` and silently skip the cache operation. The foreground command never sees the error. Cache helper signatures: cache_path() -> PathBuf // before cache_path() -> Option<PathBuf> // after load_cache + save_cache add a `let-else` guard at the top. Tests unchanged — all 6 update_check::tests still pass, workspace 153 passing / 0 failing. Co-authored-by: Cursor <cursoragent@cursor.com>
0efdd0c to
ce75c18
Compare
Merged
KaluJo
added a commit
that referenced
this pull request
May 18, 2026
Bumps the workspace to 0.3.0 — the 0.x minor (rather than 0.2.10 patch) is motivated by the breaking signature change to `pcr_core::config::pcr_dir()` from #86 (returns `Result<PathBuf>` instead of `PathBuf`). The CLI surface (`pcr <cmd>` flags / exit codes / output format) is unchanged. Version touchpoints: * `Cargo.toml` workspace.package.version → 0.3.0 * `crates/pcr-napi/package.json` version + all 4 optionalDependencies * `crates/pcr-napi/npm/{darwin-arm64,darwin-x64,linux-x64-gnu, win32-x64-msvc}/package.json` versions * `README.md` TUI mock version stamp * `CHANGELOG.md` `[Unreleased]` promoted to `[0.3.0] — 2026-05-18` with full release notes catalogued by PR (#85, #86, #87, #88) and grouped Added / Changed / Fixed / Tests. Workspace verification: * `cargo fmt --all --check` clean * `cargo clippy --workspace --all-targets -- -D warnings` clean * `cargo test --workspace` — 153 passing, 0 failing (was 128 on the v0.2.9 baseline; +25 across the 4 merged PRs) * `cargo build -p pcr-cli --release` → `pcr 0.3.0 (rust)` After this lands on `main`, the release commit is tagged `v0.3.0` locally and pushed; that triggers the release workflow which publishes npm + builds binaries + dispatches the homebrew formula update. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an update-notifier on every interactive
pcrcommand. Modeledon the npm
update-notifierpackage andcargo's own behaviour:Background refresh at command start. Fires a 3 s-timeout
GET https://registry.npmjs.org/pcr-dev/lateston a detachedthread, writes the result to
~/.pcr-dev/update-check.json. Thethread is never joined — slow DNS / captive portals / network
failures never delay the user's primary signal. Registry hit is
rate-limited to once per 24 h via the cache TTL.
One-line notice at command end. Reads the cache; if the cached
pcr-dev@latestis greater thanCARGO_PKG_VERSIONunder naivemajor.minor.patchsemver AND we haven't shown the notice in thelast hour (so back-to-back
pcr log; pcr showstays quiet),prints:
Install-method-aware suggestion. Inspects
current_exe()for/Cellar/,/opt/homebrew/, or/node_modules/and prints theright upgrade command (
brew upgrade pcr,npm i -g pcr-dev@latest,or a generic install link).
Quiet by default for machines and scripts. Hard skips:
--jsonoutput (would corrupt JSON-RPC / piped consumers)pcr hookandpcr mcp(internal stdio channels)CI=*env (CI runners don't need the nag)PCR_NO_UPDATE_CHECK=1(explicit opt-out)Forward-compatible cache schema. Older cache payloads without
the
last_notice_unixfield decode cleanly (covered by a regressiontest) so a CLI upgrade never silently disables the notice forever.
Also adds CHANGELOG.md — none previously existed in this repo —
seeded with an
[Unreleased]section that catalogues this featureplus the in-flight fixes from PRs #85 (vscode dual-watch dedup) and
#86 (watcher correctness + perf) so they have a single grep-able
home when those PRs merge into the next release.
README gets a short "Update notifier" subsection under "CI / agent
use" documenting
PCR_NO_UPDATE_CHECKand the quiet-subcommand list.Why now
Triggered by user feedback: "if you do pcr anything and there's a
new update available it should tell me".
pcrships through threedistribution channels (npm, Homebrew, raw releases), so users on
older versions never get notified when a fix lands — unless they
manually
npm outdated -gorbrew upgrade. This closes that loop.The check goes through the npm registry (not GitHub Releases) because
the npm dist-tag is the authoritative "latest" pointer — Homebrew's
formula auto-updates from the npm release after the GitHub Release
workflow finishes, and direct-download users are presumed to be the
ones manually managing versions.
Branching
Off
mainrather than stacked onfix/vscode-dual-watch-dedup/fix/watcher-shutdown-perf-correctness. No file overlap with either,and the feature is useful immediately at
v0.2.9without waiting forthose PRs to merge.
Test plan
cargo fmt --all --checkcleancargo clippy --workspace --all-targets -- -D warningscleancargo test --workspace— 134 passed across all binaries, 0 failures (was 128 on this main baseline; +6 new tests inupdate_check::tests):semver_compare_basic— straight numeric comparisonssemver_compare_handles_prerelease_suffix— beta tags don't trigger demotion promptssemver_compare_rejects_malformed— garbage versions never falsely "newer"cache_roundtrip_through_serde— JSON round-trip integritycache_decodes_partial_legacy_payload— forward-compat with older cachesquiet_subcommands_skip—hook+mcpcorrectly suppressedcargo build -p pcr-cli --releasesucceeds,pcr --versionandPCR_NO_UPDATE_CHECK=1 pcr statussmoke-tested locally.Future polish
pcr startmeans the notice (printed at end) is only seen when the user Ctrl-Cs. Could move the print earlier forstartspecifically, but kept end-of-command for v1 simplicity.stderr_is_terminal()and!NO_COLOR; deliberately kept plain for v1 to avoid fighting colour-discipline elsewhere.pcr_dir() -> Result<PathBuf>) merges, swapcache_path()to use?and drop the marker comment — noted inline.Made with Cursor