Thanks for your interest! MenuMate is a SwiftUI menu-bar app + Finder Sync extension, with a pure-logic Swift package at its core.
Requirements: macOS 13+, Xcode 15+ (String Catalogs), Homebrew (for xcodegen).
make bootstrap # installs xcodegen, copies Local.xcconfig from the template
make gen # project.yml → MenuMate.xcodeproj (the .xcodeproj is git-ignored)
make test # runs the MenuMateCore unit tests (swift test)
make build # xcodebuild Debug
make run # build + launchLocal.xcconfig holds your local signing config and is git-ignored — never commit it. The
generated MenuMate.xcodeproj and build/ are git-ignored too; edit project.yml, not the
Xcode project.
| Target | What it is | Sandbox | Responsibility |
|---|---|---|---|
| MenuMate | SwiftUI, LSUIElement menu-bar app + settings window |
No | config editing, action execution, system-menu management, heartbeat |
| FinderExtension | FIFinderSync app extension |
Yes | draws the right-click menu, forwards clicks |
| MenuMateCore | local Swift package | — | data models, config codec, rule matching — pure logic, covered by swift test |
The extension reads no files: the main app pushes a menu snapshot to it over
DistributedNotificationCenter (chunked). This is what keeps MenuMate free of the macOS
14/15 “wants to access data from other apps” prompts — there is no App Group container.
Put pure logic in MenuMateCore with tests. Keep the extension thin.
make test must stay green. Core logic is TDD'd; add tests under
Core/Tests/MenuMateCoreTests/. Tests must not depend on the user's locale — look actions up
by presetKey, not by their (localized) title.
MenuMate uses String Catalogs with abstract keys (English is the source language):
- In code, reference a key:
String(localized: "general.launchAtLogin"). Custom components takeString, so wrap user-facing strings explicitly (SwiftUI does not auto-localize aStringvalue). For interpolation:String(format: String(localized: "key"), args…). - The values live in
App/Localizable.xcstrings(main app),Core/Sources/MenuMateCore/Localizable.xcstrings(preset titles), andFinderExtension/Localizable.xcstrings(extension).
Adding a language: open the relevant .xcstrings in Xcode, add the language, translate
the keys. No code changes needed. Don't introduce new English-string-as-key or hard-coded
user-facing strings.
- Add the script to
App/PresetScripts/(zsh; honor the env contract). - Register it in
MenuConfig.defaultSeed()(Core/.../Models.swift) with a stablepresetKeyand an abstract title key, and add the title to the Core catalog (en + zh-Hans). - Update the preset-count assertions in
ModelsTests/IPCTests.
The seeder upgrades unmodified preset scripts in place and adds newly-shipped presets without
clobbering user edits; deleted presets stay deleted (a tombstone in UserDefaults).
- Branch off
main; keep commits focused with a clear subject. - Run
make testandmake buildbefore opening a PR. - Describe the change and how you verified it. Screenshots help for UI changes.
By contributing you agree your contributions are licensed under the project's MIT License.