rootle — browse remote source-control systems from your terminal
status: alpha — features, keys, and config may still shift between releases; pin a version if it matters to you.
A modal TUI (ratatui) with a yazi-style miller-column browser, syntax-highlighted previews, Zed-style global search, and a pluggable provider seam — GitHub ships in-tree, anything else wraps in via a small stdio script.

Contents
What it does
- Browse orgs → repos → trees → files in three miller columns with a live syntax-highlighted preview — no clone required.
- Revise —
␣ bswitches branches/tags (rootle owner/repo@reffrom the CLI);␣ p hfile history with open-at-commit;␣ p bblame run-margins; yanks from history anchor to the commit sha. - Inspect commits —
din file history opens the full message and changed files;Enteropens a unified delta,]f/[fstep files, andEscunwinds. Binary, unavailable and truncated patches are identified explicitly. Read-only; no staging or committing. - Search — find (
␣ f) and grep (␣ g) with a real grammar ("quoted",-negation,language:rust), results streaming into decorated per-file boxes with facet chips;Enteropens the whole file at the match line. - The pane —
␣ pfocuses and zooms the preview with vim's vertical motions (3j,gg/G,^D/^U,{/},%,zt,:42). - Open any file read-only in your editor (
Enter); yank the browser URL of anything (␣ y). - Clone repos through a wizard (
vmarks,:clone) — orgs fan out, archived grey out, sorted by last push. - Configure in-app with
:settings(writes config.toml, hot reloads themes and chrome); every keybinding is in the?popup. - Update — the modeline chips
↑ vX.Y.Zwhen a release is newer (24h-cached, silent offline);rootle updateself-updates tarball installs with checksum verification.CHANGELOG.mdrides every release.
Quick start
|
Auth is zero-friction: if gh auth login or ROOTLE_TOKEN is already
set up, rootle just uses it; anonymous works everywhere except code
search (it says so in the status line when it matters).
Documentation
| Doc | Contents |
|---|---|
| settings | every config key, env var, CLI flag |
| themes | writing your own palette (role reference) |
| provider protocol | wrap your own backend (NDJSON-RPC over stdio) |
| development | architecture, dev workflow, e2e harness |
| house style | the component behavior contract |
| provider scaffolding | public skill: scaffold a provider |
Providers
rootle talks to backends through a small protocol, not to GitHub directly.
[provider] kind = "github" is the default in-tree implementation;
kind = "stdio" spawns your adapter as a child process — four methods
make a minimal useful provider, and the canonical
forge-conformance
suite gates correctness (rootle's own CI runs it against the fs
reference provider). GitLab and Bitbucket ship as managed one-binary
adapters; the roadmap for what's next lives on
rootle.dev/docs/roadmap.html.
The built-in manager installs stdio providers as verified binaries:
rootle provider install gitlab # bare name → rootledev/rootle-gitlab
rootle provider install owner/repo@v0.1.0 # GitHub releases, tag-pinned
rootle provider install https://artifacts.corp.example/p/rootle-gitlab-0.1.0-x86_64-unknown-linux-musl.tar.gz
rootle provider install myprovider --path /opt/providers/rootle-myprovider
Every networked install is checksum-verified against the mandatory
.sha256 sidecar, whatever the host. Sources split into two
deployment shapes: releases-API sources (github.com slugs/URLs)
are tracked — rootle provider update refreshes their latest-known
tags and upgrade swaps binaries. Plain-HTTP and --path
installs are install-and-pin — update/upgrade never touch them;
upgrades come from whatever deployed them (a config manager, an
artifact-publishing pipeline). --path is a first-class deployment
shape, not a testing convenience: it is the steady state for
config-managed installs.
Development
cargo test --workspace # unit + TestBackend render tests
rootle --headless script.txt # scripted driver: keys in, frames + state JSON out
cd e2e && uv run pytest # headless + PTY end-to-end suites
docker compose run --build --rm test # fmt + clippy -D warnings + cargo test
docker compose run --build --rm e2e # same e2e suite in a container
docker compose run --build --rm model # bounded TLA+ properties + four kept faults
--headless (plans/0023) drives the real app without a terminal —
keys/settle/frame/state script steps in, plain-text cell grids
and state JSON out — the deterministic surface for tests, reviews, and
agent-driven stress runs. See crates/rootle/src/headless.rs's module docs for the
script language.
CI runs the Rust, e2e, provider-conformance and protocol-model gates.
The demo workflow re-renders all palettes when the app or its tooling
changes and publishes the GIFs to the site repository.