GitHub - PeterKnego/roost: Remote dev workspace for Claude Code and other coding agents in your browser: persistent terminals, live diffs. Single Rust binary, no Node.

GitHub

6 min read Original article ↗

roost

Run your long-running coding sessions on a server. Watch them through your browser.

This project started because I was scratching my itch: I wanted a simple remote terminal that survives any interruption, preferably runs through browser, and has a few must-haves: file tree, file upload, diff window, editor and preview. I managed to get by with mosh/tmux/md-tui, but that setup just did not understand projects and worktrees. So I created a lightweight Rust tool that gives any coding project its own browser tab and all needed info in one place. Backed by dtach shells that survive tab close, laptop sleep, network down and even restart of roost itself.

CI Release crates.io License Rust

roost workspace: file tree and git changes on the left, an editor in the middle, and Claude Code in a terminal on the right reviewing an uncommitted edit

Why

Because you want a simpler way to have remote access to your server box. Roost is a 4MB Rust binary that gives every one of your projects or worktrees a tab in a browser.

roost ttyd / Wetty code-server tmux + ssh
Terminals survive restart ✅ ❌ n/a ✅
Editor + diffs + tree ✅ ❌ ✅ ❌
Mirrors across browsers ✅ ❌ ❌ ✅
Claude Code IDE protocol ✅ ❌ ❌ ❌
Paste a screenshot to the agent ✅ ❌ ❌ ❌
Single binary, no Node ✅ ✅ ❌ ✅
Auto-reconnects after the laptop sleeps ✅ ❌ ✅ ❌
Needed on the laptop browser browser browser ssh client + terminal
Drag-and-drop files to upload ✅ ❌ ✅ ❌
Multiple git worktrees, switchable ✅ ❌ ❌ ❌
Server binary 4 MB 0.7 MB 235 MB download 1.3 MB
Server memory 16 MB (7 shells) 9 MB (1 shell) 770 MB (1 workspace) 3 MB (1 shell)

Install

Install roost on the box your code lives on — the remote dev machine, not your laptop. Your laptop only ever needs a browser.

# Homebrew — installs dtach for you
brew install peterknego/tap/roost

# or Linux packages — these install dtach for you and ship a systemd user unit.
# Grab the .deb or .rpm for your architecture from the releases page first:
sudo apt install ./roost_*.deb          # Debian, Ubuntu
sudo dnf install ./roost-*.rpm          # Fedora, RHEL
systemctl --user enable --now roost     # packages only; starts roost

# or with cargo — dtach and git must already be on PATH
apt install dtach           # or: brew install dtach
cargo install roost
# or, to build unreleased work off `develop` rather than a release — the
# channels above install a tagged version, this one does not:
cargo install --git https://github.com/PeterKnego/roost

ROOST_ROOTS="$HOME/Projects" roost 8444
# or just: roost 8444 — then add your projects directory on the front page
# open http://127.0.0.1:8444/

Prebuilt binaries for Linux (x86_64 and aarch64, statically linked — no glibc version to match) and macOS (Intel and Apple Silicon) are on the releases page, with checksums and build attestations. cargo binstall roost fetches them directly.

macOS is used daily; Windows is untested.

On macOS, a tarball downloaded in a browser hangs rather than failing. Safari and Chrome set com.apple.quarantine on the download, tar copies it onto the extracted binary, and Gatekeeper then waits on a GUI prompt nobody sees over ssh: no output, no error, no exit status, indistinguishable from a server that started. Strip it before the first run — doing it afterwards does not clear a prompt already pending:

tar xf roost-aarch64-apple-darwin.tar.xz
xattr -d com.apple.quarantine roost-aarch64-apple-darwin/roost
./roost-aarch64-apple-darwin/roost --version     # roost 0.5.2

brew install and curl are both unaffected — Homebrew strips the attribute and curl never sets it, and the binary is byte-identical in all three cases. Measured on macOS 26.6.2 (Apple Silicon) on 2026-09-12: the release binaries are ad-hoc/linker-signed and not notarized, so spctl reports rejected even for the Homebrew copy that runs — the quarantine attribute is the gate, not the signature.

roost has no authentication of its own. It only binds to 127.0.0.1. Put an auth layer in front of it — tailscale serve is what I use. Read Security model before exposing it.

Features

A tab per project/worktree

Every tab represents a project or worktree, and has panes in familiar IDE-like arrangement: file-tree, file-diffs, file preview/editor, terminal.

Terminals that survive reload/re-attach/restart

Each terminal is a PTY owned by roost and wrapped in dtach, so sessions survive a tab reload, network disconnect, laptop sleep, and even a roost restart.

All state lives on the server and mirrors live

Open a file in one browser and it opens in every connected browser. Layout and unsaved buffers persist across restarts, stored outside the repo — so pane drags never show up in git status.

Drag-n-drop files/images or paste images

Drag-n-drop files into the file tree for instant upload to remote filesystem. As for images, you can drag them or paste them into claude terminal and they will be uploaded and pasted directly into claude as image - this is a must-have feature when you just want to quickly paste a screenshot into claude for analysis.

Claude Code integrates with the project

A claude running in a terminal pane connects back to roost via the IDE protocol, the same as VS Code or JetBrains IDEs. This gives it unique integration abilities: paste image, links to @file, "live" links in the terminal that open when you click them and claude initiated file diff viewer (if in manual permission mode).

A proposal tab showing the two lines Claude wants to delete, with Accept, Reject and Edit buttons, beside the terminal where Claude is asking for the same approval

Desktop notifications

Roost supports sending desktop notifications from any terminal. Clicking a notification will take you directly to that terminal. Also, Roost can install hooks into claude to enable a notification every time claude needs attention. See docs/notifications.md.

Security model

roost only binds to 127.0.0.1 and is meant to be fronted by an auth layer, such as tailscale. More about it in SECURITY.md

Contributing

See CONTRIBUTING.md for the branch flow and how to run the test suite, and CODE_OF_CONDUCT.md for the project's conduct expectations.

License

Dual-licensed under either of

at your option — the Rust ecosystem's usual MIT OR Apache-2.0, and what Cargo.toml declares. Note that GitHub's sidebar reports "Apache License 2.0" alone: its detector picks a single LICENSE-* file and drops the other. serde, regex, clap and cargo itself all read the same way. Cargo.toml and this section are authoritative; the sidebar is not.