feat: native dock pinning and login items (CLI side)#129
Merged
Conversation
Introduces the LoginItem struct and adds DockApps []string and LoginItems []LoginItem (both omitempty) to the Snapshot struct, with round-trip JSON tests confirming serialisation and omitempty behaviour. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wires CaptureDockApps (sh -c pipeline: defaults export | plutil -extract) into CaptureWithProgress as a new step after "macOS Preferences", populates CaptureResults.DockApps, and copies it through assembleSnapshot to Snapshot.DockApps. Adds a no-panic integration guard test for the live capture path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Comment said the function "may return an error" — actually swallows them.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire CaptureLoginItems (osascript via system.RunCommandOutput) into the capture pipeline immediately after the Dock Apps step; register LoginItems in CaptureResults with nil-guard and assembleSnapshot copy. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both are read-only system probes (defaults export, osascript reads) used during snapshot capture, mirroring the existing capture.go exemption.
Add LoginItem (parallel struct, no snapshot import to avoid import cycle) and DockApps/LoginItems fields to RemoteConfig so the CLI can decode configs from the openboot.dev API that include these new fields. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds macos.SetDockApps(apps []string, dryRun bool) error which clears persistent-apps, re-adds each present app as a plist tile, and restarts the Dock. Missing apps are skipped with a stderr warning. Raw fmt.Print* calls are used instead of ui.* helpers because the macos package cannot import ui (import cycle via snapshot); new lines are baselined in internal/archtest/baseline/fmtprint.txt with a justification comment. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements SetLoginItems(items []LoginItem, dryRun bool) error in the macos package. Defines a local LoginItem type to avoid the snapshot→macos import cycle. Dry-run output uses raw fmt.Print* (same pattern as SetDockApps); new violations baselined in fmtprint.txt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add DockApps []string and LoginItems []macos.LoginItem to InstallPlan and map them from RemoteConfig in planFromRemoteConfig, mirroring the existing MacOSPrefs pattern. PlanFromSnapshot is left unchanged — InstallState has no SnapshotDockApps/SnapshotLoginItems fields yet (Task 1 only added them to snapshot.Snapshot and config.RemoteConfig, not InstallState). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wire macos.SetDockApps and macos.SetLoginItems into applyMacOSPrefs, restructuring it into three subtasks (defaults, dock, login items) with errors.Join aggregation; nil fields still short-circuit their subtask. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ucture Task 10's restructure of applyMacOSPrefs shifted the pre-existing exec.Command in applyPostInstall from line 85 to line 132. Same call, no new violations.
defaults export | plutil -extract persistent-apps json fails on real Dock plists because tile-data contains <data> blobs (alias bookmarks, icon thumbnails). Switch to xml1 + stdlib encoding/xml token walker so capture works on actual machines, not just synthetic fixtures. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.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.
What does this PR do?
Promotes Dock pinning and Login Items from
post_installshell blobs to first-class snapshot capture + declarative install fields on the CLI side.Why?
Today users pin Dock apps and register Login Items by hand-writing
defaults write com.apple.dock persistent-apps -array-add '<plist xml>'andosascript tell application "System Events"blocks inside the `post_install` array — both are common-enough macOS setup actions that they deserve first-class treatment alongside Homebrew packages anddefaultspreferences.After this PR:
openboot snapshotautomatically capturesdock_apps(list of app paths) andlogin_items(list of{name, path, hidden}) from the live system.openboot installfrom a RemoteConfig applies them declaratively (wipe-and-rebuild — install completes with the Dock / Login Items list matching the config exactly).post_installis unchanged; users may keep existing scripts or migrate to the new fields.Spec: `docs/superpowers/specs/2026-06-07-dock-and-login-items-design.md` (local, gitignored).
Plan: `docs/superpowers/plans/2026-06-07-dock-and-login-items-cli.md` (local, gitignored).
Testing
go vet ./...passesSetDockApps/SetLoginItems+ installer subtask integration testsopenboot snapshot --json | jq '{dock_apps, login_items}'returns the live Dock and Login Items correctlyCross-repo checklist
openboot.dev? — Yes, follow-up PR. The server-side schema (RemoteConfigTS type + dashboard list editors + inline install-script generator) is intentionally scoped out — this PR only ships the CLI side so users can snapshot/install from local JSON files immediately. Plan 2 covers the web side.RemoteConfig).openboot-contractschema update should land alongside the web work. Old CLIs ignore unknown fields; new CLI treats missing fields as "skip subtask", so wire compatibility is preserved.Notes for reviewer
Known limitations (intentional, out of scope):
openboot install --import snap.jsonpath) doesn't carry dock/login items yet — needsSnapshotDockApps/SnapshotLoginItemsonconfig.InstallState. RemoteConfig install path works fully.internal/typespackage.macos/dock.goandmacos/loginitems.gouse rawfmt.Print*for dry-run output (baselined infmtprint.txt) because the macos package can't importui(cycle via snapshot). Follows existing precedent —macos.goalready had 3 such baselined lines.Real bug found during verification: initial implementation used `plutil -extract persistent-apps json` which fails on real Dock plists because `tile-data` contains `` blobs (alias bookmarks, icon thumbnails). Switched to `xml1` + stdlib
encoding/xmltoken walker. Regression test `TestParseDockAppsXML_DataBlobRegression` guards against silent reintroduction.Archtest baseline changes:
🤖 Generated with Claude Code