- Ask Claude: strip control characters, send as bracketed paste (closes#2)
- end: forget before kill, so ending from inside a session leaves no ghost (closes#3)
- reconnects use `attach --existing` and never resurrect ended/renamed sessions (closes#4)
- repo: git --no-optional-locks, no safe.directory override, refresh on connect/bell/60s (closes#5)
- uploads: unique names via mktemp, cleanup trap on hangup (closes#6)
- clipboard: write-only OSC 52 provider, tmux allow-passthrough off (closes#7)
- uploads: size check up front, streamed slices, idle timeout (closes#9)
- --list: path last in TSV rows, tolerant numbers (closes#10)
- tokens via curl config on stdin; userinfo stripped from remote URLs (closes#11)
- ttyd max clients 32 and at most 2 concurrent side-channel calls (#8; BroadcastChannel polling still open)
- tmux: fixed terminal-features index (no duplicates on re-source), no status-right clock
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ttyd serves a single-file xterm.js UI styled with the LotusGuild TDS
(web_template base.css). Sessions live in a dedicated tmux server unit
(devdesk-tmux.service), so restarting or upgrading the web unit never
stops Claude. Each named session maps to a project directory. A Claude
SessionStart hook records the conversation ID, so after a reboot the
session resumes that exact conversation.
- bin/devdesk: attach / new / ls / end / pick, with an fzf picker
- ttyd requires a credential that NPM injects; origin check enabled
- debian/: dh 13 with --no-stop-on-upgrade for the tmux unit, bundled
sha256-verified ttyd 1.7.7, lintian overrides, man page
- CI: lint, test, build, smoke-test, artifact; v* tags publish to the
Gitea apt registry and create a release
Refs: tinker ticket 887531976
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>