Skip to content

feat: curl|bash installer for the macOS desktop app#595

Merged
bborn merged 1 commit into
mainfrom
feat/macos-gui-installer
Jun 12, 2026
Merged

feat: curl|bash installer for the macOS desktop app#595
bborn merged 1 commit into
mainfrom
feat/macos-gui-installer

Conversation

@bborn

@bborn bborn commented Jun 12, 2026

Copy link
Copy Markdown
Owner

What

A Nora-style curl | bash installer for the TaskYou desktop app:

curl -fsSL taskyou.dev/install-macos.sh | bash

Our DMGs are ad-hoc signed only (#78ced384), so browser downloads hit Gatekeeper's "unidentified developer" prompt. Files downloaded via curl never receive the com.apple.quarantine xattr, so this script gives a zero-prompt install with no Apple Developer account.

How it works

  1. ASCII banner + green step output (style follows scripts/install.sh)
  2. Requires macOS; maps uname -m to the real release assets from the desktop workflow matrix: arm64TaskYou-macos-arm64.dmg, x86_64TaskYou-macos-x64.dmg; clear error for anything else or if the asset isn't attached to the latest release
  3. Requires curl, hdiutil, ditto, xattr, open
  4. Downloads from releases/latest/download/<asset> into a mktemp -d dir (--retry 3 --progress-bar, trap cleanup detaches + removes on any exit)
  5. hdiutil verify, then attach -nobrowse -readonly -mountpoint
  6. ditto to ~/Applications by default (no sudo); TASKYOU_INSTALL_SYSTEM=1 opts into /Applications with sudo; warns when a copy exists in the other Applications folder (macOS may keep launching that one)
  7. Detaches, xattr -dr com.apple.quarantine on the installed app (belt-and-braces — curl downloads aren't quarantined), then opens it; TASKYOU_NO_LAUNCH=1 skips the launch for testing/CI

Placement

scripts/install.sh and docs/install.sh are identical duplicated copies with no sync mechanism (docs/ is the GitHub Pages root for taskyou.dev), so this follows suit: scripts/install-macos.sh + identical docs/install-macos.sh. Also added a docs/_headers entry mirroring the existing /install.sh one, and the one-liner in the README's GUI section (existing CLI/TUI/GUI structure untouched).

Testing

  • bash -n: clean. shellcheck (v0.11.0 via npx): clean.
  • Real end-to-end run on an arm64 Mac with TASKYOU_NO_LAUNCH=1: downloaded the actual v0.3.8 TaskYou-macos-arm64.dmg, verified, mounted, installed to ~/Applications/TaskYou.app, ejected, cleared quarantine, skipped launch:
✓ Detected macOS arm64 → TaskYou-macos-arm64.dmg

Warning: TaskYou is already installed at: /Applications/TaskYou.app
  Remove that copy to avoid two installs (macOS may launch it instead of this one):
    sudo rm -rf '/Applications/TaskYou.app'

==> Downloading TaskYou-macos-arm64.dmg...
######################################################################## 100.0%
✓ Download complete
==> Verifying disk image...
✓ Disk image verified
==> Mounting disk image...
✓ Disk image mounted
✓ Found TaskYou.app in disk image
==> Installing to ~/Applications...
✓ Installed to /Users/bruno/Applications/TaskYou.app
✓ Disk image ejected
✓ Gatekeeper quarantine cleared
✓ Skipping launch (TASKYOU_NO_LAUNCH is set)
  • Post-install checks: installed app had no com.apple.quarantine xattr, valid ad-hoc Mach-O arm64 bundle per codesign -dv; temp dir removed and no leftover mounts. (The pre-existing /Applications/TaskYou.app on the test machine — a local dev build — was left untouched; it usefully exercised the other-location warning above. The ~/Applications test install was removed afterwards.)
  • Failure path: ran with TASKYOU_GITHUB_REPO=bborn/definitely-not-a-repo → curl 404 → Error: Download failed. TaskYou-macos-arm64.dmg may not be attached to the latest release for this architecture — check …, exit code 1.

Notes

  • Intel asset gap: the desktop workflow matrix builds both macos-arm64 and macos-x64 DMGs, but the latest release (v0.3.8, the first with any DMG) only has the arm64 asset — TaskYou-macos-x64.dmg 404s today. The script supports both archs; Intel users get the clear "may not be attached to the latest release" error until the macos-13 job's asset actually ships.
  • The script won't be live at taskyou.dev/install-macos.sh until this merges and Pages redeploys; until then it works via curl -fsSL https://raw.githubusercontent.com/bborn/taskyou/feat/macos-gui-installer/scripts/install-macos.sh | bash.

🤖 Generated with Claude Code

Add scripts/install-macos.sh (mirrored at docs/install-macos.sh so
GitHub Pages serves it at taskyou.dev/install-macos.sh, same pattern
as install.sh) that installs TaskYou.app from the latest release DMG
with zero Gatekeeper prompts:

- detects arch (arm64 -> TaskYou-macos-arm64.dmg, x86_64 ->
  TaskYou-macos-x64.dmg) and fails with a clear message if the asset
  isn't published
- downloads with curl (no com.apple.quarantine xattr, so no
  "unidentified developer" prompt for our ad-hoc-signed bundles),
  hdiutil-verifies, mounts read-only, ditto-copies
- installs to ~/Applications by default (no sudo);
  TASKYOU_INSTALL_SYSTEM=1 opts into /Applications with sudo
- warns when a copy exists in the other Applications folder
- strips quarantine belt-and-braces, then launches the app;
  TASKYOU_NO_LAUNCH=1 skips the launch (testing/CI)

Also add the one-liner to the README GUI section and a docs/_headers
entry so the script is served as text/plain.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@bborn

bborn commented Jun 12, 2026

Copy link
Copy Markdown
Owner Author

QA evidence — real installer run

Real end-to-end run of TASKYOU_NO_LAUNCH=1 bash scripts/install-macos.sh on macOS arm64 (Darwin 24.2.0), recorded with VHS. The latest-release v0.3.8 TaskYou-macos-arm64.dmg was actually downloaded, verified, mounted, and installed to ~/Applications. Wall clock of the run is visible in the frame: real 0m7.400s.

Final frame (full ✓ step list + "All set"):

595-install-final

Full run:

595-install

Note: the yellow "TaskYou is already installed at: /Applications/TaskYou.app" warning in the recording is the script's dual-install detection working as designed — this machine has a dev copy in /Applications, which was deliberately left untouched.

Post-install verification (run after the recording, before cleanup)

$ xattr -l ~/Applications/TaskYou.app
(exit 0, no output = no quarantine attr)

$ xattr -p com.apple.quarantine ~/Applications/TaskYou.app
xattr: /Users/bruno/Applications/TaskYou.app: No such xattr: com.apple.quarantine

$ codesign -dv ~/Applications/TaskYou.app
Executable=/Users/bruno/Applications/TaskYou.app/Contents/MacOS/taskyou-desktop
Identifier=taskyou_desktop-01540379dbdeb8be
Format=app bundle with Mach-O thin (arm64)
CodeDirectory v=20400 size=84776 flags=0x20002(adhoc,linker-signed) hashes=2645+0 location=embedded
Signature=adhoc
Info.plist=not bound
TeamIdentifier=not set
Sealed Resources=none
Internal requirements=none

No com.apple.quarantine xattr (so no Gatekeeper "damaged"/"unidentified developer" prompt), and the bundle carries the expected ad-hoc linker signature from 78ced38. (FYI: codesign --verify --deep --strict reports "code has no resources but signature indicates they must be present" — expected for linker-signed ad-hoc bundles with no sealed resources; pre-existing signing characteristic, not introduced by this installer.)

Machine left clean: the test install at ~/Applications/TaskYou.app was removed after verification (~/Applications is back to its prior state), the DMG/mount temp dir is cleaned by the script's EXIT trap, and the dev copy at /Applications/TaskYou.app was not touched.

🤖 Generated with Claude Code

@bborn bborn merged commit 7b1e268 into main Jun 12, 2026
4 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.

1 participant