You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
deckd runs on macOS today only from a source checkout: just setup-macos (uv + Python + Node), just build-client, then just install-service, which sed-substitutes @PROJECT_DIR@ into packaging/launchd/com.deckd.daemon.plist and points the LaunchAgent at .venv/bin/deckd.
That requires a git checkout, Python, Node, and uv — and it gives macOS's privacy system (TCC) no stable code identity to grant. Accessibility / System Events / Screen Recording grants are attributed to the responsible process and keyed to a code identity, so a launchd agent exec'ing a venv script often cannot be granted Accessibility at all, and the core input features fail silently (see docs/PLATFORM-PARITY.md §"Verification status"). README lists "Packing and deployment" as planned; there is no tracking issue for the macOS story.
Goal
Any Mac user can install deckd with zero toolchain: download a DMG from a GitHub release, drag the app to Applications, grant permissions once, and use it. No Python, Node, Homebrew, or checkout required.
Decisions (from design discussion)
Target user: any Mac user, zero toolchain.
Channel: GitHub release DMG containing a self-contained .app. No Homebrew tap or PyPI publishing for now (a repo-local formula can come later as a contributor path).
Signing: ad-hoc signed only (codesign -s -, free). Not notarized (avoids the paid Apple Developer Program). Quarantine workaround documented.
App shape: menu-bar app (LSUIElement, no Dock icon). The daemon runs in-process on a background thread; AppKit owns the main thread.
Menu items: Open surface (browser), Open layouts folder, Restart, Quit.
Data dirs: layouts seeded on first run to ~/Library/Application Support/deckd/layouts (bundle Resources are read-only); password at ~/.config/deckd/password (already the default); log to ~/Library/Logs/deckd.log.
Refactor seam: split daemon/deckd/__main__.pymain() into build_server(args) + serve(server) so the menu-bar entry point can construct a Server and run the asyncio loop on a thread without installing signal handlers. Pure refactor; existing tests must stay green.
Toolchain: PyInstaller onedir (.spec with BUNDLE(...), custom info_plist, ad-hoc signing). Fallback if pyobjc fights the freezer: a hand-assembled bundle using a uv standalone CPython + venv.
Build recipes:just build-macos-app, just build-macos-dmg (hdiutil).
Constraints / risks
A .app can only be built on macOS (Apple toolchain). This dev machine is Linux, so the build runs on the user's Mac or on GitHub macos-14 runners; only the non-AppKit parts are testable locally.
TCC identity: grants key on bundle id com.deckd.daemon; because the bundle is ad-hoc signed, an upgrade may require re-granting. Document it.
Quarantine: a browser-downloaded DMG is quarantined → Gatekeeper blocks first open. Document xattr -dr com.apple.quarantine /Applications/deckd.app (or right-click → Open).
Not notarized: the "unidentified developer" dialog will appear; documented workaround only.
Arch strategy: decide arm64-only (build on an arm64 runner) vs universal2.
Rename churn:Rename project: deckd → deskestra #145 (deckd → deskestra) would change the bundle id, data dir, and artifact names — settle naming before publishing releases.
Plan
Phase 0 — doable on Linux, testable here
Refactor __main__.py into build_server() / serve().
Problem
deckd runs on macOS today only from a source checkout:
just setup-macos(uv + Python + Node),just build-client, thenjust install-service, which sed-substitutes@PROJECT_DIR@intopackaging/launchd/com.deckd.daemon.plistand points the LaunchAgent at.venv/bin/deckd.That requires a git checkout, Python, Node, and uv — and it gives macOS's privacy system (TCC) no stable code identity to grant. Accessibility / System Events / Screen Recording grants are attributed to the responsible process and keyed to a code identity, so a launchd agent exec'ing a venv script often cannot be granted Accessibility at all, and the core input features fail silently (see
docs/PLATFORM-PARITY.md§"Verification status"). README lists "Packing and deployment" as planned; there is no tracking issue for the macOS story.Goal
Any Mac user can install deckd with zero toolchain: download a DMG from a GitHub release, drag the app to Applications, grant permissions once, and use it. No Python, Node, Homebrew, or checkout required.
Decisions (from design discussion)
.app. No Homebrew tap or PyPI publishing for now (a repo-local formula can come later as a contributor path).codesign -s -, free). Not notarized (avoids the paid Apple Developer Program). Quarantine workaround documented.LSUIElement, no Dock icon). The daemon runs in-process on a background thread; AppKit owns the main thread.[macos]extra) + built client (client/dist) + layouts (layouts/,layouts.macos/).Design
~/Library/Application Support/deckd/layouts(bundle Resources are read-only); password at~/.config/deckd/password(already the default); log to~/Library/Logs/deckd.log.daemon/deckd/__main__.pymain()intobuild_server(args)+serve(server)so the menu-bar entry point can construct aServerand run the asyncio loop on a thread without installing signal handlers. Pure refactor; existing tests must stay green.onedir(.specwithBUNDLE(...), custominfo_plist, ad-hoc signing). Fallback if pyobjc fights the freezer: a hand-assembled bundle using auvstandalone CPython + venv.just build-macos-app,just build-macos-dmg(hdiutil).Constraints / risks
.appcan only be built on macOS (Apple toolchain). This dev machine is Linux, so the build runs on the user's Mac or on GitHubmacos-14runners; only the non-AppKit parts are testable locally.com.deckd.daemon; because the bundle is ad-hoc signed, an upgrade may require re-granting. Document it.xattr -dr com.apple.quarantine /Applications/deckd.app(or right-click → Open).universal2.Plan
Phase 0 — doable on Linux, testable here
__main__.pyintobuild_server()/serve().packaging/macos/menubar.py— PyObjC status-item app.packaging/macos/deckd.spec— PyInstaller recipe.Info.plistbits + icon placeholder.just build-macos-app/just build-macos-dmg.Phase 1 — on a Mac
7. Run the build, fix PyInstaller/pyobjc issues, verify menu bar + daemon + that a TCC grant sticks.
Phase 2 — release pipeline
8. GitHub Actions
macos-14job: build client → PyInstaller → DMG → attach to the GitHub release.Open questions
universal2.SMAppService(macOS 13+) vs a shipped LaunchAgent vs "Open at Login".Related