- macOS 15 or newer
- Xcode or Command Line Tools with SwiftPM support
justfor shortcut commands
swift build # debug build
swift test # test suite
just build # assemble GhostTile.app + ghosthide.dylib + codesign
just run # rebuild and open
just build-cli # build only the CLI
just format && just lint # local cleanup
just format-check # CI-equivalent formatting checkIf you change packaging, resources, or release metadata, also run just build.
Sources/GhostTileCore — shared core logic (AppManager, Config, signing, logging)
Sources/GhostTileApp — macOS app (SwiftUI + AppKit, menu bar, settings)
Sources/ghosttile — CLI entrypoint and commands
Resources — app bundle resources, icons, Info.plist, helper source
See AGENTS.md for detailed architecture and editing guidance.
Internal engineering notes live under docs/dev. They are useful for implementation context, but they are not end-user documentation and may describe incomplete or experimental work.
Release signing intentionally requires explicit environment variables:
DEVELOPER_ID_APPLICATIONNOTARY_PROFILESPARKLE_SIGN_UPDATE
That avoids leaking maintainer-specific signing identities into contributor workflows.
Release notes live in releases/<version>.html and are embedded into Sparkle appcast entries. Keep them as an HTML body fragment with no wrapper tags.
Before publishing a release, verify the exact archive after extraction:
bash scripts/verify-release-archive.sh dist/GhostTile-<version>.zip notarizedThe verifier rejects AppleDouble metadata, checks the extracted app signature, validates the stapled ticket, and runs spctl -av on the extracted GhostTile.app.
Please follow SECURITY.md for sensitive reports involving binary patching, signing, or privilege boundaries.
Sources/GhostTileCore: shared core logicSources/GhostTileApp: macOS app and SwiftUI UISources/ghosttile: CLI entrypoint and commandsResources: app bundle resources, icons, Info.plist, injected helper sourcejustfile: local build, packaging, and install commands