needs-you

Guides

Keeping up to date

A release that passed its tests reaches the Mac app on its own, and from the Mac's hub every sender machine can follow. The design and its reasons: docs/roadmap/rollout-updates.md.

tag vX.Y.Z → CI tests → draft release (+ release-manifest.json) → you publish it
  → the Mac app sees it (within 6 h), waits 2 h, verifies, installs when you're away
  → its hub now serves the new CLI, hook, skill and Orca snippet (/dl/manifest.json)
  → senders run `needs-you update` (by hand, daily with --auto-update, or scripts/rollout.sh)
  → Settings → Updates: "1 of 4 machines out of date"

The Mac app #

Settings → Updates. It shows this app's version, the last check and its result, and:

SettingDefaultWhat it does
Check for updates automaticallyon2 minutes after launch, then every 6 hours. The only request goes to api.github.com and carries nothing about your items.
Install updates automaticallyonWhen you've been away 10 minutes (no keyboard or mouse), or when you quit. Never while the panel is open, the pointer is on it, or an item arrived in the last 2 minutes.
ChannelReleasesOr releases and pre-releases. Drafts never.
Wait after a release2 hoursA release pulled within this time never reaches this Mac.

Check now checks at once. When an update passes the checks, Download and install now (or Restart to update once it's downloaded) installs it straight away, and Skip X.Y.Z skips that version.

What it checks before installing anything: the release is published (not a draft); it is newer than this app; it carries release-manifest.json, which only the release job writes, after the tests passed; the zip matches the SHA-256 in both the manifest and SHA256SUMS, and its size; the release workflow run named in the manifest concluded success on the same commit (when the token can read Actions); this Mac meets the manifest's min_macos; the unpacked app has the same bundle id (app.needsyou.mac), the promised version, a valid seal (codesign --verify --deep --strict), the same signing team as this app (when this app has one), no symlink pointing outside the bundle, and a bundled install.sh. Downloads come from GitHub's own hosts over https only, redirects included, from the repo fixed in the app. Once a release signing key is pinned in the app, a valid Ed25519 signature over the manifest is required too (owner steps: release-signing.md).

Installing runs the app's bundled install.sh: it quits the app, swaps /Applications/NeedsYou.app (keeping NeedsYou.app.previous), relaunches in the background, and puts the previous version back if the new one doesn't stay running. A version that was rolled back is skipped from then on. Settings says "Updated to X.Y.Z" after a successful update. The log is ~/Library/Application Support/NeedsYou/Updates/install.log. To go back by hand: /Applications/NeedsYou.app/Contents/Resources/scripts/install.sh --rollback.

After an update, if the macOS firewall asks whether python3 may accept incoming connections, choose Allow: the ad-hoc signature changes with every build, and until then other machines can't reach this Mac's hub (they queue).

No GitHub account is needed: the repo is public, so the app checks anonymously when it finds no credential. If it finds one it uses it, in order: the GitHub CLI's token (gh auth token, from /opt/homebrew/bin/gh or /usr/local/bin/gh), then a fine-grained token (Contents: read and Actions: read, on this repo only) in ~/Library/Application Support/NeedsYou/github.token with mode 600. The token stays in memory, goes only to api.github.com, and is never logged or shown; Settings shows only where it came from.

Testing without a release: mac/scripts/make-test-feed.sh --version 0.1.2 builds a feed in /tmp/needsyou-feed; defaults write app.needsyou.mac updateFeedURL file:///tmp/needsyou-feed/ points the app at it (or NEEDS_YOU_UPDATE_FEED). Settings then shows a Test update source warning, and nothing from it installs automatically. defaults delete app.needsyou.mac updateFeedURL goes back to GitHub.

Upgrade note: the bundle id moved to app.needsyou.mac #

0.1.x had a different bundle id. From the next release the app is app.needsyou.mac, so macOS treats it as a new app:

Sender machines #

needs-you update --check     # what would change, and from where
needs-you update             # do it
needs-you update --rollback  # put back the files the last update replaced

needs-you update updates what's already installed on the machine (it never adds a piece): the CLI, the Claude Code hook and its entries in ~/.claude/settings.json (re-merged by install-hooks.sh, which keeps a .bak), a project's own hooks when you run it inside that project, the skill, and the Orca snippet. It:

Automatic (opt-in). With NEEDS_YOU_AUTO_UPDATE=1 in ~/.config/needs-you/env (the installer's --auto-update writes it), the 5-minute needs-you flush runs the same update once a day, at a time that differs per machine, quietly and without ever failing the flush. It is off by default: an update is code. It also needs gh (logged in, able to read the repo) on the sender for the release cross-check, unless NEEDS_YOU_UPDATE_REQUIRE_RELEASE_MATCH=0.

Asked from the Mac (Request update). In Settings → Access (the machine list), a sender whose CLI is older than the Mac app, or hasn't reported a version, has a Request update button. It marks that machine's token "update requested" on each of your owner hubs, and the machine's next post, resolve, flush or token-checked health call gets "update_requested": true back. Then:

The row shows "Update requested 5m ago" with Cancel until the machine reports a different CLI version (or one at least the hub's), when the hub clears the request by itself and the row says "Up to date". "Up to date" means at least the Mac app's own version: that is what its hub serves, so it's the newest the machine can get from it. The request is a flag, never a URL or a command, and is kept per hub, not replicated (the app sends it to every owner hub it has). From a server hub's shell: needs-you-admin token request-update <name> and token clear-update <name>. Why this is safe: request-update.md.

Every request a sender makes carries X-Needs-You-Client: cli=…; hook=…; skill=…; orca=…, so Settings → Updates → Sender machines on the Mac shows each machine's versions, when it was last seen, and "N of M machines out of date". needs-you doctor has an update line with the local versions against the hub's.

Orca prompts point at ~/.config/needs-you/orca-snippet.md instead of carrying a copy (integrations/orca), so an update reaches every automation on its next run. Prompts pasted before this change carry the old full text: replace them with the pointer once.

Many machines at once: scripts/rollout.sh devbox ci-runner (or a list in ~/.config/needs-you/hosts, one SSH alias per line) runs needs-you update and needs-you doctor on each over SSH, in parallel, and prints a table. --check only reports. A machine without the CLI is listed; set it up with an invite link.

Server hubs #

A server hub serves its own checkout or tarball on /dl, so its senders follow it, not the Mac. Update it as in Server hubs. An automatic updater for server hubs is planned (rollout-updates.md, item 15).

This page is docs/guides/updates.md in the repo. View or edit it on GitHub.