v0.1.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DevDesk
A persistent browser terminal for Claude Code, at https://dev.lotusguild.org.
- Persistent sessions: closing the tab, restarting the web service or upgrading the package never stops Claude.
- Survives reboots: after a reboot, every named session resumes its own conversation.
- Styling: uses the LotusGuild Terminal Design System (web_template).
- Packaging: ships as a
.debfrom Gitea's apt registry.
Browser ─https─▶ NPM (wildcard cert, Authelia two_factor, injects ttyd credential)
─http─▶ ttyd :7681 [devdesk.service] ── /ws?arg=<name> → `devdesk attach <name>` (tmux client)
tmux server [devdesk-tmux.service] ── one session per project:
window "claude": devdesk-claude-run → claude --resume <recorded id>
window "shell"
Why two units
The tmux server runs in its own unit, so every Claude process lives in that unit's cgroup.
- ttyd (
devdesk.service) only starts tmux clients (tmux -Nnever starts a server). It can restart freely, and does so on package upgrades. devdesk-tmux.serviceis installed with--no-stop-on-upgrade, so apt never touches it.- Only
systemctl stop devdesk-tmux(or removing the package) ends the sessions.
Sessions
- How the session is chosen:
https://dev.lotusguild.org/?arg=<name>opens session<name>and creates it on demand in$DEVDESK_PROJECTS_ROOT/<name>.mainuses the root itself, and folders with spaces are reached by slug (test code→test-code).- With no
?arg=, an fzf picker opens, listing running (●), dormant (○) and new (+) sessions.
- Windows: each session has a
claudewindow (0) and ashellwindow (1). - Conversation tracking: a Claude
SessionStarthook records each session's conversation ID in/var/lib/devdesk/registry.json. After a reboot the session resumes that conversation, even when other Claude instances, such as code-server, use the same directory. - SSH:
devdesk attach <name>,devdesk ls,devdesk pick,devdesk end <name>.
Keys
| Key | Action |
|---|---|
| Shift+Enter | Newline in Claude's prompt (sends Ctrl+J) |
| Esc | Interrupt Claude |
| Ctrl-b 0 / 1 | Claude window / shell window |
| Ctrl-b s | Switch session (the URL follows) |
| Ctrl-b d | Detach (the session keeps running) |
| Shift+drag | Native browser selection (plain drag goes to tmux copy-mode, which copies via OSC 52) |
| Ctrl+Shift+C / V | Copy selection / paste |
Use the Full button for fullscreen. In Chromium it also captures Ctrl+W/Ctrl+T, which browsers otherwise keep for themselves.
Configuration
/etc/devdesk/env(conffile):- port, bind address and projects root
CLAUDE_BINandCLAUDE_ARGSDEVDESK_REMOTE_CONTROL=1, which also starts each session with Claude Remote Control so it can be continued from the Claude app
/etc/devdesk/secret.envis generated on install. It holds the ttyd credential that NPM must inject; see docs/DEPLOY.md./etc/devdesk/tmux.local.confis optional and is sourced after the packagedtmux.conf.
Build
Needs Node ≥ 18, debhelper, bats, tmux, jq, shellcheck:
make # dist/index.html (single inlined page) + build/ttyd (pinned, sha256-verified)
make lint test
dpkg-buildpackage -us -uc -b && lintian ../devdesk_*_amd64.deb
apt install ../devdesk_*_amd64.deb
CI (.gitea/workflows/build-deb.yml):
- Every push lints, tests, builds and smoke-tests the package and uploads it as an artifact.
- A
v*tag also publishes tohttps://code.lotusguild.org/api/packages/LotusGuild/debianand creates a release.
Roadmap
- v1.1:
devdesk-apisidecar for the Repo/CI and Claude Context panels, Matrix notifications when you're away, and auto-deploy. - v2: Ops Alerts (Grafana) with "Ask Claude" prompts, and file drop.
Releases
28
devdesk v0.12.0
Latest
Languages
JavaScript
52.9%
Shell
35%
CSS
9.2%
HTML
2.4%
Makefile
0.5%