A new project called Carbonyl takes a fresh stab at text-based browsing by forking Chromium and re-routing its rendering pipeline into a terminal emulator. Rather than outputting pixels to a window, Carbonyl maps every web page onto Unicode block characters and ANSI color escapes—complete with interactive text capture and input support.
📰 Coverage on CyNews: https://cynews.vercel.app/show/45133935
📎 Project page & write-up: https://fathy.fr/carbonyl
Background
Most terminal-based browsers rely on parsing HTML and re-implementing layout (e.g. w3m, lynx). Carbonyl instead leverages the real Chromium engine:
- It hooks Skia’s bitmap and text-drawing devices to capture rendered output.
- It preserves the exact layout, CSS, JavaScript engine and extensions you’d see in Chrome.
- It translates that output into terminal control sequences on the fly.
The result is a “true” Chrome experience—minus the GUI.
Rendering Pipeline
HTML → Skia bitmap
Chromium’s renderer draws pages into an offscreen SkBitmap. Carbonyl intercepts this via a customHostDisplayClient
and shared memory mapping between GPU, renderer, and browser processes.Bitmap → Terminal blocks
Each terminal cell uses U+2584 (lower half block) with 24-bit ANSI colors. Carbonyl sets the cell’s background to the top pixel and foreground to the bottom. It batches calls for minimal cursor movement:
fn print_pixels_pair(top: RGB, bottom: RGB, cursor: (x, y)) {
move_cursor(cursor);
set_background(top);
set_foreground(bottom);
println!("▄");
}
-
Text capture
A
TextCaptureDevice
, inserted into Skia’s pipeline, intercepts glyph runs. It converts glyph IDs to Unicode and issues ANSI code to render characters instead of bitmap blocks—preserving crisp text and selectable content.
Input & Interaction
Carbonyl listens for mouse and keyboard via ANSI Device Control Sequences (DCS). For example:
fn report_mouse_down((x, y): (usize, usize)) {
write!(stdin, "\x1b[<0;{y};{x}M");
}
These sequences feed events back into Chromium’s input system on the main thread via BrowserMainThread::PostTask
, enabling clicks, scrolling, and text input—just like in a GUI browser.
Performance & Tuning
Out of the box, Carbonyl renders at about 5 FPS with ~400 % CPU usage on a modern laptop. Two key optimizations were introduced:
- LoDPI scaling: For terminal output, the display scale is forced to 1/7, reducing the pixel grid by a factor of 49.
-
Threaded compositing hacks: Disabling
--disable-threaded-scrolling
and--disable-threaded-animation
keeps rendering on the main thread, avoiding expensive cross-thread coordination.
With these tweaks, idle CPU usage drops to near zero, and scrolling stabilizes around 15 %.
Community Feedback
On the CyNews discussion, developers highlighted:
- Novelty: “Finally, a real Chromium-powered terminal browser.”
- Performance concerns: CPU overhead makes it impractical for daily use today.
- Potential use cases: Remote servers, CI log previews, low-bandwidth environments, or ultra-portable dev setups.
- Feature requests: True-color detection, configurable block resolution, SSH-friendly input modes.
Why Carbonyl Matters
Carbonyl demonstrates how far browser engines can be repurposed when paired with terminal graphics tricks. It:
- Preserves exact web compatibility (JS, CSS, extensions).
- Maintains selectable text for copy/paste or accessibility readers.
- Opens a path for GUI-less demos, remote interaction, and embedded deployments in constrained environments.
For anyone curious about browser internals, terminal graphics or building bridges between GUIs and CLIs, Carbonyl is a compelling, hands-on case study.
🔗 Project write-up & demo: https://fathy.fr/carbonyl
📰 Read the CyNews article: https://cynews.vercel.app/show/45133935
Let me know if you try it—what pages render best, or how it fits into your remote workflows!
Top comments (0)