Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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)"

Expand Down Expand Up @@ -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 ────────────────────────────────────────────────────
Expand Down
28 changes: 25 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
58 changes: 58 additions & 0 deletions SIGNING.md
Original file line number Diff line number Diff line change
@@ -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.
Loading