Install the T1 daemon
The T1 daemon is a headless background process that hooks your OS clipboard. Copy on your laptop → paste on your phone. Copy on your phone → paste on your workstation. All encrypted end-to-end.
Runs anywhere Python runs. Install-and-forget on Linux (systemd user unit) and macOS (LaunchAgent); Windows Task Scheduler works too.
Prerequisites#
- Python 3.10 or newer with
pip. - A ScaiGrid API key with scopes
scaiclip:readandscaiclip:write. - Linux: one of
xclip,xsel, orwl-copy(Wayland). The daemon auto-detects.
Install the daemon package (this is currently distributed as the ScaiGrid repo — a standalone PyPI wheel lands in a follow-up):
1 2 3 | |
Test the daemon runs:
1 2 3 | |
You should see the daemon connect, subscribe to your personal channel, and start watching the clipboard. Copy something and check the log — [pub] seq=1 len=N recips=1.
Linux — systemd user service#
The daemon ships a hardened systemd unit file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
The unit is hardened — restricted paths, no new privileges, memory + CPU caps. Reads its API key from ~/.config/scaiclip/env rather than the unit file so you can rotate keys without touching systemd.
macOS — LaunchAgent#
1 2 3 4 5 6 7 8 9 10 11 12 | |
Windows — Task Scheduler#
Windows-native support is coming; for now use Task Scheduler:
- Open Task Scheduler → Create Task.
- General: name
ScaiClip Daemon. Check "Run whether user is logged on or not" if you want autostart before login; otherwise leave default. - Triggers: add "At log on".
- Actions:
Start a program. Program:python. Arguments:-m modules.scaiclip.tools.t1_daemon --profile %COMPUTERNAME%. Start in: your ScaiGrid repo root. - Environment: set
SCAIGRID_HOSTandSCAIGRID_API_KEYin the user'sSystem Properties → Environment Variablesbefore creating the task.
Log output goes to whatever console the task runs in; redirect to a file in the Arguments field if you want persistence.
Enrolling a second device#
Once the daemon runs on device A, enrol device B by running the daemon there with a distinct --profile name (usually the machine's hostname). First launch calls POST /devices/me to register B's keys with ScaiKey. Both devices' KEM public keys land in the directory; the next clip published on either device gets wrapped for both.
If device B was offline when A first published a clip, that specific clip won't be readable on B — its wrap wasn't included. Future clips will be. The onboarding-broker flow that back-fills clips for late-joining devices is on the roadmap.
Verifying it works#
Copy a distinctive string on device A. Within ~350 ms plus network RTT, the same string should appear in device B's clipboard. Paste it into a text editor to confirm.
If nothing happens:
1 2 3 4 5 | |
Common causes:
no OS clipboard backend detected— installxcliporwl-copyon Linux. macOS/Windows should work out of the box.[warn] directory lookup failed— API key doesn't havescaiclip:readscope, or the ScaiGrid endpoint isn't reachable.[recv] no matching wrap— the publishing device didn't include a wrap for the receiver. Usually means the receiver enrolled after the clip was published; try copying something new.
Uninstall#
Linux:
1 2 3 4 | |
macOS:
1 2 3 | |
To also delete the device from your ScaiKey account, use DELETE /v1/modules/scaiclip/devices/me/{device_id} — the daemon will refuse to reconnect after that.
Optional tray UI#
The tray UI is a PySide6 GUI companion that embeds the daemon in a background thread. Shows a system-tray icon with:
- Recent clips (last 20) — click to re-copy.
- Pause/resume publish toggle.
- Notifications on inbound clips.
- About + quit.
Install PySide6 and run the tray instead of the daemon:
1 2 | |
Without PySide6 installed, the tray script falls back to the headless daemon with a friendly message.
For persistent autostart with the tray, replace the ExecStart= line in scaiclip-daemon.service with -m modules.scaiclip.tools.t1_tray (Linux) or edit the plist arguments accordingly (macOS).
Image clip support#
The daemon publishes and receives PNG images on Linux via xclip or wl-copy. Copy an image → daemon detects, encrypts, uploads to scratch storage, publishes the envelope with a ref_scratch pointer. Receiver fetches from scratch, decrypts, writes the PNG back to the OS clipboard.
macOS + Windows image read/write is a follow-up (NSPasteboard + DataFormats gymnastics).
Team-channel onboarding#
The daemon fetches team-channel keys on connect (key.wraps.get). If no wrap exists for its device yet, the onboarding broker fires wrap.request to sibling devices. Any sibling running the daemon responds with key.wraps.put, the grid pushes wraps.ready, and the new daemon refetches. Result: fully automatic team-channel onboarding across devices.
What the daemon doesn't do yet#
- No file clips. Only text and PNG images. File-URI clipboard integration varies wildly across desktop environments and is deferred.
- No macOS/Windows image support. Text works everywhere; image read/write on those platforms needs native APIs.
- No T2 native platform integration. Deeper OS notifications, deeper platform hooks — separate track.
What's next#
- Two-device round trip — the manual client walkthrough the daemon is a productionized version of.
- Channels, envelopes, wraps, claims — what the daemon is doing under the hood.
- Troubleshooting — common error paths.