# AirPrint Bridge — User Guide

## 1. Quick Start

**AirPrint Bridge** is a macOS shell script that broadcasts any CUPS-shared printer as an AirPrint-compatible service on your local network. iPhones, iPads, and other Apple devices can then discover and print to it without any extra app or driver installation on the mobile device.

**Key features:**

- Converts any printer already shared via CUPS into an AirPrint-visible printer
- Introspects printer capabilities (color, duplex, media sizes, print quality) and builds accurate AirPrint URF records automatically
- Installs as a macOS LaunchDaemon so the bridge starts at boot and stays running
- Configures CUPS remote access (`Allow @LOCAL`) and the macOS firewall automatically — no manual config editing required
- Provides a dry-run test mode (`-t`) to verify everything works before committing to a permanent install
- Full uninstall restores every change the script made
- Available via Homebrew for easy installation and upgrades

**Prerequisites:** macOS with at least one printer already added and shared in System Settings. Homebrew is recommended but optional.

**Install and run in three commands:**

```bash
brew tap sapireli/AirPrint_Bridge
brew install airprint-bridge
sudo airprint-bridge -i
```

> [!TIP]
> Run `sudo airprint-bridge -t` first to verify your printers are detected and advertised without making permanent changes. Press `Ctrl-C` to exit the test.

---

## 2. Installation

### 2.1 System Requirements

| Requirement | Detail |
|---|---|
| Operating system | macOS (any version supported by your Homebrew installation) |
| Printer sharing | At least one printer shared via System Settings → General → Sharing → Printer Sharing |
| Privileges | `sudo` / root required for install, uninstall, and test modes |
| Runtime tools | `dns-sd`, `lpstat`, `lpoptions`, `launchctl` — all ship with macOS |
| Homebrew | Recommended; manual install also supported |

> [!IMPORTANT]
> The script requires `sudo` for all three operational modes (`-i`, `-u`, `-t`). Running without root prints an error and exits immediately. This is because CUPS configuration and LaunchDaemon management both require elevated privileges.

### 2.2 Install via Homebrew (Recommended)

```bash
# Add the tap
brew tap sapireli/AirPrint_Bridge

# Install the airprint-bridge command
brew install airprint-bridge
```

```text
==> Tapping sapireli/AirPrint_Bridge
...
==> Installing airprint-bridge from sapireli/AirPrint_Bridge
...
AirPrint Bridge has been installed to /usr/local/bin/airprint-bridge
```

After installation, follow the workflow in Section 4 to bring the bridge online.

### 2.3 Install from Source (Manual)

```bash
# Clone the repository
git clone https://github.com/sapireli/AirPrint_Bridge.git
cd AirPrint_Bridge

# Make the script executable and place it in your PATH
chmod +x airprint_bridge.sh
sudo cp airprint_bridge.sh /usr/local/bin/airprint-bridge
```

### 2.4 Post-install Verification

```bash
airprint-bridge -h
```

```text
Usage: airprint-bridge [-i | -u | -t] [-f script_file] [-h]
  -i  Install (requires sudo)
  -u  Uninstall (requires sudo)
  -t  Test (dry run mode), use CTRL-C to exit
  -f  Script filename and location
  -h  Print this message
```

> [!NOTE]
> The Homebrew formula installs the script as `airprint-bridge` (hyphen) in `/usr/local/bin`. The source file on disk is named `airprint_bridge.sh` (underscore). Both refer to the same program.

---

## 3. Configuration

AirPrint Bridge does not use a configuration file. All behavior is determined at runtime by querying CUPS. The only prerequisite is that your printers are shared before you run the bridge.

### 3.1 Share Your Printers First

Before running AirPrint Bridge, every printer you want to expose must be:

1. Installed in macOS (visible in System Settings → Printers & Scanners)
2. Shared: System Settings → General → Sharing → Printer Sharing → enable the toggle for each printer

> [!IMPORTANT]
> AirPrint Bridge only processes printers that CUPS reports as shared (`printer-is-shared=true`). An unshared printer will not appear in the AirPrint list, even if it is installed and working.

### 3.2 What the Script Configures Automatically

When you run `sudo airprint-bridge -i` or `sudo airprint-bridge -t`, the script handles all of the following without manual intervention:

| Task | File / Service Modified | Condition |
|---|---|---|
| CUPS remote access | `/etc/cups/cupsd.conf` | Only if `Allow @LOCAL` is absent |
| User access for shared printers | CUPS printer configuration | Only if a shared printer is not set to allow all users |
| Firewall exception for CUPS | macOS Application Firewall | Only if the firewall is enabled and CUPS is not already allowed |
| Backup of original CUPS config | `/etc/cups/cupsd.conf.bak` | Only on first auto-modification |

> [!NOTE]
> If the script modifies `/etc/cups/cupsd.conf`, a backup is saved as `/etc/cups/cupsd.conf.bak` before any change is made. The uninstaller (`-u`) restores this backup automatically.

### 3.3 Internal Variables (Advanced)

The following variables are defined at the top of `airprint_bridge.sh` and can be edited before installation if you need non-default behavior:

| Variable | Default | Purpose |
|---|---|---|
| `LOGGING` | `0` | Set to `1` to write log output to `airprint_bridge.log` in addition to stderr |
| `LOGFILE` | `airprint_bridge.log` | Log file path when `LOGGING=1` |
| `SERVICE` | `_ipp._tcp.,_universal` | Bonjour service type broadcast by `dns-sd` |
| `DOMAIN` | `local` | mDNS domain for service registration |
| `SCRIPT` | `airprint_bridge_launcher.sh` | Name of the generated per-printer registration script |

See the Admin Guide for a full description of every internal variable and generated file.

---

## 4. Core Usage

### 4.1 Command Reference

```bash
sudo airprint-bridge [-i | -u | -t] [-f script_file] [-h]
```

| Flag | Name | Requires `sudo` | Description |
|---|---|:---:|---|
| `-i` | Install | Yes | Detects shared printers, builds AirPrint registration, installs LaunchDaemon so the bridge starts at boot |
| `-u` | Uninstall | Yes | Stops and removes the LaunchDaemon, deletes the registration script, restores CUPS config if modified |
| `-t` | Test | Yes | Dry-run: performs all checks and printer detection identically to install, then runs registration in the foreground. Press `Ctrl-C` to exit |
| `-f FILE` | Script file | — | Override the generated launcher script name/path |
| `-h` | Help | No | Print usage and exit |

> [!WARNING]
> Exactly one of `-i`, `-u`, or `-t` must be specified. The script will print an error and show usage if all three are omitted.

### 4.2 Installing the Bridge as a Persistent Service

```bash
# Step 1: Share printers in System Settings (see Section 3.1)

# Step 2: Optionally test first
sudo airprint-bridge -t

# Step 3: Install permanently
sudo airprint-bridge -i
```

A successful install produces output similar to:

```text
Checking CUPS permissions...
CUPS remote access is already allowed.
Checking macOS firewall...
Firewall is disabled; skipping.
Listing local shared printers...
Found 1 printer(s) to process:
 - HP_LaserJet_P1102w
Resolving "HP_LaserJet_P1102w"...
Device URI: ipp://192.168.1.5/ipp/print
Description: HP LaserJet P1102w
Generating ./airprint_bridge_launcher.sh...
Copying airprint_bridge_launcher.sh to /usr/local/bin...
Generating /Library/LaunchDaemons/com.sapireli.airprint_bridge.plist...
Plist loaded: /Library/LaunchDaemons/com.sapireli.airprint_bridge.plist
Installation complete.
```

After installation, your iOS/iPadOS devices will discover the printer in any app with a print option.

### 4.3 Running a Test (Dry Run)

```bash
sudo airprint-bridge -t
```

Test mode goes through full dependency checking, CUPS permission checking, firewall checking, printer detection, URF generation, and registration script generation — then runs the `dns-sd` registration live in the foreground. The AirPrint advertisement is active only while the script is running. Press `Ctrl-C` to stop.

> [!TIP]
> While the test is running, open any app with a print option on an iPhone or iPad and look for your printer in the printer picker. This confirms the Bonjour advertisement is working before you install permanently.

### 4.4 Uninstalling

```bash
sudo airprint-bridge -u
```

Uninstall performs these steps in order:

1. Restores `/etc/cups/cupsd.conf` from backup if the script had modified it
2. Unloads and removes `/Library/LaunchDaemons/com.sapireli.airprint_bridge.plist`
3. Removes `/usr/local/bin/airprint_bridge_launcher.sh`
4. Kills any running `dns-sd` processes that were advertising the AirPrint service

---

## 5. Common Tasks

### 5.1 Add a New Printer After the Bridge Is Already Installed

Reinstall the bridge to pick up any newly shared printer:

```bash
sudo airprint-bridge -u   # Remove old registration
sudo airprint-bridge -i   # Reinstall with all current shared printers
```

### 5.2 Verify the Bridge Is Running

```bash
# Check if the LaunchDaemon is loaded
sudo launchctl list | grep airprint

# Check if dns-sd is running
pgrep -fl "dns-sd -R"
```

```text
com.sapireli.airprint_bridge.plist
```

### 5.3 Restart the Bridge Without Reinstalling

```bash
sudo launchctl stop com.sapireli.airprint_bridge.plist
sudo launchctl start com.sapireli.airprint_bridge.plist
```

### 5.4 View the Generated Registration Script

```bash
cat /usr/local/bin/airprint_bridge_launcher.sh
```

The launcher contains one `dns-sd -R` command per shared printer, with the full set of AirPrint TXT records derived from that printer's capabilities.

### 5.5 Enable Logging

Open `airprint_bridge.sh` (or `/usr/local/bin/airprint-bridge`) in a text editor, change `LOGGING=0` to `LOGGING=1`, then reinstall:

```bash
sudo airprint-bridge -u
sudo airprint-bridge -i
```

Logs are written to `airprint_bridge.log` in the directory from which you ran the script.

### 5.6 Upgrade via Homebrew

```bash
brew upgrade airprint-bridge
sudo airprint-bridge -u   # Remove old service
sudo airprint-bridge -i   # Reinstall with upgraded script
```

---

## 6. Troubleshooting

### Diagnostic Decision Tree

```
Printer not visible on iPhone/iPad?
 ├─ Is the printer shared in System Settings? (Sharing → Printer Sharing)
 │   └─ No → Share it, then: sudo airprint-bridge -u && sudo airprint-bridge -i
 ├─ Is the bridge running? (pgrep -fl "dns-sd -R")
 │   └─ No → sudo launchctl start com.sapireli.airprint_bridge.plist
 ├─ Are the Mac and iOS device on the same Wi-Fi network?
 │   └─ No → Connect them to the same network
 └─ Run test mode and review output: sudo airprint-bridge -t
```

---

### Error: `Error: You must run this script as root (sudo) to install, uninstall, or test.`

**Cause:** The script was invoked without `sudo`.

**Solution:**

```bash
sudo airprint-bridge -i
```

**Prevention:** Always prefix the command with `sudo`.

---

### Error: `Error: Required command 'dns-sd' is not installed.`

**Cause:** One of the required macOS command-line tools (`dns-sd`, `lpstat`, `lpoptions`, `launchctl`) was not found.

**Solution:**

1. Confirm you are running macOS (not Linux).
2. Check that the missing tool is present: `which dns-sd`
3. Reinstall macOS Command Line Tools if needed: `xcode-select --install`

**Prevention:** These tools ship with macOS and are not expected to be missing on a standard installation.

---

### Error: `No shared printers found.`

**Cause:** No printer in CUPS has `printer-is-shared=true`.

**Solution:**

1. Open System Settings → General → Sharing → Printer Sharing.
2. Enable sharing for each printer you want to expose.
3. Run the bridge again.

**Prevention:** Share printers before running the bridge.

---

### Error: `client-error-not-authorized` in CUPS logs (Issue #7)

**Cause:** CUPS is rejecting print jobs from iOS because remote access is restricted.

**Solution:**

AirPrint Bridge auto-fixes this by adding `Allow @LOCAL` to `/etc/cups/cupsd.conf`. If the error persists after installation:

1. Run `sudo airprint-bridge -u && sudo airprint-bridge -i` to force a fresh fix.
2. Manually verify `/etc/cups/cupsd.conf` contains `Allow @LOCAL` in the `<Location />` block.

---

### Duplicate printers shown in the AirPrint list (Issues #14, #17, #27)

**Cause:** Multiple `dns-sd` processes are advertising the same printer, typically from a prior install that was not fully removed.

**Solution:**

```bash
sudo airprint-bridge -u   # Full uninstall (kills all AirPrint dns-sd processes)
sudo airprint-bridge -i   # Clean reinstall
```

