A small browser with a hard memory budget. Open as many tabs as you like; Wren keeps the whole browser (engine processes included) under a budget you set, 500 MB by default.
Named for the bird: tiny, loud, everywhere. Runs on Linux and Windows.
No browser engine is light, so Wren doesn't pretend to be. Instead it controls the lifecycle of tabs. A watchdog measures the real memory of the whole process tree every few seconds and walks an escalation ladder:
| Tier | When | What happens | What you notice |
|---|---|---|---|
| Freeze | A background tab has been idle ~30 s | JS and timers stop | Nothing |
| Discard | Memory passes ~85% of budget | Oldest background tabs drop their renderer (history kept) | Tab reloads when you return |
| Destroy | Still over budget | View deleted; tab becomes a URL + title placeholder | Reload, scroll position lost |
| Warn | The active tab alone exceeds the budget | Nothing is killed | Memory badge turns red |
Restored sessions open as placeholders: only the tab you're looking at loads, so startup is fast and a 40-tab session costs the same as a 2-tab one.
The toolbar badge always shows the live number, e.g. 342 / 500 MB.
Needs Python 3.10+ and uv (or plain pip). No compiler, no admin rights, no system packages.
git clone <this-repo> wren && cd wren
uv venv .venv
uv pip install .
.venv/bin/wren # Windows: .venv\Scripts\wrenOr for development: uv pip install -e ".[dev]".
wren # restore last session (as lazy placeholders)
wren https://example.com # open URLs
wren --budget-mb 400 # override the budget for this runType in the address bar: full URLs load, bare hostnames get https://,
anything else searches DuckDuckGo.
| Key | Action |
|---|---|
| Ctrl+T / Ctrl+W | New tab / close tab |
| Ctrl+L | Focus address bar |
| Ctrl+Tab / Ctrl+Shift+Tab | Next / previous tab |
| Ctrl+R or F5 | Reload |
| Ctrl+F | Find in page (Esc closes) |
| Ctrl+= / Ctrl+- / Ctrl+0 | Zoom in / out / reset |
| Ctrl+Q | Quit |
~/.config/wren/config.json on Linux, %APPDATA%\wren\config.json on Windows.
All keys optional:
{
"budget_mb": 500,
"soft_ratio": 0.85,
"freeze_after_s": 30.0,
"governor_interval_ms": 3000,
"pressure_interval_ms": 1000,
"renderer_process_limit": 2,
"disable_gpu": false,
"restore_session": true,
"search_template": "https://duckduckgo.com/?q={query}",
"home_url": "about:blank"
}- The floor is the floor: one live tab costs roughly 250–350 MB because the engine is Chromium (via Qt WebEngine). The budget controls the ceiling: 20 tabs cost about the same as 2.
- A single heavy page (YouTube, Figma) can exceed the budget on its own while active. Wren shows this (red badge) instead of killing what you're reading.
- No extensions, no sync, no DRM video. It's for browsing websites.
- GPU rendering is on by default; software rendering turned out unusably
slow in real use. The GPU process costs 50–100 MB (counted in the badge),
and on Linux some graphics-driver allocations escape the accounting, so
the badge can read slightly low there.
disable_gpu: trueexists for headless runs or strict accounting.
Signing into a Google account directly (accounts.google.com) fails with "This browser or app may not be secure". This is Google deliberately blocking embedded browser engines, and Wren uses one (QtWebEngine). It is not fixable from Wren's side, and it affects every QtWebEngine browser, qutebrowser included.
Why it can't be worked around here: a clean Chrome user-agent is given away by
the engine's Sec-CH-UA client-hint headers; spoofing Firefox doesn't help
because those Chromium client hints keep getting sent and then contradict the
Firefox user-agent, which is itself the signature Google blocks. The one lever
that would fix it, turning client hints off, isn't honored by the engine. This
was tested directly, not assumed.
Workaround: sign into Google in a mainstream browser (Chrome, Firefox, Edge). Wren handles everything else. If first-class Google support ever becomes essential, the real fix is a different engine, which is a much larger change.
Ubuntu 24.04 restricts unprivileged user namespaces, which breaks Chromium's
sandbox for pip-installed engines. Wren detects this and disables the engine
sandbox for itself (with a loud log line) so pages still render. This is a
real security trade-off; prefer trusted sites, or allow user namespaces
system-wide if you'd rather keep the sandbox:
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 (needs sudo).
uv pip install -e ".[dev]"
pre-commit install
ruff check . && black --check . && pytest --tb=shortThe governor logic (governor.py), memory accounting (memory.py), config
(config.py), and URL handling (utils.py) are pure and unit-tested. The Qt
classes (browser.py, tab.py) are thin glue over those modules and are
exercised by running the app (wren --smoke-seconds 20 <urls> prints a
memory report and exits; used for measurement).
MIT