Lector
Lector is an experimental graphical browser for terminals. It renders browser frames as pixels and sends them to terminals through image protocols, with Sixel as the first backend.
The project goal is a terminal-native browser that works without a GUI window and still supports mouse clicks, scrolling, text input, dragging, tabs, and real web-page rendering.
Status
Lector is early software. The core terminal shell is usable, and the repository contains an in-process Servo experiment for real page rendering.
Current highlights:
- fullscreen alternate-screen terminal UI
- Sixel frame output
- tmux-aware Sixel passthrough handling
- mouse click, drag, wheel, and keyboard event plumbing
- tab bar and address bar
Ctrl-Nnew tab,Ctrl-Wclose tab,Escquit- ServoShell bridge backend
- native Servo backend when building from this repository with vendored Servo
The crates.io package is the lightweight core package. Native Servo embedding is available from the source tree because it depends on a vendored Servo checkout.
Install
Run the packaged build:
Servo is the default backend. In the crates.io package this means the ServoShell bridge, which expects a ServoShell binary:
LECTOR_SERVO_SHELL=/path/to/servoshell
Native Servo
To use the native in-process Servo backend, build from this repository instead of the crates.io package:
The native adapter lives in crates/lector-servo-native and uses Servo's
software rendering context to capture RGBA frames for the Sixel pipeline.
Controls
Esc: quit, or leave address-bar focusCtrl-C: quitCtrl-N: new tabCtrl-W: close current tabEnter: navigate when the address bar is focused- arrow keys / PageUp / PageDown: scroll and key navigation
- mouse wheel: scroll
- left click: click page controls or switch tabs
- drag: send pointer drag events to the page
tmux
Lector wraps Sixel output for tmux passthrough and temporarily hides the tmux status line while running. For best results, enable passthrough in tmux:
set -g allow-passthrough on
Then reload tmux:
If the image still does not appear, verify that the outer terminal itself supports Sixel. Lector also reads tmux client cell-size metadata to size the rendered framebuffer.
Terminal Sizing
Inspect detected terminal geometry:
Override cell size when the terminal does not report usable pixel dimensions:
LECTOR_CELL_WIDTH=10 LECTOR_CELL_HEIGHT=20
Backends
servo-native: default when built from source with--features servo-nativeservo: default in the crates.io package; ServoShell bridge using an externalservoshellhtml: lightweight built-in renderer for basic terminal/protocol testingdemo: synthetic graphical page for layout and Sixel debugging
Architecture
src/
app.rs event loop, tabs, address bar, frame scheduling
cli.rs command-line parsing
event.rs keyboard and mouse event model
terminal.rs raw mode, terminal queries, tmux lifecycle
engine/
mod.rs browser engine trait and event types
html.rs lightweight built-in renderer
demo.rs synthetic layout renderer
servo.rs ServoShell bridge
servo_native.rs feature-gated native Servo adapter
graphics/
frame.rs RGBA frame buffer
sixel.rs Sixel encoder and tmux wrapper
The engine contract is intentionally small: an engine receives viewport/input events and returns an RGBA frame. The terminal layer owns protocol output, chrome, input, and lifecycle cleanup.