Files
scrot/README.md
T

94 lines
3.9 KiB
Markdown
Raw Normal View History

# scrot
Clipboard sync across your own devices, and screenshot → instant public
link. One blob store, one small server, two thin CLI scripts.
## Why
Two small itches, solved by the same mechanism — see
[PROPOSAL.md](./PROPOSAL.md) for the full design rationale, and why this
isn't just `wisp` or `flit` again:
- **Clipboard sync**: copy on one machine, pull it on another, without a
cloud clipboard manager that might get paywalled or discontinued.
- **Screenshot → link**: capture a region, get a shareable URL on your
clipboard immediately, without an Imgur/CloudApp-style third-party
uploader.
## Model
A single `blobs` table with a `kind`:
- `clip` — private, text. Pull-only — your other devices ask "what's the
latest clip?" No public URL is ever minted.
- `shot` — public, image. Upload returns a short link (`/s/:id`) anyone
with the link can view — no auth required, same trust level as handing
someone a photo link.
Single shared `DEVICE_TOKEN` gates every write and the private clip-read —
this is single-user infrastructure across your own machines, not a
multi-tenant service, so there's no per-device registry to manage.
No end-to-end encryption: unlike `wisp` (built for sharing with other
people), this server is already fully trusted homelab infra, same trust
level as `keep`/`trace`. Adding client-side crypto here would defend
against a threat that doesn't apply.
## Server
```bash
cd server
npm install
DEVICE_TOKEN=... npm run dev
```
See [.env.example](./.env.example) for the full config surface
(`CLIP_TTL_SECONDS`, `SHOT_TTL_SECONDS`, `MAX_UPLOAD_BYTES`, ...).
## CLI
Four scripts in [cli/](./cli/), each meant to sit behind a keybinding:
- `scrot-clip-push` — pushes the current system clipboard as a `clip`.
- `scrot-clip-pull` — fetches the latest `clip` into the system clipboard.
- `scrot-shot` — captures a region screenshot, uploads it as a `shot`,
copies the resulting public link to the clipboard.
- `scrot-onboard` — prints (and, with `qrencode` installed, renders as a
terminal QR code) the link that onboards a phone onto the PWA below.
Each needs `SCROT_SERVER` and `DEVICE_TOKEN` in the environment — source
them from `~/.config/scrot/env` (gitignored, not tracked here). Wayland
(`wl-paste`/`wl-copy`/`grim`+`slurp`) and X11 (`xclip`/`maim`) are both
supported, auto-detected via `$WAYLAND_DISPLAY`.
## Mobile / PWA
The server also serves a small installable web app (`server/public/`) —
paste-or-share text as a `clip`, upload/share an image as a `shot`, and pull
the latest clip back down. No separate mobile client.
Onboarding a phone onto the shared `DEVICE_TOKEN`: run `scrot-onboard` and
open the printed link (or scan the QR) on the phone. That saves the token
into the page's `localStorage` and mirrors it into a cookie. Add the app to
the home screen and reopen it once — that re-fetches `/manifest.webmanifest`
with the token now baked into its `share_target.action` URL (see
[server/src/manifest.ts](./server/src/manifest.ts)), which is what makes
"Share to scrot" show up in the OS share sheet for photos and selected text.
No service worker involved: the share sheet POSTs straight to `/share`
([server/src/share.ts](./server/src/share.ts)), which checks the token in
the query string (custom headers aren't available to a share-target POST)
and inserts the blob through the same path as `POST /api/blobs`.
## Status
Scaffolded: server (routes, auth, TTL cleanup, SQLite, PWA share target) and
CLI scripts written, not yet run against a real deployment or wired into
`keep`. Next: `npm install` + smoke test locally, then a first deploy.
## Deploy
Mirrors the rest of the project family — `Dockerfile` + `docker-compose.yml`,
named volume for `data/`, env-driven config. Not yet migrated onto `keep`
for secret delivery (tracked in goonk's `FUTURE.md` ops migration list
alongside every other project still on hand-copied `.env`).