RustyWolf/README.md

9.6 KiB

RustyWolf

RustyWolf is a minimal, privacy-focused browser shell built in Rust with two engine modes:

  • WebKit mode (default, light) — the system webview: WebKitGTK on Linux, WKWebView on macOS, WebView2 on Windows. No browser install needed.
  • Gecko mode (opt-in) — real Firefox (Gecko) engine through a RustyWolf-managed profile. Requires an installed Firefox.

Switch between them any time with the leaf toggle in the toolbar (or the leaf on the RustyWolf home page in Gecko mode). Open tabs carry over in both directions.

(complete honesty, this whole thing is vibecoded, however I never paid for any ai service (I got a free student plan for a year) so if you wanna avoid AI slop, just skip this but I never contributed to the AI BOOM with my money, if you wanna contribute, feel free to do so)

image

Engines

WebKit mode Gecko mode
Engine WebKitGTK / WKWebView / WebView2 Firefox (Gecko), driven by RustyWolf
Weight lightest — typically ~300 MB with a tab open Firefox-weight
RustyWolf UI full chrome (tabs, URL bar, ADS, K, D, Properties) Firefox's own UI + RustyWolf home page
Adblock built-in lightweight blocker (ADS toggle) Firefox strict tracking protection
Extras keep-in-ram tabs (K), popup gate, download panel, properties page Firefox features, managed profile, tab handoff

The leaf button shows the current engine: lit green = WebKit, dim = Gecko.

What It Does

  • Really, I mean really lightweight in WebKit mode! the reason I even made this is because I need a lightweight browser to run on my old macbook unibody 2010 4gb ddr3
    • in a gentoo(openrc)+i3wm setup it took only ~285 MB RAM with one tab open (dvorakmortonxd.dev) compared to firefox which took ~866 MB
    • tabs have a toggle for Keeping-in-ram (K): with it off the tab is unloaded, only the URL is kept, and it reloads on click
    • background tabs are suspended automatically, and the download ticker only runs while something is downloading
  • Privacy-first defaults: DuckDuckGo home + search fallback from the URL bar
  • Multi-tab browsing with back, forward, reload, and keyboard shortcuts (Ctrl/Cmd+T, W, L)
  • Built-in custom adblock with top-bar toggle (ADS), persisted across restarts
  • Popup handling that behaves like a real browser: clicked links open tabs, clicked window.open popups (OAuth/"Sign in with Google", SoundCloud, ...) open real popup windows with window.opener intact, and scripted popups go through the permission gate
  • Native user agent by default, so sites (and their login flows) see an honest browser; --ua-chrome is available for stubborn sites
  • Download support with live progress panel (D) and session download history
  • Properties page with session browsing history + download history
  • Default window size 1000x600 (still fully resizable)
  • Optional --private mode in both engines
  • Engine switch with tab handoff: WebKit tabs become Firefox tabs and vice versa

Run

cargo run --

# pick a URL / window title
cargo run -- --url https://example.com
cargo run -- --url example.com
cargo run -- --title "RustyWolf"

# engine selection (persisted in ~/.config/RustyWolf/config.json)
cargo run -- --engine webkit
cargo run -- --engine gecko
cargo run -- --engine gecko --firefox /path/to/firefox

# compatible user agent for picky sites (WebKit mode)
cargo run -- --ua-chrome

# misc
cargo run -- --private
cargo run -- --dry-run

# Linux backend controls
cargo run -- --linux-backend x11
cargo run -- --linux-backend wayland
cargo run -- --linux-disable-dmabuf

The leaf button in the toolbar switches engines immediately; the choice is remembered for the next launch.

Gecko Mode (real Firefox engine)

There is no embeddable Gecko in 2026, so Gecko mode supervises a real Firefox with a dedicated profile under ~/.config/RustyWolf/gecko-profile:

  • hardening prefs are rewritten on every launch (strict tracking protection, DNT/GPC, no telemetry, no sponsored content, no Pocket)
  • downloads go straight to your Downloads folder
  • new tabs stay blank; the RustyWolf home page is the start page and carries the leaf button back to WebKit
  • browser.sessionstore.interval is shortened so RustyWolf can hand your tabs back to WebKit
  • Firefox is launched with --no-remote --new-instance, so your normal Firefox session is never touched (--firefox / RUSTYWOLF_FIREFOX to point at a specific binary)

Privacy Notes

WebKit mode applies baseline hardening in page context:

  • navigator.doNotTrack = "1"
  • disables legacy openDatabase
  • disables RTCPeerConnection

Adblocking is built-in and lightweight. It is not full uBlock Origin parity. Gecko mode uses Firefox's own strict tracking protection instead.

Linux Setup (prerequisites)

Install WebKitGTK development/runtime packages before building.

Debian

sudo apt update
sudo apt install -y libwebkit2gtk-4.1-dev libgtk-3-dev build-essential pkg-config git appmenu-gtk3-module appmenu-gtk2-module
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

Arch

sudo pacman -Sy
sudo pacman -S --needed webkit2gtk-4.1 gtk3 base-devel pkgconf git appmenu-gtk-module
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

Gentoo

(u can replace doas with sudo btw)

doas emerge --sync
doas emerge --ask net-libs/webkit-gtk:4.1 x11-libs/gtk+ virtual/pkgconfig dev-vcs/git x11-misc/appmenu-gtk-module
doas mkdir -p /etc/portage/package.use
echo ">=media-libs/gst-plugins-base-1.24.13-r1 gbm" | doas tee /etc/portage/package.use/rustywolf-media
doas emerge --ask 'media-libs/gst-plugins-base[gbm]' media-plugins/gst-plugins-soup media-plugins/gst-plugins-vpx media-plugins/gst-plugins-hls media-plugins/gst-plugins-dash media-plugins/gst-plugins-libav
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

For Gecko mode just make sure Firefox is installed (emerge www-client/firefox or the binary release).

For NVIDIA, make the DRM modeset setting part of the boot command line, not only /etc/modprobe.d, then reboot:

doas cp /etc/default/grub /etc/default/grub.bak
doas sed -i 's/^#GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="nvidia-drm.modeset=1 nvidia-drm.fbdev=1"/' /etc/default/grub
doas grub-mkconfig -o /boot/grub/grub.cfg
doas reboot

After reboot, verify the active command line:

cat /proc/cmdline

Linux media playback deps (important)

If Linux logs gstreamer element autoaudiosink not found or YouTube/audio fails, install GStreamer audio/video plugins.

Debian/Ubuntu/Pop!_OS example:

sudo apt update
sudo apt install -y gstreamer1.0-tools
sudo apt install -y gstreamer1.0-plugins-base gstreamer1.0-plugins-good
sudo apt install -y gstreamer1.0-plugins-bad gstreamer1.0-libav
sudo apt install -y gstreamer1.0-pulseaudio gstreamer1.0-pipewire gstreamer1.0-alsa

Verify the sink exists:

gst-inspect-1.0 autoaudiosink

If your distro is not Debian-based, install the equivalent GStreamer base/good/bad/libav + audio sink plugin packages.

Linux Troubleshooting (Wayland/X11)

RustyWolf supports both X11 and native Wayland on Linux.

Some NVIDIA + WebKitGTK stacks can fail with dmabuf/gbm allocation errors, especially on Wayland. On NVIDIA X11, RustyWolf disables WebKitGTK's broken dmabuf renderer automatically. This avoids the blank webview/GBM allocation failure while keeping GStreamer media codecs available for sites such as YouTube.

Try these launch modes:

# auto backend (also applies the NVIDIA/X11 WebKitGTK fallback when needed)
cargo run

# native wayland
cargo run -- --linux-backend wayland

# X11/XWayland
cargo run -- --linux-backend x11

# last-resort compatibility fallback
cargo run -- --linux-disable-dmabuf

# force the upstream dmabuf renderer anyway
WEBKIT_FORCE_DMABUF_RENDERER=1 cargo run

If you still see Failed to load module "appmenu-gtk-module", that is a desktop GTK setup issue (not a RustyWolf crash).

Debian/Ubuntu/Pop!_OS fix:

sudo apt update
sudo apt install -y appmenu-gtk3-module appmenu-gtk2-module

If you do not want global appmenu integration, remove appmenu-gtk-module from GTK settings files:

~/.config/gtk-3.0/settings.ini
/etc/gtk-3.0/settings.ini
/etc/xdg/gtk-3.0/settings.ini

If RustyWolf segfaults instantly with Couldn't register with accessibility bus when launched from a bare TTY/SSH shell, there is no session D-Bus for the GTK accessibility bridge (libatk-bridge). Launch it from your graphical session, or make DBUS_SESSION_BUS_ADDRESS available (on many systems export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$(id -u)/bus).

MacOS

installing Homebrew (skip if already installed)

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Gecko mode finds Firefox in /Applications/Firefox.app automatically; WebKit mode uses the system WKWebView.

Windows Setup

Install the Microsoft Edge WebView2 Runtime (Evergreen) for WebKit mode, then build normally with the Rust MSVC toolchain.

Gecko mode finds Firefox under Program Files / %LOCALAPPDATA%\Mozilla Firefox, or use --firefox.

Dev Quick Checks

cargo fmt
cargo check
cargo test
cargo clippy --all-targets

# exercises the Gecko handoff against a real headless Firefox
cargo test -- --ignored --nocapture