**Prevention:** Always uninstall before reinstalling.

---

### Printer only prints in black and white (Issues #9, #32)

**Cause:** The printer's CUPS driver does not expose color mode capabilities via `lpoptions -l`. The URF generator can only advertise what the driver reports.

**Solution:**

1. Update or reinstall the printer driver.
2. After the driver update, reinstall the bridge so the URF record is regenerated with the updated capabilities.

---

### Brew tap not found (Issue #25)

**Cause:** The tap command used an incorrect repository path.

**Solution:**

```bash
brew tap sapireli/AirPrint_Bridge
brew install airprint-bridge
```

Use exactly `sapireli/AirPrint_Bridge` (capital A, capital P, capital B) as the tap name.

---

### Printer not found / unable to configure (Issues #28, #33)

**Cause:** The printer is not registered in CUPS, or is installed but not shared.

**Solution:**

1. Add the printer in System Settings → Printers & Scanners.
2. Enable sharing in System Settings → General → Sharing → Printer Sharing.
3. Run `lpstat -p` to confirm the printer is listed.
4. Reinstall the bridge.

---

### Printer and User lists keep clearing (Issue #31)

**Cause:** Reported on macOS Sequoia (Tahoe 26.2) with a Brother HL-2270DW. The CUPS configuration or printer sharing settings may be reset by a macOS update.

**Solution:**

Re-share the printer and reinstall the bridge after any macOS upgrade:

```bash
sudo airprint-bridge -u
sudo airprint-bridge -i
```

---

## 7. FAQ

**Q: What macOS versions are supported?**

AirPrint Bridge uses only built-in macOS tools (`dns-sd`, `lpstat`, `lpoptions`, `launchctl`, `socketfilterfw`). There is no hard version requirement in the source. The Homebrew formula declares `depends_on :macos`.

---

**Q: Does AirPrint Bridge work on Linux or Windows?**

No. The script uses macOS-specific tools and installs a LaunchDaemon. It is macOS-only.

---

**Q: Does the bridge survive reboots?**

Yes. Install mode (`-i`) creates a LaunchDaemon at `/Library/LaunchDaemons/com.sapireli.airprint_bridge.plist` with `RunAtLoad=true` and `KeepAlive=true`. The bridge starts automatically at boot and restarts if the process exits unexpectedly.

---

**Q: Will this affect my existing native AirPrint printers?**

No. The script processes only printers that CUPS reports as shared. It does not modify printers that already broadcast AirPrint natively.

---

**Q: How does the bridge know the printer's capabilities?**

It queries CUPS via `lpoptions -l -p <printer>` and parses the `ColorModel`, `Duplex`, `PageSize`, `MediaType`, `InputSlot`, and `cupsPrintQuality` lines to build a URF (Universal Raster Format) capabilities string. This string is included in the Bonjour TXT record so iOS knows what the printer can do.

---

**Q: Can I use this with multiple printers?**

Yes. The bridge processes all shared printers in one pass and registers each as a separate Bonjour service.

---

**Q: How do I change the default paper size?**

Paper size defaults come from the printer's CUPS configuration. Change the default in System Settings → Printers & Scanners → select your printer → Options & Supplies, then reinstall the bridge so the updated capabilities are reflected in the AirPrint TXT records. See issue #30 for community context on this topic.

---

**Q: Can I install via Homebrew Cask?**

The repository ships a standard Homebrew formula, not a Cask. Cask support was requested (issue #13) but the project uses the formula approach. Install with `brew tap sapireli/AirPrint_Bridge && brew install airprint-bridge`.

---

**Q: What does test mode (`-t`) actually change on my system?**

Test mode runs every setup step — dependency checks, CUPS permission fixes, firewall checks, printer detection, URF generation, and registration script generation — but runs the registration in the foreground instead of installing a LaunchDaemon. CUPS config and firewall changes do still apply in test mode. Press `Ctrl-C` to stop; the AirPrint advertisement ends immediately.

---

**Q: How do I report a bug or request a feature?**

Visit [https://github.com/sapireli/AirPrint_Bridge/issues](https://github.com/sapireli/AirPrint_Bridge/issues).

---

_Generated May 2026 from sapireli/AirPrint_Bridge at 743085a. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
