Guide

Everything scrn does, in the order you'll meet it.

Install

curl -fsSL https://raw.githubusercontent.com/w0zro/scrn/main/install.sh | sh

The script fetches the release built for this machine, verifies it against the release's checksums.txt, and puts the binary in ~/.local/bin. Two variables change its mind:

SCRN_INSTALL_DIRinstall somewhere else
SCRN_VERSIONa release other than the latest

Building from source works too, with Go 1.22 or later:

go install github.com/w0zro/scrn@latest

First run

scrn

There is nothing else to set up. The first window starts the daemon — the same binary — and later windows attach to it. By default scrn looks for repositories under ~/projects; point it elsewhere in the config.

The list opens showing what is running, so on a quiet machine it may say nothing running. Two keys from there:

The left column is a tree, at most four levels deep: grouprepositorysub-projectprocess.

Repositories

Every git repository under your project roots. The scan skips node_modules, vendor, target, .build, Pods, .venv and venv, plus anything you add to skipDirs.

Groups

A folder inside a root that holds two or more repositories groups them — the common shape of a project that spans sibling repos. The group is a place of its own: s opens a shell at the folder, r runs the folder's plan, x covers everything beneath it.

Sub-projects

In a monorepo, a directory with a manifest is a project of its own and gets a row under its repository. The manifests, in the order they are trusted: .scrn, Procfile, package.json, deno.json, composer.json, go.mod, Cargo.toml, Gemfile, mix.exs, pyproject.toml, pom.xml, build.gradle. They are found through git ls-files — no tree walk, ignores respected, untracked files included.

Processes

Each place lists the processes running in it, attributed to the innermost place they belong to, and named by what you would call them — npm run dev, not node. A few keys shape the list:

spacefold or unfold the selected node; a folded node shows +n for what it hides
-fold or unfold everything; unfolded rows also show pids
.toggle between everything and only what's running

Dim rows are processes that exist but were started outside scrn, on some other terminal. They are listed and killable, but there is nothing to step into.

Shells

s opens a shell at the selected place. enter on a shell's row steps into it: keystrokes go to the shell, and ctrlo is the one key scrn keeps for itself, to step back out.

Shells live in the daemon, so they survive the window — close the terminal, reboot the terminal app, come back and everything is where it was. The pane is a real emulator: the alternate screen, mouse reporting, window title and progress all pass through, so full-screen programs behave.

Scroll up (wheel or k after entering scrollback) to read what has scrolled away; j k move, esc returns to live. Each shell keeps 10,000 lines of transcript by default — scrollback in the config raises it.

When several windows watch the same shell, it is sized for the smallest of them, so no window sees a torn screen.

Agents

a starts Claude Code in the selected place, in a shell like any other. scrn reads the session files Claude leaves behind, so the navigator can say more than "claude":

That mark is what tells you, from across the list, which projects need your attention — the most of all, since answering it resumes work already underway. The detail pane for a Claude row names what a blocked instance is waiting on, and shows the tail of its transcript.

Plans

Working on a project usually means the same processes every time: the dev server, the test watcher, an agent. A project writes them down in .scrn — Procfile format, a name and a command per line:

.scrn

dev:   npm run dev
api:   go run ./cmd/api
agent: claude

Without one, scrn reads the conventions in the order they are trustworthy: a Procfile means every line is a process; a package.json means only that its dev or start script probably is, so exactly one of those is taken.

r starts the plan's entries that aren't running, each in its own shell named for its entry. It is a list to run, not a supervisor: nothing restarts on its own, and a dead server shows as dead until you start it again.

Killing

xkill the selected process
Xkill it and everything under it
x on a repository or groupkill everything running in it

Every kill asks first — x, y or enter confirms, anything else cancels. Processes get SIGTERM, and a signalled row wears a red marker until a rescan actually observes the exit; the list never claims an exit it hasn't seen. Kills work on any listed process, including ones scrn didn't start.

Configuration

One JSON file, entirely optional. It lives at ~/.config/scrn/config.json (XDG_CONFIG_HOME is honored).

~/.config/scrn/config.json

{
  "projectsDirs": ["~/projects", "~/work/mono"],
  "scrollback": 50000,
  "navWidth": 34,
  "skipDirs": ["bazel-out", "dist"]
}
FieldDefault
projectsDir$HOME/projectsthe directory searched for repositories; ~ and $VARS expand
projectsDirsseveral roots; when set, it is the whole answer and projectsDir is ignored. A root that only exists on your other machine is fine
scrollback10000transcript lines each shell keeps. Read by the daemon at start, so raising it takes R to reach running shells
navWidth28the navigator column's width, 16–60
skipDirsdirectory names the project scan never enters, on top of the built-in list

The daemon

The daemon is the same scrn binary, started by the first window that finds none listening. It owns the ptys, holds the transcripts, and serves every window over a unix socket at ~/.local/state/scrn/scrnd-<uid>.sock (SCRN_SOCKET overrides). One daemon per user, for all projects.

It never outstays its purpose: holding no shells and watched by no window for a minute, it exits. A window that loses its daemon says so and reconnects when one is back.

Upgrading

Install the new binary (the install script again, or go install), then press R in any window. The running daemon replaces itself with the binary on disk by exec — same process, new code — and every shell carries across: pids, ptys, transcripts, screen state. The programs in them never notice.

Linux

Linux builds are published for arm64 and amd64, cross-compiled and so far untested — reports welcome. scrn reads the process list through lsof, so it must be installed:

apt install lsof   # or dnf, pacman, apk…