Skip to content

Conversation

@Geramy
Copy link
Collaborator

@Geramy Geramy commented Jan 18, 2026

Summary

This PR introduces comprehensive macOS support for Lemonade, focusing on native packaging, system integration, and performance optimizations. It establishes the foundation for seamless macOS integration, replacing the previous cross-platform approach with macOS-native implementations.

Changes

Packaging & Installation

  • Switched to .pkg installer: Replaced .dmg with .pkg format for automatic installation of both the Electron app and system services
  • System-wide installation: Configured installation to standard macOS locations (/Applications, /Library/LaunchDaemons, /Library/LaunchAgents)
  • Code signing & notarization: Added support for macOS Gatekeeper requirements and Apple notarization
  • Installer robustness: Improved path handling and error recovery in installation scripts

System Integration

  • Launchd services: Implemented proper launchd daemon and agent configurations with plist files
  • Daemon mode: Added --no-tray option for headless server operation
  • macOS-specific paths: Enhanced path_utils with macOS cache directory handling for both root and user modes

Performance & Compatibility

  • Metal acceleration: Enabled Metal backend for llama.cpp on macOS for improved GPU performance
  • Backend auto-conversion: Automatic Vulkan-to-Metal conversion on macOS systems
  • Modern Objective-C: Refactored tray implementation using ARC and contemporary patterns
  • Implement Tar Usage-C: I have switched to use tar on windows 10/11 platforms primarily and powershell as a backup.

Build & Development

  • CMake enhancements: Updated build system for macOS packaging, notarization, and service installation
  • Post-install scripts: Added automated service setup and configuration
  • Documentation updates: Included macOS-specific building and notarization instructions

Miscellaneous

  • Repository hygiene: Added .DS_Store to .gitignore to prevent macOS system files from being committed
  • Code cleanup: Namespace improvements and general code maintenance

This PR represents Stage 1 of macOS support, providing a solid foundation for native macOS integration while maintaining compatibility with existing cross-platform functionality.

Stage 2 is to fix some tray features

such as showing loaded model, unload models, load models etc...
Currently the tray icon has limited functionality.
Enable/Disable Service
Start/Stop Service
Quit Lemonade (closes tray icon and unloads models)
Open App (Opens electron app)

Geramy added 28 commits January 5, 2026 19:28
- Relax CMake minimum version to 3.10...3.28 for broader compatibility
- Adjust Electron app unpack directory for macOS to simplify path handling
- Add comprehensive CPack configuration for packaging Electron .app bundle in .dmg, including resource embedding and optional system service installation
- Update VSCode settings with local source directory and additional C++ header mappings for improved IntelliSense and development workflow
…rvice and app, lemonade-server is not working on macosx, yet. but it installs.
Refactor CMakeLists.txt to install binaries, plist, and resources to system directories (/usr/local/bin, /usr/local) instead of embedding them in the Electron app bundle. Configure CPack for productbuild with system domain installation and add post-install script for service setup. This enables proper system service deployment on macOS, requiring admin privileges.
- Remove leading slash from LaunchDaemons path in CMakeLists.txt to use relative installation
- Change component from Services to Runtime for plist installation
- Strip trailing slash from INSTALL_ROOT in postinst script for consistency
- Handle missing plist file gracefully in postinst by warning instead of exiting, allowing launchctl to manage errors
- Remove trailing newline from CMakeLists.txt for cleaner file ending
- Add macOS-specific IntelliSense config to VS Code c_cpp_properties.json
- Update launch.json for lldb-based debugging on macOS
- Modify CMakeLists.txt to sign executables only in Release builds on Apple platforms
- Add CPACK variables for macOS package metadata including version, vendor, and descriptions
- Refactor install logic to use relative paths with /usr/local prefix for correct destinations
- Fix share directory creation by installing a placeholder file to ensure /usr/local/share/lemonade-server exists
- Update macOS system info to provide clearer error messages for unsupported GPU and NPU detection (NVIDIA GPUs and Ryzen AI NPUs)
- Implement Tray Icon for macos
- Upgrade the windows 10/11 unzip to use tar which is a default program and if the program doesnt exist it resorts to powershell unzip. This should fix the errors that seem to occur sometimes on some machines on windows.
- Update .vscode/settings.json to change debug config from "cpu" to "metal" for llama.cpp
- Add macOS-specific source file server/macos_system_info.mm and link Metal framework in CMakeLists.txt to leverage hardware acceleration on Apple devices
Enable Automatic Reference Counting (ARC) for macOS Objective-C++ files to automate memory management and reduce manual release calls. Add logic to automatically convert Vulkan backend to Metal during llama.cpp server install and load operations for better macOS compatibility. Update tray implementation to use ARC and improve callback handling.
…tterns

Completely refactored the macOS tray implementation to use Automatic Reference Counting (ARC) and modern Objective-C patterns, including safer callback handling with wrapper classes, proper threading with GCD for UI updates, and support for both modern UserNotifications (for bundled apps) and legacy NSUserNotificationCenter (for CLI/debug modes), improving reliability and compatibility across different macOS deployment scenarios. Adjusted CMakeLists.txt to reorder tray subdirectory inclusion and refine macOS packaging/signing logic accordingly.
- Add --no-tray argument to launch configurations for debugging without tray icon
- Modify signal handler to ignore SIGHUP, preventing termination on parent exit to enable daemon mode
- Update server manager to handle server initialization without quick readiness check, improving startup reliability for tray-less operation
- Removed redundant write_pid_file and redundent health checks and resorted back to one final health check with a 10 second loop.

- Recommended future fix
```
    // TODO:
    // lemonade-router honestly should create its own pid file and then we should wait for the file to exist up-to a certain timeout.
    // if that pid file doesnt exist we should check to see if the process is still alive and if it is.
    // the process might be busy downloading a model, we coudl redirect I/O to see what its doing and stay up-to date instead of using a blind timeout.
    ```
…t and user modes

Implement platform-specific logic in get_cache_dir() to use user cache (~/.cache/lemonade) for non-root users and system cache (/Library/Application Support/Lemonade) for root or system services on macOS. This ensures proper isolation and adherence to macOS conventions for application data storage. Includes necessary includes for macOS user ID and password database access.
…e and it doesnt need to be in the repository.
@Geramy Geramy requested a review from ramkrishna2910 January 30, 2026 05:19
Copy link
Contributor

@ramkrishna2910 ramkrishna2910 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested and approved! Great contribution!

@Geramy Geramy force-pushed the geramy/macosx-support-stg1 branch from 7c3b371 to cbcef13 Compare February 3, 2026 22:48
Geramy added 12 commits February 3, 2026 16:27
- Enable Objective-C++ language for macOS Metal GPU support in CMakeLists.txt
- Set source file language to OBJCXX for macOS system info
- Fix license file path in CPack configuration
- Add detailed macOS build, notarization, and distribution instructions to dev docs
- Remove inference engine detection from Metal GPU code in macOS system info
- Add post-install code signing for router and server binaries in release builds
- Set CPACK_PRODUCTBUILD_RELOCATE OFF to preserve signatures
- Improve notarization commands with verbose output and clearer messages
- Add entitlements to macOS DMG build configuration for hardened runtime

This ensures compliance with macOS security requirements and prevents signature invalidation during packaging.
Specify COMPONENT Runtime for install commands of the main executable and lemonade-server on Apple platforms. This enables component-based installation, allowing tools like CPack to selectively install runtime components without including development or other parts. Improves packaging flexibility for macOS builds.
- Add "tray" subcommand to CLI for launching tray interface on macOS
- Improve Electron app copying with fallback paths for different architectures
- Fix installation paths to use absolute directories for proper macOS packaging
- Add CPACK_SET_DESTDIR for correct package relocation
- Rename notarize_package target to notarize and update dependencies
- Add method to retrieve server launchctl output for tray app integration

These changes enhance macOS support by introducing a tray interface for easier server management and fixing build/installation issues for better packaging and notarization.
@jeremyfowers jeremyfowers added this pull request to the merge queue Feb 4, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Feb 4, 2026
@Geramy Geramy added this pull request to the merge queue Feb 4, 2026
Merged via the queue into main with commit b46e494 Feb 4, 2026
34 checks passed
@Geramy Geramy deleted the geramy/macosx-support-stg1 branch February 4, 2026 04:44
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.

4 participants