RelayPrint is a Windows and macOS desktop application for sharing one or more locally installed printers across a LAN with explicit pairing and per-printer authorization. Every installation can act as a host, a client, or both.
Warning
RelayPrint is alpha software. LAN traffic is encrypted and paired peers are pinned, but initial pairing still assumes a trusted private network. Do not treat locally built or unsigned installers as production releases.
The current source release line is 0.2.0-alpha.1. Exact application, agent, commit, platform, architecture, and LAN-protocol identity is available under Settings → About RelayPrint. Version policy and migration requirements are documented in docs/versioning.md and UPGRADING.md; official binaries, when qualified, are published only through GitHub Releases.
The repository contains the first runnable vertical slice:
- Electron, React, and TypeScript desktop shell.
- Go background agent with local authenticated IPC.
- Real operating-system printer enumeration on macOS, Linux/CUPS, and Windows.
- Persistent device identity, printers, queue, permissions, and settings in SQLite.
- Multi-path LAN discovery using DNS-SD/mDNS, UDP multicast announcements, and a bounded private-subnet fallback scan.
- Runtime LAN readiness checks, macOS local-network declarations and recovery, Windows local-subnet firewall rules, and manual private-IP discovery fallback.
- Six-digit pairing with one-time PIN rotation and per-device, per-printer capability tokens.
- TLS 1.3 transport with per-installation Ed25519 certificates, public-key pinning, and protocol-upgrade re-pairing.
- Keychain-backed secret protection on macOS and DPAPI-backed protection on Windows.
- IPP Everywhere data plane with bounded private spooling and reliable Create-Job/Send-Document support.
- Stable loopback IPP queues that keep host capabilities out of operating-system printer URLs.
- Native driverless queue installation and removal on macOS/CUPS and Windows; default-printer policy remains owned by the operating system.
- Host-authoritative queue visibility, per-device privacy, native spooler tracking, device blocking, and cancellation flows.
- Windows PDF rendering through an authenticated loopback Electron bridge, with Winspool status/cancellation and targeted remote-job routing.
The earlier macOS-to-Windows path was observed on real machines before the protocol-3 security migration. Every host/client combination must now be requalified with signed artifacts using docs/release-qualification.md. Public installer signing also requires maintainer-owned Apple and Windows signing credentials; no GitHub release is created from an untagged build.
- Node.js 22.12 or newer.
- Go 1.25.12 or newer.
- macOS or Windows for desktop runtime testing.
npm ci
npm run verify
npm run devSource builds store their state in a separate RelayPrint Development directory, so running a clone or fork does not alter pairing, queues, or settings from an installed RelayPrint build. Set RELAYPRINT_USER_DATA_DIR to an isolated absolute path when running multiple development instances.
For browser-only visual development, run the agent and Vite separately:
./apps/desktop/resources/bin/relayprint-agent --local-port 53842 --demo
npm run dev:webThe --demo flag is explicit and never enabled by the packaged application. It seeds visual test data and automatically restricts the agent to loopback, with no LAN listener or discovery advertisement. --dev-token uses the same safe default. Isolated integration tests can opt in with --network-scope lan.
- Both computers run RelayPrint on the same LAN.
- The printer owner enables Share on this network and shares the displayed six-digit pairing code.
- The client opens Computers, enters that code next to the discovered host, and pairs.
- The shared printers become available under Printers. Install printer registers the IPP queue with the operating system.
Pairing codes rotate after a successful pairing. Block revokes printer capability tokens while retaining the relationship so it can be restored. Forget removes RelayPrint queues from this computer, revokes access to printers shared by this computer, and deletes the local relationship. Relationships are local to each installation, so complete removal requires forgetting the peer on both computers.
A discovered computer is only a connection candidate; it is not an incoming approval request and does not appear under Printer access. Printer access can move from discovered to allowed only through a successful pairing-code exchange. The access screen can block or restore computers that have already completed pairing, but it cannot approve an unpaired discovery record. Discovery-only entries disappear after three minutes without fresh evidence and are pruned after 24 hours; Remove clears one immediately without affecting any paired relationship.
Automatic discovery starts with DNS-SD/mDNS and administratively scoped UDP multicast on 239.255.77.78:53844. A bounded scan of the default-route private IPv4 /24 probes the default RelayPrint TLS port 53843 when multicast is suppressed. Secondary adapters continue to participate in mDNS and UDP discovery, while manual IP probing remains available for uncommon multi-homed layouts. Each UDP or scan result is verified against the peer's TLS certificate and public identity endpoint before it is displayed; discovery still grants no printer access.
If automatic discovery is unavailable, open Computers → Add computer by IP and enter the host's private or IPv4 link-local address. Production hosts use LAN port 53843; RelayPrint does not silently move to a random port. If that port is unavailable, the app remains usable as a client but pauses hosting until the conflict is resolved and RelayPrint is restarted. Manual probing accepts only literal LAN IP addresses, never public URLs or hostnames, and pairing is still required.
The network-readiness row distinguishes hosting from outbound client discovery. Self-discovery never proves LAN permission, inbound traffic proves only hosting, and outbound peer evidence expires after three minutes. Scan now immediately repeats the UDP announcement and bounded subnet scan. On macOS, RelayPrint declares _relayprint._tcp, triggers Local Network access from the application process, and sends multicast from an explicit LAN source address before opening the privacy surface for user review. macOS permission cannot be granted, bypassed, or reset to an undetermined state programmatically; the user must enable RelayPrint under Privacy & Security → Local Network when the runtime probe reports EHOSTUNREACH, then return to RelayPrint and use Check again. On Windows, the per-machine installer creates and verifies inbound TCP and UDP application rules for every network profile, while still limiting access to the RelayPrint agent executable and LocalSubnet. Runtime diagnosis also verifies that the current agent process owns the expected LAN TCP listener. A Windows Public category therefore no longer requires changing the Wi-Fi profile to Private; pairing remains mandatory before printer metadata or print access is granted. Installer firewall diagnostics are stored in %ProgramData%\RelayPrint\logs\installer.log.
RelayPrint never changes the Windows or macOS default printer. Use OS printer settings for default-printer policy. Remote queues point to the local IPP bridge on 127.0.0.1:53845; the agent forwards them to the paired host through pinned TLS. Removing a remote queue from RelayPrint does not remove the pairing relationship.
Closing the RelayPrint window does not stop printer sharing. On Windows, the close button hides the window in the notification-area tray; its menu shows whether the agent is ready and how many printers are shared. On macOS, closing the window leaves RelayPrint active in the Dock and reopening the app restores the window. Use the explicit operating-system Quit RelayPrint action to stop the background agent.
Installed builds start automatically at user sign-in by default and remain quiet in the background instead of opening the main window. This preference is stored in desktop-settings.json and can be changed under Settings → Background service → Start when I sign in. Development builds never register the Electron development executable as an operating-system login item.
While at least one local printer is shared, RelayPrint prevents idle application/system suspension but still allows the display and screen saver to turn off. Forced system sleep, closing a laptop lid, shutdown, or an explicit quit pauses LAN printing because no desktop application can accept network traffic in those states. RelayPrint reruns its network check and discovery after resume or screen unlock.
Queue behavior, privacy boundaries, limits, and native-spooler status semantics are documented in docs/queue-model.md.
Persistent rotating logs are enabled by default for early cross-machine testing. On Windows they are stored in %APPDATA%\RelayPrint\logs; on macOS they are stored in ~/Library/Application Support/RelayPrint/logs. Use Settings → Diagnostics → Open logs folder to collect them.
See docs/logging.md for the event coverage, redaction policy, rotation limits, and Windows collection procedure.
# Local macOS arm64 DMG and ZIP with a valid ad-hoc signature
npm --workspace @relayprint/desktop run dist:local:mac -- --arm64
# Windows x64 sidecar and per-machine NSIS installer
npm run build:agent:windows
npm --workspace @relayprint/desktop run dist -- --win --x64Artifacts are written to apps/desktop/release/. Local macOS packages are ad-hoc signed and are for development only; reliable Local Network identity across upgrades requires an Apple-issued signing identity. Tagged GitHub builds require Developer ID signing, notarization and stapling on macOS plus Authenticode signing on Windows. The tag-only workflow accepts exact prerelease SemVer tags from protected main, keeps signing credentials in reviewed GitHub environments, verifies platform-job digests and the macOS code-signing identifier before publication, and emits SHA-256 checksums, an SPDX SBOM, and GitHub artifact attestations. It deliberately excludes updater blockmaps. See docs/release-qualification.md before configuring release secrets or tags.
Read CONTRIBUTING.md before submitting a change. Fork-specific setup and isolation guidance lives in FORKING.md. Support and privacy expectations are documented in SUPPORT.md and PRIVACY.md. Report suspected vulnerabilities privately using the process in SECURITY.md, not through a public issue.
RelayPrint is licensed under the Apache License 2.0. Third-party dependencies remain under their respective licenses and are recorded in THIRD_PARTY_NOTICES.txt.