Skip to content

Commit bc26f85

Browse files
authored
docs: surface the user-visible reliability backlog in the roadmap (#25)
## Summary Course correction on PR #24. I was too strict on "user-facing only" — a bunch of the Round-M items I'd parked in private memory are actually user-visible bugs (uploads hang, screenshot bursts dropped, slow upload misses next poll, typo'd commands silently run setup, fatal errors exit 0). Those belong in the public roadmap. This PR: 1. Splits \`## Roadmap\` into two subsections — **Reliability fixes** and **Features and ergonomics** — so the list stays scannable. 2. Pulls 11 user-visible bug-class items out of memory into the Reliability subsection. 3. Leaves purely-internal items (commitlint config doc, semantic-release idempotency wiring, package.json metadata cleanup, CI smoke checks, monitor.ts split, tsconfig test/ inclusion) in memory — those are housekeeping, not user direction. ## Items added under **Reliability fixes** - SSH upload \`BatchMode=yes\` + timeout + EPIPE handler - \`sshshot stop\` honors the 5 s graceful-shutdown window - Decouple poll loop from upload completion - macOS screenshot burst handling (oldest-first) - \`sshshot config\` preserves \`activeTarget\` + \`paused\` - Typo'd CLI commands print error + exit 1 - Fatal CLI errors set non-zero exit code - \`loadConfig\` shape validation + \`saveConfig\` atomic writes - Cache clipboard-tool availability at startup - \`~/.ssh/config\` parse defensiveness + \`?\` wildcard filter + dedup - \`removePidFile\` only-if-still-ours guard \`docs:\` only, no release fired. ## Test plan - [x] yarn format:check - [ ] CI matrix Node 20/22/24 green (no source changes)
1 parent 1ab2a33 commit bc26f85

1 file changed

Lines changed: 19 additions & 1 deletion

File tree

README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,25 @@ You'd still need a server to receive uploads, and AI agents running over SSH don
176176

177177
## Roadmap
178178

179+
### Reliability fixes
180+
181+
These are user-visible bugs surfaced by audit reviews — none silent, all observable in real workflows.
182+
183+
- [ ] SSH upload uses `BatchMode=yes` + an absolute upload timeout (via AbortController/kill) + a stdin EPIPE handler, so a hung remote doesn't permanently occupy an upload slot
184+
- [ ] `sshshot stop` honors the daemon's 5 s in-flight-upload grace before SIGKILL — currently SIGTERM is sent and the process is killed before the daemon can finish a mid-flight upload
185+
- [ ] Decouple the poll loop from upload completion so a slow SSH upload can't cause the daemon to miss the next clipboard / file screenshot
186+
- [ ] Process all stable macOS screenshots newer than `lastSeenScreenshotMtime` in mtime order — currently a burst of multiple rapid screenshots only uploads the most recent one
187+
- [ ] Editing remotes via `sshshot config` preserves `activeTarget` and `paused` (currently both are silently dropped)
188+
- [ ] Typo'd CLI commands like `sshshot stat` print a clear error and exit 1 — currently they fall through every known-command branch and run first-run setup, which is confusing
189+
- [ ] Fatal CLI errors set a non-zero exit code so scripts and CI detect failures (currently `main().catch(console.error)` exits 0)
190+
- [ ] `loadConfig` runtime-validates the parsed JSON shape (so a hand-edited `{ "remotes": "host" }` doesn't break the daemon); `saveConfig` writes via temp-file + atomic rename so a crash mid-write can't truncate the file
191+
- [ ] Cache clipboard-tool availability at startup — currently a missing `pngpaste`/`xclip`/`wl-paste` is re-spawned every 200 ms poll
192+
- [ ] `~/.ssh/config` parsing handles unreadable files (try/catch on read), dedupes auto-detected aliases, and filters `?` wildcards in addition to `*`
193+
- [ ] `removePidFile` only unlinks when the file's contents still match `process.pid`, so a stop-and-restart race can't delete the new daemon's pid file
194+
- [ ] mtime-vs-daemon-start gate so a Screenshot-named file copied into the watch dir (restored from backup, `cp`'d in, etc.) isn't mistakenly uploaded as a fresh screenshot
195+
196+
### Features and ergonomics
197+
179198
- [ ] **Context-aware clipboard routing** (macOS first) — replace clipboard with the remote path only when the foreground app is a terminal-ish thing (Terminal/iTerm2/Warp/Ghostty/Zed/VS Code/etc.). For Slack/GitHub/iMessage screenshots the image bytes stay on the clipboard. `pause`/`resume` is the short-term workaround.
180199
- [ ] Retry on SSH failure with exponential backoff — currently a failed upload silently drops the screenshot
181200
- [ ] System notification on upload success / failure (`osascript -e 'display notification'` on macOS, `notify-send` on Linux) so the daemon's status is visible without tailing logs
@@ -186,7 +205,6 @@ You'd still need a server to receive uploads, and AI agents running over SSH don
186205
- [ ] `sshshot open` — open the most recent screenshot in the system image viewer
187206
- [ ] Optional `pngquant` / `optipng` compression passthrough before upload — 80–90 % size reduction for similar visual quality, big win on slow links
188207
- [ ] Configurable remote upload directory (currently hardcoded to `~/sshshot-screenshots/`); same for the `local` mode directory
189-
- [ ] mtime-vs-daemon-start gate so a Screenshot-named file copied into the watch dir (restored from backup, `cp`'d in, etc.) isn't mistakenly uploaded as a fresh screenshot
190208
- [ ] Record macOS demo gif (current `demo-windows.gif` is the upstream Windows/PowerShell flow)
191209
- [ ] Record Linux X11 / Wayland demo gif
192210
- [ ] Optional inline image paste (instead of path) for tools that accept multipart pastes — future ergonomic win

0 commit comments

Comments
 (0)