diff --git a/Makefile b/Makefile index 7a85a76..dadf335 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ RELEASE_DIR := $(BUILD_DIR)/release APP_BUNDLE := $(BUILD_DIR)/$(APP_NAME).app INSTALL_DIR := /Applications CLI_INSTALL := $(HOME)/.local/bin +CODESIGN_IDENTITY ?= - .PHONY: build run install uninstall clean dmg help @@ -27,8 +28,8 @@ build: cp -R Resources/zh-Hans.lproj "$(APP_BUNDLE)/Contents/Resources/" cp "$(RELEASE_DIR)/$(CLI_NAME)" "$(APP_BUNDLE)/Contents/Resources/$(CLI_NAME)" - @echo "πŸ” Ad-hoc code signing…" - codesign --force --sign - "$(APP_BUNDLE)" + @echo "πŸ” Code signing app bundle with identity '$(CODESIGN_IDENTITY)'…" + codesign --force --sign "$(CODESIGN_IDENTITY)" "$(APP_BUNDLE)" @echo "βœ… Build complete β†’ $(APP_BUNDLE)" @@ -66,6 +67,10 @@ dmg: build rm -f "$(BUILD_DIR)/$(APP_NAME).dmg" hdiutil create -ov -volname "$(APP_NAME)" -srcfolder "$(BUILD_DIR)/dmg_stage" -format UDZO "$(BUILD_DIR)/$(APP_NAME).dmg" rm -rf "$(BUILD_DIR)/dmg_stage" + @if [ "$(CODESIGN_IDENTITY)" != "-" ]; then \ + echo "πŸ” Signing DMG volume…"; \ + codesign --force --sign "$(CODESIGN_IDENTITY)" "$(BUILD_DIR)/$(APP_NAME).dmg"; \ + fi @echo "βœ… DMG packaging complete β†’ $(BUILD_DIR)/$(APP_NAME).dmg" # ── Clean ──────────────────────────────────────────────────── diff --git a/README.md b/README.md index 7af063f..9bff82f 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,37 @@ A macOS menu-bar status light app β€” a breathing LED that lives in your status - **LSUIElement** β€” no Dock icon, pure menu-bar app - macOS 14+ (Sonoma) -## Build & Run +## Build & Installation + +### Option 1: Direct Build & Installation +Build the app and install it to your system paths: ```bash make build # Build release binary & .app bundle -make run # Build and launch -make install # Copy to /Applications + ~/.local/bin +make run # Build and launch immediately +make install # Copy .app to /Applications and CLI helper to ~/.local/bin make clean # Remove build artifacts ``` +### Option 2: Package as DMG +Build a clean, shareable disk image (.dmg) containing `Signal.app` and a shortcut to `/Applications`: + +```bash +make dmg # Packages the app into .build/Signal.dmg +``` + +To install: +1. Open the DMG and drag `Signal.app` to your `Applications` folder. +2. Launch the application. +3. Open the status bar controls and click **"Install 'sgnl' CLI Command"** to install the `sgnl` command line tool directly to `~/.local/bin` without using terminal scripts. + +--- + +## Code Signing & Troubleshooting + +For instructions on signing the application with an Apple Developer Account, or resolving macOS Gatekeeper warnings ("app is damaged" / "unidentified developer"), please see [SIGNING.md](SIGNING.md). + + ## CLI Usage ```bash diff --git a/SIGNING.md b/SIGNING.md new file mode 100644 index 0000000..fb813e6 --- /dev/null +++ b/SIGNING.md @@ -0,0 +1,58 @@ +# Code Signing & Gatekeeper Guide + +Because Signal is distributed outside the Mac App Store and relies on ad-hoc (self) signing by default, you may see a Gatekeeper warning stating that the app is "damaged" or from an "unidentified developer" when running it on another machine. + +This document describes how to configure official code signing for distribution, or how to bypass these security warnings for local development and testing. + +--- + +## 1. Official Code Signing (For Distribution) + +If you have a paid Apple Developer Account, you can sign both the application bundle and the generated DMG. + +### Prerequisites +You must have a **Developer ID Application** certificate installed in your macOS Keychain. You can find its name in the Keychain Access app (e.g., `"Developer ID Application: Your Name (TEAMID)"`). + +### How to Sign +Pass your signing identity when running `make dmg` or `make build`: + +```bash +# Package the DMG and sign both the app bundle and the DMG file +make dmg CODESIGN_IDENTITY="Developer ID Application: Your Name (TEAMID)" + +# Or build the app bundle and sign it +make build CODESIGN_IDENTITY="Developer ID Application: Your Name (TEAMID)" +``` + +### Notarization & Stapling +To completely avoid Gatekeeper blocks, you must submit the signed DMG to Apple's Notary Service: + +1. **Submit for Notarization**: + ```bash + xcrun notarytool submit .build/Signal.dmg --apple-id "your-apple-id" --team-id "YOUR_TEAM_ID" --password "your-app-specific-password" --wait + ``` +2. **Staple the Ticket**: + Once approved, attach the notarization ticket to the DMG: + ```bash + xcrun stapler staple .build/Signal.dmg + ``` + +--- + +## 2. Gatekeeper Bypass (For Local Testing) + +If you compile the app locally or download an unsigned/ad-hoc signed DMG, macOS may prevent the app from launching. You can bypass this using one of the following methods. + +### Method A: Right-Click Open (Recommended) +1. Locate `Signal.app` in Finder (typically in `/Applications`). +2. **Right-click** (or Control-click) the application icon and choose **Open** from the context menu. +3. A warning dialog will appear. Click **Open** (or **Open Anyway**) to confirm. +4. macOS will remember this preference, and the app will open normally in the future. + +### Method B: Terminal Command (Clear Quarantine Flag) +When apps are downloaded or copied over networks, macOS attaches a `com.apple.quarantine` extended attribute. You can remove this flag using the `xattr` tool in your terminal: + +```bash +xattr -d com.apple.quarantine /Applications/Signal.app +``` +Once run, the app will launch immediately without warnings.