Skip to content

Running Sashfold

codingncaffeine edited this page Sep 20, 2026 · 16 revisions

Running Sashfold

The window

sashfold                          # the browser window, on about:sashfold
sashfold https://example.org/     # opened on a page

The window is written for Windows (Win32) and Linux (a Wayland client of its own; the section below). Every color, size and timing of its chrome comes from themes/default.json (see Themes); the file is looked for beside the executable, then in its parent directory, and it reloads while the window is open.

Option Meaning
--theme <file.json> Use another theme file
--blocklists <dir> The folder of content-blocking lists (filters/*.txt in Adblock syntax, nefarious/*.txt sites to keep off), read at start; blocklists/ beside the executable or its parent by default. See Security defaults
--downloads <dir> Where downloads are saved (the window defaults to your Downloads folder)
--profile <dir> The profile folder, where the window keeps cookies.txt (and cookies-<name>.txt per container), storage.json, containers.json, session.json, settings.json and the cache/ folder — the cookies, every page's storage, the containers offered, the tabs of the last run, the theme last chosen from the palette and the pages fetched, brought back on the next start (see The shell, Themes and Networking); $XDG_CONFIG_HOME/sashfold (else ~/.config/sashfold) on Linux and macOS, %APPDATA%\Sashfold on Windows by default, made when missing
--trace-frames Every turn of the window's loop that did anything says on stderr what it took in and what it cost, and where (a turn of a quarter of a second or more always does). SASHFOLD_TRACE_FRAMES=1 in the environment is the same. See The shell
--js-heap-limit <MB> The ceiling on one page's script heap (0: none). Unsaid, a quarter of the machine's memory, no less than 512 MB and no more than 4 GB — the rule the engine under Chrome gives a page its heap by. A page whose scripts hold more has them stopped; see The shell
--memory-ceiling <MB> The ceiling on the whole process, which the window's memory watch holds it to (0: no watch). Unsaid, half the machine's memory, no less than 2 GB and no more than 16 GB
--fonts system|builtin Use the machine's fonts, or the built-in face alone (system is the default everywhere except --script)
--add-font <file.ttf> Install a font file for the page as if the machine had it. Repeatable, and applied after --fonts, so --fonts builtin --add-font X.ttf gives the page exactly that face and the built-in one. A file with no outlined face stops the run rather than laying the page out in some other font quietly. This is how a render is taken in the same font a test is scored in

The window on Linux

On Linux the window is a Wayland client spoken directly over the compositor's socket: no toolkit, no libwayland (see The Pledge). The frame is the shell's own, as Firefox's and Chrome's is — minimize, maximize and close at the tab strip's right end, the strip's empty part as the handle that moves the window, and a band along the edges that resizes it, each carried out by the compositor on the press that asked for it — so a theme's frame color and picture reach the top edge of the window; a title bar the compositor draws is one no theme can dress. SASHFOLD_WAYLAND_CSD=0 asks the compositor for its title bar through xdg-decoration instead (KDE Plasma, sway and the wlroots compositors provide one), until the settings page has that switch. It names its cursors through cursor-shape-v1, hands the compositor its icon through xdg-toplevel-icon-v1, reads the keyboard through the xkb keymap the compositor sends (parsed here, virtual modifiers resolved the way libxkbcommon resolves them), and speaks the clipboard through the data device. On a scaled display it draws at the display's scale, fractions included: the compositor names the scale through fractional-scale-v1 and the window renders its buffer at that size behind a viewport of the logical size (a compositor without that protocol is asked for its preferred whole-number scale, or the scale of the output the window is on), so the chrome, the pages and their type are as sharp as the screen; a page's scripts see the factor as devicePixelRatio and every length in CSS px. A touchscreen works through the seat's touch: a tap is a click where the finger landed, and a finger carried across the screen scrolls what was under it by the distance it moved. An input method works through text-input-v3: while a field has focus the method is enabled and told where the caret is, its composing text shows underlined at the caret (in a page's field, the address bar and the find box alike), and what it commits is typed there; the window offers the method no surrounding text, so a method that edits around the caret rather than at it has nothing to edit.

bash tools/install-desktop-linux.sh --desktop installs the launcher, the icon at every size the icon theme names, and a Desktop shortcut for the current user; the window's app id is sashfold, which is how the desktop matches it to the launcher's name and icon.

SASHFOLD_WAYLAND_DEBUG=1 prints what the compositor offered and what was bound, every configure, the keymap's parse and each key and present, and writes the keymap it received to $XDG_RUNTIME_DIR/sashfold-keymap.xkb for a keymap the parser refuses.

Testing the window without a display

--exit-after <ms> closes the window on its own after that many milliseconds, and --timings <file.json> writes what it saw on the way: when the start page was first presented, when nothing was left to load, the cost of every present, and the same shell counters and network account --bench reports. Paired with a headless Wayland compositor this drives the real window, decorations, presents and all, unattended:

weston --backend=headless --socket=sashfold-test --no-config --idle-time=0 &
WAYLAND_DISPLAY=sashfold-test sashfold <url> --profile <dir> --exit-after 6000 --timings out.json

Headless modes

Every mode below runs without a window, on every OS the engine builds on.

--render — a page to a PNG

sashfold --render page.html -o out.png [--width N] [--height N]

Lays the page out (a local file or a live URL, through the same session logic as the window — stylesheets, images and fonts included) and writes the picture. A load that fails renders the page the window would show: the error page, or the certificate page.

Flag Meaning
--width N, --height N The viewport (800×720 by default)
--max-height N Cap the picture's height
--thumbnail small.png [--thumbnail-width N] Also write the viewport's top, scaled down
--report out.json Write a JSON account of the load: status, final URL, title, timings per stage, page height, text runs, stylesheets, pictures and fonts with their failures, connections, and what the page's stylesheets ask for that the engine does not do
--dump-live-dom <prefix> With --render: write the document as its scripts left it to <prefix>.html, and each frame's document to <prefix>-frame-N.html, numbered in tree order, each under a comment with its address.
--dump-layout Print every laid-out box and text run with its position, size and baseline — the instrument for a layout question. It goes with --render: an option only a windowless run reads, given with no such run named, is refused rather than opening the window

--bench — a whole run, timed

sashfold --bench page.html [--runs N] [--width N] [--height N] [--report out.json]

Runs a whole page the way the window would (1100×800 by default): time to first paint, time to pixels once the page's scripts have had their three seconds of virtual time, twenty wheel notches each timed for its frame and its paint, the resident set before and after, and the same shell counters and network account --render --report writes (see Scripting the shell and The Sashfold 100). Over several --runs it prints medians, and --report out.json writes them as one file.

--script — drive the shell from a text file

sashfold --script tests/shell/live.script [--update-goldens] [--width N] [--height N]

Replays commands against the shell and checks its assertions; this is how the shell is tested in CI. The command reference is on Scripting the shell.

Other modes

Mode Does
--fetch <url> Print the response head, through the same fetch choke point the browser uses
--dump-dom <file.html> Parse the file and print the document tree
--font-info <file.ttf|file.ttc> Describe a font file as the TrueType reader sees it
--font-list List the fonts the font manager catalogued, and how long the scan took
--import-theme <folder|manifest.json|file.xpi|file.crx|file.zip> [-o <dir>] Convert a Firefox or Chrome theme into a theme of ours, in -o's folder or the profile's themes folder; prints the theme file's path, and on stderr what could not be carried over (see Themes)
--font-sampler <out.png> [--font <file.ttf>] Draw a QA sheet of a face (Sashfold Mono by default)
--smoke [-o out.png] Render the painter's smoke scene

The Sashfold 100 and the WPT runner

bash tools/sashfold100.sh build/sashfold out/          # render the hundred and write the dashboard into out/
bash tools/wpt-fetch.sh                                # fetch the Web Platform Tests checkout, then:
build/tests/wpt_reftest wpt tests/wpt/directories.txt tests/wpt/passing.txt
bash tools/perf-census.sh out/ [--top N] [--by <column>]  # rank where the seconds go, from the same out/

See The Sashfold 100 and Testing for what each does and their flags.

Clone this wiki locally