rootle 0.12.0

Modal TUI for browsing remote source-control systems from the terminal
Documentation

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.

ci release audit crates.io version status website

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.

demo

Contents

What it does

  • Browse orgs → repos → trees → files in three miller columns with a live Tree-sitter syntax-highlighted preview — no clone required.
  • Revise — ␣ b switches branches/tags (rootle owner/repo@ref from the CLI); ␣ p h file history with open-at-commit; ␣ p b blame run-margins; yanks from history anchor to the commit sha.
  • Inspect commits — ␣ h opens repository history; Enter inspects a commit. File history (␣ p h) still supports open-at-commit and d for detail. Changed files stay beside the syntax-highlighted diff; Tab switches files/preview, ]f/[f step filtered files, and Esc unwinds. Binary, unavailable and truncated patches remain explicit. 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; Enter opens the whole file at the match line. Fresh profiles start here with an empty browser, not seeded repositories. Modal input prompts show ❯ in INSERT and ● in NORMAL.
  • The pane — ␣ p focuses 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 (v marks, :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.Z when a release is newer (24h-cached, silent offline); rootle update self-updates tarball installs with checksum verification. CHANGELOG.md rides every release.

Quick start

curl -fsSL https://rootle.dev/install.sh | sh   # linux x86_64, to ~/.local/bin
brew install rootledev/tap/rootle   # linux (builds from source)
brew install --cask rootledev/tap/rootle   # macOS (prebuilt binary)
cargo install rootle                # or from crates.io (Rust 1.88+)

rootle                # repo search on first run; browser after that
rootle owner/repo     # jump straight into a repo
rootle owner/repo@release/2.7   # …at a branch, tag, or sha
rootle update         # self-update (tarball installs), or your channel's hint

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. Use settle [ms] before sampling after navigation; it waits for outstanding workers and their follow-ups, failing the run on timeout (default 10000ms). rootle --help documents every directive; see crates/rootle/src/headless.rs for the driver.

Development builds support opt-in session diagnostics: rootle --log selects a new private log under the XDG state directory; --log-file issue.jsonl selects a new file. Add --log-content only when you need sensitive typed text, visible cells and provider stderr. The same flags work with --headless; see the diagnostic workflow before sharing logs.

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.