Maple is a free, fast, native macOS Git client built with SwiftUI — no web views, no Electron, no subscription. It talks directly to
giton your machine and exposes the full power of Git without hiding it behind abstractions.Repo: https://github.com/poolcamacho/Maple · License: MIT
Why another Git client
There are solid Git GUIs on macOS already — Tower and Fork are both great. I started Maple for a narrower reason: I wanted something that was free, open source, native SwiftUI, and unapologetically power-user friendly, and I wanted to learn modern SwiftUI by building something I'd actually use every day.
So Maple has a pretty specific design brief:
- Fully native SwiftUI — no web views, no Electron, opens as fast as Terminal.
- Free and MIT-licensed — no subscription, ever.
- Shows Git as it is — full commit graph with real topology, visible branches and merges, proper conflict view. No wizards that hide what's happening.
- Respects your workflow — shortcuts and actions for the operations power users actually care about: interactive staging, stash, rebase, merge, cherry-pick.
It's not a replacement for Tower for everyone. It's the one I wanted to exist.
What it does today
The screenshots will come later — I'm publishing this as a progress post, not a launch — but here's what's already working end-to-end on a real repo:
-
Open any local repo via folder picker, with
.gitvalidation - Sidebar with repository list, local and remote branches
- Toolbar with Pull, Push, Fetch, Stash, Branch, Merge, Rebase
- Four tabs: Changes, History, Branches, Stashes
- Live diff viewer with colored hunks, line numbers, and a Blame toggle
- Commit graph with real topology — lane assignment algorithm, curved edges per parent, merge nodes drawn as ringed circles
-
Merge and rebase with conflict handling —
UU/AA/DDdetection, an operation banner with Abort / Continue / Skip, and per-fileUse Ours/Use Theirsresolution -
Auto-refresh via FSEvents on
.git/ - Adaptive layout from wide desktops down to compact laptop windows
It's a real client already. I've been dogfooding it to commit and push the work on itself.
The architecture, in one screen
Models/ — Pure Sendable data (AppState, GitModels, StashModels)
Services/ — GitService (actor, CLI execution)
GitCoordinator (@MainActor orchestration)
Command extensions (GitCommands, GitBranchOps,
GitStashOps, GitMergeRebase)
CommitGraphBuilder, ConflictParser, FileWatcher
Views/ — One file per view, zero business logic
Utils/ — FolderPicker, DateExtensions
A couple of decisions worth calling out:
GitService is an actor, so all CLI calls serialize behind a single gatekeeper. GitCoordinator is @MainActor and sits between the views and the actor — views only call state.coordinator.* and never touch Process or Pipe directly.
Every git invocation uses a fresh /dev/null stdin and closes its pipes explicitly. Without that, I was getting NSPOSIXErrorDomain code=9 / EBADF errors after long-running commands like push, because FileHandle.nullDevice is a shared singleton that drifts into bad states across many posix_spawn calls. Opening /dev/null per call with closeOnDealloc: true fixed it.
The commit graph isn't the usual “dot + vertical line” fake. It builds an actual lane layout: for each commit, claim the lane that expects it (child→parent link), otherwise reuse a free lane. First parents stay in the same lane to keep the main line straight; extra parents on merges spawn side lanes with curved connectors. Edges are resolved in a second pass because a parent may appear many rows later.
Conflict UX is per-file, not per-hunk — on purpose for v1. When a merge conflict lands, the Changes tab lights up conflicted files with a purple ! marker, and each one offers a three-button bar: Use Ours, Use Theirs, or edit the markers in your own editor. A persistent banner at the top of the window shows Merging X with Abort / Continue / Skip. No modal dialogs, no hijacking your workflow.
What's already in place beyond the app itself
Because I want this to grow as a real OSS project and not as a one-off:
-
GitHub Actions CI — build +
xcodebuild analyze+ SwiftLint (strict) on every push and PR - CodeQL — scheduled weekly Swift analysis, plus on any PR that touches Swift code
-
Release workflow — tag
v*to publish an unsigned.appzip automatically -
Branch protection on
master— required status checks, no force push, no deletion, conversation resolution required - Dependabot for GitHub Actions, so pinned action versions stay fresh
- SECURITY.md with private vulnerability reporting enabled
- Issue forms and a PR template that enforces the “no business logic in views” rule
None of this is heroic, but it's the boring scaffolding that turns a weekend project into something other people can actually contribute to.
What's next
The roadmap I'm actively working through:
- [ ] Interactive staging — stage individual hunks and lines instead of whole files
- [ ] Tag management — create, list, delete from the UI
- [ ] Search filtering — filter commits and files with fuzzy matching
- [ ] Clone from URL — right now you open existing repos; cloning is the obvious next step
- [ ] Remote management — add, remove, configure remotes without dropping to CLI
- [ ] Keyboard shortcuts —
Cmd+Sto stage,Cmd+Enterto commit,Cmd+Kfor the command palette I haven't built yet - [ ] Persist open repositories between sessions
- [ ] Settings & preferences
- [ ] Signed + notarized releases once the app is ready for non-developer users
Try it, and help shape where it goes
It's MIT-licensed, open source, and built in public:
→ github.com/poolcamacho/Maple
If you're on macOS 14+ with Xcode 16+, git clone and Cmd+R in Xcode gets you running in under a minute. Please open issues — especially if you hit a Git workflow the UI makes awkward. I'd much rather fix that than guess what power users need.
And if you want to sponsor the work so it stays free and actively maintained, there's a Sponsor button at the top of the repo, or you can go directly to github.com/sponsors/poolcamacho. Sponsorship keeps Maple free for everyone and funds the signing + notarization budget I'll need for shipping to non-developers.
Next post will probably be about interactive staging — that one's the most interesting design problem on the list. Stay tuned.



Top comments (0)