Skip to content

Repository files navigation

ScanPaste app icon

ScanPaste

Move text, images, and files from your Mac to any nearby device.
Scan once. Nothing to install on your phone.

English · 简体中文

macOS 15.0+ Swift 5.0 CI MIT License

ScanPaste is a lightweight macOS menu bar app that exposes a temporary, authenticated page on your local network. Open it by scanning a QR code, then copy Mac text, save an image, or download a file from an iPhone, iPad, Android device, or any modern browser.

No companion app. No keyboard extension. No account. No cloud relay.

What it does

Text Images Files
Browse up to 10 recent entries and copy with browser-compatible fallbacks. Preview a thumbnail, open the original, then long-press to save or use the system share sheet when available. Download one or several regular files with short-lived tickets, streaming, and HTTP Range support.

Additional details:

  • Native SwiftUI menu bar interface with no Dock icon.
  • First-run onboarding, resizable settings, configurable port, and launch-at-login support.
  • English and Simplified Chinese on both macOS and the mobile page.
  • Clipboard history exists only in memory and is cleared when ScanPaste quits.
  • Diagnostic logs contain metadata only, rotate daily, and are retained for up to 7 days.

Quick start

  1. Launch ScanPaste and click its clipboard icon in the menu bar.
  2. Select a local address if needed, then click Generate Sharing QR Code.
  3. Scan the code with a phone or tablet connected to the same reachable network.
  4. Tap Refresh to browse recent clipboard entries.

The sharing session stops automatically after 30 minutes. You can stop or regenerate it at any time from the menu bar.

How it works

flowchart LR
    A["macOS pasteboard"] --> B["In-memory history<br/>up to 10 entries"]
    B --> C["Local NWListener<br/>temporary HTTP session"]
    C --> D["QR code with token<br/>stored in URL fragment"]
    D --> E["Mobile browser"]
    E -->|"Authenticated refresh"| C
    C -->|"Text, image, or file stream"| E
Loading

ScanPaste checks NSPasteboard.changeCount every 3 seconds. A clipboard change becomes one newest-first history entry:

Clipboard content Storage Limit
Text Full text in memory 1 MiB per entry
Copied image or screenshot PNG snapshot plus JPEG thumbnail in memory 15 MiB per image, 64 MiB total image budget
Files copied from Finder File URL and safe metadata only; bytes are read during download Up to 20 regular files per entry

Finder image files are treated as files. To exercise the image-preview path, copy image pixels from Preview or a browser, or use Control-Shift-Command-4 to capture a screenshot to the clipboard.

The web UI lives in ScanPaste/Web as standalone HTML, CSS, and JavaScript resources. Runtime strings and limits are supplied by /api/config.

Security and privacy

ScanPaste is designed for short-lived use on a trusted local network:

  • Every sharing session receives a new cryptographically secure random token and expires after 30 minutes.
  • The token stays in the QR URL fragment, which is not sent in the initial HTTP request. JavaScript sends it later in the X-ScanPaste-Token header.
  • File downloads use resource-scoped random tickets that expire after 2 minutes; the session token is never placed in a download URL.
  • Page and API responses disable caching.
  • Absolute Mac file paths are never returned to the browser.
  • Logs do not record clipboard bodies, access tokens, or absolute file paths.

The current local server uses plain HTTP. Traffic is not encrypted, so do not transfer passwords, private keys, or other sensitive material on public or untrusted Wi-Fi.

Hardened Runtime is enabled. App Sandbox is currently disabled, so the project is suitable for local builds, unsigned distribution, or Developer ID distribution, but not direct Mac App Store submission in its current form.

Current limits

  • Mac to mobile only; the browser cannot send content back to the Mac yet.
  • Local network only; there is no remote HTTPS relay.
  • Folders are skipped rather than archived.
  • Images larger than 15 MiB are skipped and reported on the mobile page.
  • A referenced file must still exist and match its captured size, modification date, and resource identity when downloaded.
  • Web Share and modern Clipboard APIs depend on browser and secure-context support; the page includes practical fallbacks for local HTTP.

Build from source

Requirements:

  • macOS 15.0 or later
  • Xcode 26 or a compatible toolchain
git clone https://github.com/sugite/ScanPaste.git
cd ScanPaste
open ScanPaste.xcodeproj

Select the shared ScanPaste scheme and run on My Mac. For an unsigned command-line build:

xcodebuild \
  -project ScanPaste.xcodeproj \
  -scheme ScanPaste \
  -configuration Release \
  CODE_SIGNING_ALLOWED=NO \
  build

Releases

To build the same unsigned ZIP published on GitHub Releases locally:

bash Scripts/package-release.sh 1.0.0

The script creates these files under dist/:

ScanPaste-1.0.0-macOS.zip
ScanPaste-1.0.0-macOS.zip.sha256

Publishing is automated by .github/workflows/release.yml. After the release commit is on main, create and push a semantic version tag:

git tag -a v1.0.0 -m "ScanPaste v1.0.0"
git push origin v1.0.0

GitHub Actions runs the test suite, builds the Release app, packages it, generates its SHA-256 checksum, and creates a GitHub Release with both files attached. GitHub's automatically generated “Source code” archives contain source only; users should download ScanPaste-<version>-macOS.zip instead.

Current release archives are unsigned. On first launch, users need to right-click Open, or approve ScanPaste in System Settings → Privacy & Security. A future Developer ID release can add signing, Apple notarization, and a DMG without changing the tag-based release flow.

Troubleshooting

The phone cannot open the page

  • Confirm the Mac and mobile device can reach each other on the current network.
  • Try another address shown in the menu bar app.
  • Allow incoming connections and local-network access when macOS prompts.
  • Avoid guest Wi-Fi or networks with client isolation.

The page says the token is invalid

Generate a new QR code and open the complete scanned URL. Old tabs belong to earlier sharing sessions and will be rejected.

A file can no longer be downloaded

The file may have moved or changed since it was copied. Copy it again in Finder and refresh the page.

Need more detail

Open Settings → Open Log Folder. Logs are stored under ScanPaste's Application Support directory, split by day, and automatically deleted after 7 days.

Project structure

ScanPaste/
├── ScanPasteApp.swift             Menu bar app entry point
├── ClipboardServer.swift          Local HTTP routes and sessions
├── HTTPRequestParser.swift        Strict HTTP request validation
├── ClipboardHistoryStore.swift    Text, image, and file history
├── FileDownloadResponder.swift    Streaming and Range responses
├── AppLogger.swift                Rotating diagnostic logs
├── Localizable.xcstrings          English and Chinese strings
└── Web/                            Mobile browser interface
ScanPasteTests/                     Parser and logging security tests

Roadmap

  • Recent text clipboard
  • Image preview and original-image access
  • Multiple regular-file downloads
  • Localized macOS and mobile interfaces
  • Automated unsigned ZIP releases
  • Remote HTTPS relay
  • Explicit mobile-to-Mac transfer
  • Signed releases and automatic updates

Contributing

Issues and pull requests are welcome. Please keep changes focused, preserve the zero-install mobile workflow, update both English and Simplified Chinese user-facing text, and verify the shared ScanPaste scheme builds and tests before opening a pull request.

For security-sensitive findings, avoid posting tokens, clipboard content, or private file paths in a public issue.

License

ScanPaste is released under the MIT License.

About

Scan your Mac clipboard. No phone app required.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages