DEV Community

Mr Punk da Silva
Mr Punk da Silva

Posted on

Carbonyl: Forking Chromium to Render Live in a Terminal

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

  1. HTML → Skia bitmap

     Chromium’s renderer draws pages into an offscreen SkBitmap. Carbonyl intercepts this via a custom HostDisplayClient and shared memory mapping between GPU, renderer, and browser processes.

  2. 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!("▄");
   }
Enter fullscreen mode Exit fullscreen mode
  1. 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");
}
Enter fullscreen mode Exit fullscreen mode

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)