Skip to content

feat: add macOS desktop support - #201

Open
lorenzopincinato wants to merge 6 commits into
Chnapy:mainfrom
lorenzopincinato:macos-app-build
Open

feat: add macOS desktop support#201
lorenzopincinato wants to merge 6 commits into
Chnapy:mainfrom
lorenzopincinato:macos-app-build

Conversation

@lorenzopincinato

@lorenzopincinato lorenzopincinato commented Aug 24, 2026

Copy link
Copy Markdown

Summary

I've been using PKVault on my Mac for a few weeks now. I started out with the Docker version, but last week I compiled it natively for macOS and have been running it without issues since, so I wanted to share it with the community.

This PR adds native macOS desktop support (Apple Silicon + Intel), on par with the existing Windows/Linux desktop builds.

PKVault running on macOS, with the bundled example save open:

Screenshot 2026-08-24 at 20 05 29

The Gatekeeper prompt users will see on first launch, since the app isn't notarized (documented in the README, bypassable via System Settings > Privacy & Security > Open Anyway):

Screenshot 2026-08-24 at 20 04 31

What's included

  • PKVault.Desktop/publishers/macos/build-app.sh - builds PKVault.app from a dotnet publish output: generates the .icns and ad-hoc signs the bundle. Uses iconutil/codesign when available, otherwise falls back to icnsutil (pip) and rcodesign, so the whole thing also runs on Linux - no real Mac needed to build it.
  • CI/release pipeline - reuses the existing generic desktop-publish Dockerfile stage (already used for Windows/Linux, since dotnet publish cross-compiles fine) plus a new desktop-publish-macos-app/desktop-macos stage. The release workflow now builds and attaches pkvault-<version>-osx-arm64.app.zip and pkvault-<version>-osx-x64.app.zip the same way it already does for the other platforms - no macOS runner required.
  • Backend - RuntimeSystem gained a MACOS case (was previously falling through to UNKNOWN), and the app data directory now resolves to ~/Documents/pkvault on macOS instead of incorrectly falling back to next to the executable (which, inside a .app bundle, is Contents/MacOS/ - not writable post-install).
  • Frontend - macOS label added to the settings page's runtime system display, with translations.
  • Docs - README platform table/usage section and the technical considerations doc now mention macOS.

Testing

  • All 127 existing backend tests still pass.
  • Built and ran the .app on my own Apple Silicon Mac, both via a local build and via the actual CI pipeline output (Docker-based, Linux-built).
  • Verified the produced bundle is properly signed (codesign --verify --deep --strict, spctl) and launches cleanly - only the expected "Apple could not verify this app is free from malware" prompt for unnotarized software (bypassable via System Settings > Privacy & Security > Open Anyway), no "damaged" error.

Known limitations / follow-ups

  • Not notarized - that requires a paid Apple Developer account, so users will need to allow the app manually the first time (documented in the README).
  • No DMG installer - currently ships as a .zip containing the .app; a drag-to-Applications DMG is a nice-to-have for later.
  • Translations - I only speak English and Portuguese, so I only updated the en and pt-br docs/locale files where full sentences needed translating. I did not touch the French technical-considerations doc since I can't verify translation accuracy there - would appreciate a French speaker reviewing that before merge. The settings.system.macos label added to fr/de/zh-hant locale files is just the untranslated word "macOS" (mirroring how "Windows"/"Linux" are already handled in those files), so that part should be safe.

Builds PKVault.app from a dotnet publish output, generating the .icns
and ad-hoc signing it. Uses macOS's iconutil/codesign when available,
otherwise falls back to icnsutil (pip) and rcodesign so it also runs
on Linux, with no real Mac required.
Adds a desktop-publish-macos-app / desktop-macos Dockerfile stage,
reusing the existing generic desktop-publish stage (dotnet cross-compiles
osx-arm64/osx-x64 fine from Linux). The release job extracts both
pkvault-<version>-<rid>.app.zip archives the same way it already does
for the Windows/Linux desktop builds.
Previously macOS fell through to UNKNOWN for RuntimeSystem and used the
directory next to the executable for app data, which inside a .app bundle
is Contents/MacOS/ - not writable post-install. Mirrors the existing
Linux behavior instead.
French (fr) intentionally left untranslated - needs review by a French
speaker before merge.
@Chnapy

Chnapy commented Aug 25, 2026

Copy link
Copy Markdown
Owner

Thanks for this PR, I don't have Apple devices so it was quite hard to do myself.
Your code looks clean, I just have to do some testing and we'll go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants