Skip to content
chromedpPublic

About

A chromedp terminal graphics casting package.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

chromedp logo

About termcast

termcast is a small Go package that streams the screen of a chromedp page to a terminal that has graphics. It uses the screencast of the Chrome DevTools Protocol to get the frames, and rasterm to draw them. It works in Kitty, iTerm2 and Sixel terminals. You start it with one call.

Unit Tests Go Reference Releases Discord Discussion

Install

The module needs Go 1.25 or later. It requires chromedp v0.20.0 and cdproto v0.157.8.

go get github.com/chromedp/termcast

Usage

Load the page first, so that the stream has a page to show. Start also starts the browser when the context has none. Then call Flags.Start or Start with the context. The stream stops when you call Stop, and when the context ends.

package main

import (
	"context"
	"flag"
	"log"
	"time"

	"github.com/chromedp/chromedp"
	"github.com/chromedp/termcast"
)

func main() {
	var tc termcast.Flags
	tc.Register(flag.CommandLine)
	verbose := flag.Bool("v", false, "print the protocol messages")
	flag.Parse()

	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	// Load the page. This call starts the browser.
	if err := chromedp.Do(ctx, chromedp.Navigate("https://example.com")); err != nil {
		log.Fatal(err)
	}

	// s is nil when the flag -visible-on-terminal is off. A nil stream is
	// safe to use.
	s, err := tc.Start(ctx, *verbose)
	if err != nil {
		log.Fatal(err)
	}
	log.SetOutput(s.LogWriter())
	defer s.Stop()

	log.Println("the page is on the screen")
	if err := chromedp.Do(ctx, chromedp.Sleep(10*time.Second)); err != nil {
		s.Fatal(err)
	}
}

Run it with the flag:

go run . -visible-on-terminal

To start the stream with no flag, call termcast.Start(ctx, opts...).

How it works

The browser sends a frame only when the page changes. The stream keeps the latest frame. At each tick it clears the terminal and draws the latest frame, but only when the frame is new. A page that stops changing stays on the screen. A program can end before the browser sends the first frame. In that case Stop takes one screenshot, so that the final frame is never empty.

The stream clears the screen with \x1b[H\x1b[2J at each redraw. It uses no alternate screen and does not hide the cursor. A program that ends with log.Fatal skips its deferred calls, and the terminal must not stay in a changed state. See the decision.

Options

Option Default Meaning
WithFPS(fps) 4 The most frames per second that the stream draws
WithQuality(q) 80 The JPEG quality of the frames, from 0 to 100
WithMaxSize(w, h) 1024 by 768 The largest size of a frame in pixels
WithOutput(w) os.Stdout The writer that receives the frames
WithLogOutput(w) os.Stderr The writer that receives the held log lines
WithElement(sel) the whole page Draws only the element that the selector finds
WithEncoder(e) Kitty, iTerm2 or Sixel The rasterm.Encoder that draws a frame

Flags registers two flags: -visible-on-terminal, which turns the stream on, and -terminal-fps, which sets the frame rate and defaults to 4.

Programs that use it

The chromedp/examples repository has 34 programs that use termcast. Most of them take the flags -visible-on-terminal and -terminal-fps with Flags. The program termcast calls Start directly. It plays an animated SVG and streams it to the terminal. These programs use the package: click, console, cookie, dialogs, download_file, download_image, dragdrop, emulate, eval, eventsiter, exposefunc, extension, fast, forecast, frames, geoip, headers, intercept, keys, latlon, logic, pdf, pdfoptions, proxy, remote, screenshot, selectors, structeval, submit, subtree, termcast, text, upload and visible.

Show one element

WithElement takes a chromedp selector, such as chromedp.CSS("#chart"), and draws only the first element that it matches.

s, err := termcast.Start(ctx, termcast.WithElement(chromedp.CSS("#chart")))

The stream looks up the element again at each frame, so an element that moves or changes its size stays in view. It crops the frame to the border box of the element. The browser sends the viewport, so the stream shows the part of the element that is in the viewport. Use chromedp.ScrollIntoView first when the element is lower on the page. While the page has no such element, the stream keeps what is on the screen.

Terminals that work

The terminal must support one of these graphics protocols:

  • Kitty and Ghostty
  • iTerm2, WezTerm and mintty
  • Sixel

rasterm detects the protocol from the environment (TERM, TERM_PROGRAM, LC_TERMINAL and the variables of Kitty) and, for Sixel, with a query to the terminal. The variable TERM_GRAPHICS forces the protocol to kitty, iterm or sixel, and the value none turns graphics off. Start returns ErrNoGraphics when no protocol is available. Available reports the same thing before you start.

Log lines

A log line that the program prints draws over the frames, and the next redraw erases it. Stream.LogWriter returns a writer that holds the lines while the stream runs. When the stream stops, it draws a final frame and then prints the lines to the log output. Use log.SetOutput(s.LogWriter()). After Stop, the writer passes each line on at once.

Stream.Fatal stops the stream, prints the held lines, and then calls log.Fatal. Use it where a program calls log.Fatal, because log.Fatal ends the program before a deferred Stop runs.

Every method of *Stream is safe on a nil pointer. On a nil stream, Stop does nothing, Fatal calls log.Fatal and LogWriter returns os.Stderr.

The flag -v

The flag -v of a program prints the protocol messages. They draw over the frames, so the two do not work together. Flags.Start returns ErrVerbose when both are on.

Tests

The tests start Chrome and need no terminal. They use a fake encoder and a local page that animates. See AGENTS.md for the commands.

GOWORK=off go test -race ./...

Contributing

See CONTRIBUTING.md. Ask questions in the GitHub Discussions of chromedp, and report bugs in the issues of chromedp. The documents of this repository are AGENTS.md, CLAUDE.md, CONTRIBUTING.md and docs/decisions/README.md.

About

A chromedp terminal graphics casting package.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages