I guess every browser makes those claims, but hww is very different than what you might be imagining.
hww fetches a web page, parses the HTML, then displays it using hww's own renderer. It removes so much surface area this way. Speed, safety, accessibility, and more privacy are very cheap after that. And the browser maintainer is not playing whack-a-mole with JS engine vulnerabilities. Multiple classes of bugs and vulnerabilities are not possible in hww.
<canvas> element, WebGL, audio, installed fonts, screen size, timezone, storage, or WebRTC. Servers still see your IP address, requested URLs, and hww's HTTP/TLS fingerprint.Ctrl+L, Ctrl+F, Ctrl+R, Ctrl+H, Ctrl+D, Alt+Left. Press ? for the card.Ctrl+D (Cmd+D on macOS) bookmarks the page you are reading and Ctrl+Shift+B opens them; Ctrl+H (Cmd+Y on macOS) opens the pages hww has drawn for you, which it writes down as it goes. Each has its own switch in Settings and its own button to empty it, and none of them takes another with it. The history records the address and the title, once per page rather than once per visit, and nothing about what you did on the page. Page info tells you whether the page on screen is bookmarked, and which hosts the site icons came from.Shift+L, or right-click it and choose Read later, and it waits on a list l opens. hww does not fetch any of the pages until you open one: the list holds addresses and the words the links were wearing, nothing else. Each row carries a remove button, and forget all under the title empties the list; Shift+L on a link already listed takes it off too./favicon.ico and leaves the column empty where that guess comes to nothing. Only the rows on screen are asked for, and each one only once: hww keeps the marks for the sites those two lists name (see On every platform), so opening a list again draws the column off your own disk. No image requests stops every one of those requests, as it stops every other picture — the column still draws whatever hww already has, which contacts nobody — and page info names every host contacted and counts the marks that needed none.Ctrl+Shift+R reloads bare.Binaries live on the Releases page. Download the file for your platform along with SHA256SUMS, and verify it before installing. With the GitHub CLI you can also check that a download was built by this repository's own workflow:
gh attestation verify <file> --repo tayler/hww
Ubuntu 22.04 or newer, for libc6 >= 2.35.
Download hww_*_amd64.deb and the checksum file SHA256SUMS from the latest release, then verify and install:
sha256sum --ignore-missing -c SHA256SUMS
sudo apt install ./hww_*_amd64.deb
The package installs the application, its desktop entry, and its icons. Open hww from the application menu or run hww at a shell; installing a newer package the same way upgrades it.
sudo apt purge hww
rm -rf "${XDG_CONFIG_HOME:-$HOME/.config}/hww"
Apple Silicon, macOS 11 Big Sur or later, which the disk image enforces. Download hww-*-aarch64-macos.dmg and the checksum file SHA256SUMS from the latest release. macOS ships shasum rather than sha256sum, so compare the two lines this prints:
shasum -a 256 hww-*-aarch64-macos.dmg
grep aarch64-macos SHA256SUMS
Open the image, drag hww.app onto the Applications shortcut beside it, and eject the image. The app is ad-hoc signed and carries no Developer ID, so Gatekeeper refuses the first launch. xattr -d com.apple.quarantine /Applications/hww.app clears it in one command, or open System Settings › Privacy & Security and choose Open Anyway beside the message naming hww.
An Intel Mac has no published binary and builds from source, which needs the Xcode Command Line Tools and a stable Rust toolchain:
cargo install --git https://github.com/tayler/hww --locked --features gui --bin hww
Drag the app to the Trash, then:
rm -rf ~/Library/Application\ Support/hww
64-bit Windows. Download hww-*-x86_64-windows.zip and the checksum file SHA256SUMS from the latest release. PowerShell has no sha256sum, so compare the two lines this prints:
$zip = Get-Item hww-*-x86_64-windows.zip
(Get-FileHash $zip -Algorithm SHA256).Hash.ToLower()
Select-String -Path SHA256SUMS -Pattern $zip.Name
Extract the archive and run hww.exe from the hww-<version> folder it creates. There is nothing to install: the binary links the C runtime statically, so no Visual C++ Redistributable is needed. The first run raises SmartScreen's "Windows protected your PC", since the binary is not code-signed; choose More info, then Run anyway.
Delete the hww-<version> folder and %APPDATA%\hww.
The Ubuntu package and the macOS bundle register hww as a handler for http and https, so it appears in Open with… on Ubuntu and Open With in Finder, and in the default-browser list on both. That makes hww choosable, not default. Do not set it as your default browser: single-page applications render blank in hww by design, and every link you click anywhere on the machine would land in a reader that cannot run them. Choose hww for the link you want to read in it.
Windows has no door yet. It ships as a zip with no installer, and registering a browser there means writing under HKLM\Software\Clients\StartMenuInternet, which is an installer's job. Run hww.exe <url> instead.
HWW_CONFIG_DIR overrides where settings, bookmarks, and history are kept; if it was set when hww ran, remove that directory instead of the one named above. Page content and article images are never saved to disk. The one file that outlives a run besides settings.json is archive.json, and it holds three lists: the pages you bookmarked, each with the address of its site's icon, the links you marked to read later, and — unless you switch it off — the address and title of each page hww has shown you. Settings › Bookmarks › forget everything empties the first, Settings › Reading list › forget the reading list the second, and Settings › History › forget history the third; each leaves the other two alone, and the uninstall commands above delete the file with the rest of the directory.
Beside it is one directory, icons, holding the little marks your bookmarks and your reading list draw beside each row. It holds them only for sites those two lists already name, never for a page you merely visited, so it says nothing your bookmarks do not already say — and it means opening either list draws its column without asking those sites for the same picture again. Either forget button deletes the marks for the list it empties, hww refetches one it has not seen for a month, and the settings panel prints the directory's path under both groups. Page info reports, on every page, how many marks came off your own disk and how many were fetched.
Before 0.4 this file was called library.json and bookmarks were called the library. hww does not look for the old file: if you are upgrading and want what is in it, rename it to archive.json yourself, and change every "kind": "kept" in it to "kind": "bookmark". The settings key moved with it — if you had turned page-keeping off, settings.json names it keep_library and hww now reads keep_bookmarks, so the switch comes back on until you set it again.
| File | Role |
|---|---|
src/bin/hww.rs | Parses command-line flags and starts the reader |
src/reader/ | Reading logic and settings; reader/ui drives the egui window |
src/reader/archive.rs | The bookmarks, the reading list, and the history, and the doctrine for anything hww is allowed to remember |
src/reader/iconcache.rs | Site-icon bytes on disk, for addresses the archive already names, and the one exception to that doctrine |
src/session.rs | Runs rewrite → fetch → decode → extract for a URL |
src/sites.rs | Builtin host rewrites and per-site extraction profiles |
src/search.rs | Turns a query into a URL and a result page into entries |
src/feed.rs | Parses RSS 2.0 and Atom into Document |
src/fetch.rs | HTTP client with no cookie jar, redirect inspection, and request limits |
src/html.rs | Parses HTML into Document: article scoring, cards, thread hooks |
src/thread.rs | Detects comment lists from repeated siblings with the same classes |
src/ir.rs | Semantic document intermediate representation (IR); extractors write the IR, renderers read it |
A stable Rust toolchain new enough for edition 2024 (1.85 or later), and a C toolchain for aws-lc-sys, which arrives under rustls and builds vendored sources rather than linking a system TLS library. No graphics, font, or windowing package has to be installed first, because every native library in the graph is opened at runtime. Windows also needs NASM on PATH; macOS needs only the Xcode Command Line Tools.
cargo run --features gui # the reader, URL bar focused
cargo run --features gui -- example.com/article # straight to a page
cargo build --release --features gui # ./target/release/hww
The application lives behind the gui feature, so core tests compile without the egui dependency graph or the image subresource path. hww takes --no-rewrite, --no-profile, --no-search, and --no-feed to switch off one way of reading a response for a single run, --show-rewrites, --show-profiles, and --show-engines to print a table and exit, and --why for triage. In the reader, Ctrl+Shift+R (Cmd+Shift+R on macOS) reloads with all four off at once.
cargo run --features gui -- --why https://example.com/article
cargo run --features gui --bin hww-shot -- --url https://example.com/article --out /tmp/look
--why fetches through the same pipeline as a normal load and prints, instead of the article, what the extractor did with it: every content-root candidate it weighed with the winner marked, what the thread detector saw and why each group was rejected or chosen, where each metadata field came from, and whether the <body> fallback fired. It is built by the same pass that builds the document, so it cannot describe a decision the extractor did not take. Every terminal print runs through render::sanitize_for_terminal, because untrusted page text on a terminal is a stream of commands.
hww-shot photographs the reader on a page, so you can look at the rendering instead of guessing at it. --keys "space space" scrolls first, --theme dark checks the other palette, and --out keeps an ad-hoc look out of the regression baseline. Its --all catalog is a separate regression run that owns the display for minutes at a time.
Five commands must pass:
cargo fmt --all -- --check
cargo clippy --all-targets --locked -- -D warnings
cargo test --locked
cargo clippy --all-targets --locked --features gui -- -D warnings
cargo test --locked --features gui
The first three run only on Linux. The last two run again on Windows and macOS, which block the same merges. Each push to main also attaches a development package to its workflow run, kept for 14 days and meant for testing unreleased code.
Cargo.lock is committed because this crate ships binaries.
Licensed under the GNU Affero General Public License, version 3 or later (LICENSE or https://www.gnu.org/licenses/agpl-3.0.html).
Section 13 does not arise for a desktop client, which serves nobody over a network; it is here for the shape this code would take if it ever did. The extraction pipeline is the part of hww worth lifting, and a hosted version of it is the one derivative that plain GPL would let stay closed.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you shall be licensed as above, without any additional terms or conditions.
The embedded faces keep their own terms: Atkinson Hyperlegible Next, IBM Plex, and Noto under the SIL Open Font License, DejaVu Serif under the Bitstream Vera license. The texts are in fonts/ and ship in every package.
The license grants rights in the code and none in the name hww or the logo under assets/logo/. Sections 7(d) and 7(e) of the AGPL provide for a notice of this kind, so this is an additional term under the license rather than a request standing beside it. It is stated in NOTICE, which ships in every package: a term that reached only this file would reach nobody holding the .deb or the .zip, who are the people it is addressed to.
Referring to the project needs no permission: call a fork "a fork of hww", say that a program reads hww's settings file, name it in a comparison, write about it. What needs permission is using the name or the logo as the identity of something distributed — a modified build published as hww, a package or executable named for it, or any presentation implying that this project produced or endorsed the result. Fork under the license and give the fork its own name.
61 commits
1 commits
Hacker News (1)
Rust
98.5%
Shell
1.1%
I guess every browser makes those claims, but hww is very different than what you might be imagining.
hww fetches a web page, parses the HTML, then displays it using hww's own renderer. It removes so much surface area this way. Speed, safety, accessibility, and more privacy are very cheap after that. And the browser maintainer is not playing whack-a-mole with JS engine vulnerabilities. Multiple classes of bugs and vulnerabilities are not possible in hww.
<canvas> element, WebGL, audio, installed fonts, screen size, timezone, storage, or WebRTC. Servers still see your IP address, requested URLs, and hww's HTTP/TLS fingerprint.Ctrl+L, Ctrl+F, Ctrl+R, Ctrl+H, Ctrl+D, Alt+Left. Press ? for the card.Ctrl+D (Cmd+D on macOS) bookmarks the page you are reading and Ctrl+Shift+B opens them; Ctrl+H (Cmd+Y on macOS) opens the pages hww has drawn for you, which it writes down as it goes. Each has its own switch in Settings and its own button to empty it, and none of them takes another with it. The history records the address and the title, once per page rather than once per visit, and nothing about what you did on the page. Page info tells you whether the page on screen is bookmarked, and which hosts the site icons came from.Shift+L, or right-click it and choose Read later, and it waits on a list l opens. hww does not fetch any of the pages until you open one: the list holds addresses and the words the links were wearing, nothing else. Each row carries a remove button, and forget all under the title empties the list; Shift+L on a link already listed takes it off too./favicon.ico and leaves the column empty where that guess comes to nothing. Only the rows on screen are asked for, and each one only once: hww keeps the marks for the sites those two lists name (see On every platform), so opening a list again draws the column off your own disk. No image requests stops every one of those requests, as it stops every other picture — the column still draws whatever hww already has, which contacts nobody — and page info names every host contacted and counts the marks that needed none.Ctrl+Shift+R reloads bare.Binaries live on the Releases page. Download the file for your platform along with SHA256SUMS, and verify it before installing. With the GitHub CLI you can also check that a download was built by this repository's own workflow:
gh attestation verify <file> --repo tayler/hww
Ubuntu 22.04 or newer, for libc6 >= 2.35.
Download hww_*_amd64.deb and the checksum file SHA256SUMS from the latest release, then verify and install:
sha256sum --ignore-missing -c SHA256SUMS
sudo apt install ./hww_*_amd64.deb
The package installs the application, its desktop entry, and its icons. Open hww from the application menu or run hww at a shell; installing a newer package the same way upgrades it.
sudo apt purge hww
rm -rf "${XDG_CONFIG_HOME:-$HOME/.config}/hww"
Apple Silicon, macOS 11 Big Sur or later, which the disk image enforces. Download hww-*-aarch64-macos.dmg and the checksum file SHA256SUMS from the latest release. macOS ships shasum rather than sha256sum, so compare the two lines this prints:
shasum -a 256 hww-*-aarch64-macos.dmg
grep aarch64-macos SHA256SUMS
Open the image, drag hww.app onto the Applications shortcut beside it, and eject the image. The app is ad-hoc signed and carries no Developer ID, so Gatekeeper refuses the first launch. xattr -d com.apple.quarantine /Applications/hww.app clears it in one command, or open System Settings › Privacy & Security and choose Open Anyway beside the message naming hww.
An Intel Mac has no published binary and builds from source, which needs the Xcode Command Line Tools and a stable Rust toolchain:
cargo install --git https://github.com/tayler/hww --locked --features gui --bin hww
Drag the app to the Trash, then:
rm -rf ~/Library/Application\ Support/hww
64-bit Windows. Download hww-*-x86_64-windows.zip and the checksum file SHA256SUMS from the latest release. PowerShell has no sha256sum, so compare the two lines this prints:
$zip = Get-Item hww-*-x86_64-windows.zip
(Get-FileHash $zip -Algorithm SHA256).Hash.ToLower()
Select-String -Path SHA256SUMS -Pattern $zip.Name
Extract the archive and run hww.exe from the hww-<version> folder it creates. There is nothing to install: the binary links the C runtime statically, so no Visual C++ Redistributable is needed. The first run raises SmartScreen's "Windows protected your PC", since the binary is not code-signed; choose More info, then Run anyway.
Delete the hww-<version> folder and %APPDATA%\hww.
The Ubuntu package and the macOS bundle register hww as a handler for http and https, so it appears in Open with… on Ubuntu and Open With in Finder, and in the default-browser list on both. That makes hww choosable, not default. Do not set it as your default browser: single-page applications render blank in hww by design, and every link you click anywhere on the machine would land in a reader that cannot run them. Choose hww for the link you want to read in it.
Windows has no door yet. It ships as a zip with no installer, and registering a browser there means writing under HKLM\Software\Clients\StartMenuInternet, which is an installer's job. Run hww.exe <url> instead.
HWW_CONFIG_DIR overrides where settings, bookmarks, and history are kept; if it was set when hww ran, remove that directory instead of the one named above. Page content and article images are never saved to disk. The one file that outlives a run besides settings.json is archive.json, and it holds three lists: the pages you bookmarked, each with the address of its site's icon, the links you marked to read later, and — unless you switch it off — the address and title of each page hww has shown you. Settings › Bookmarks › forget everything empties the first, Settings › Reading list › forget the reading list the second, and Settings › History › forget history the third; each leaves the other two alone, and the uninstall commands above delete the file with the rest of the directory.
Beside it is one directory, icons, holding the little marks your bookmarks and your reading list draw beside each row. It holds them only for sites those two lists already name, never for a page you merely visited, so it says nothing your bookmarks do not already say — and it means opening either list draws its column without asking those sites for the same picture again. Either forget button deletes the marks for the list it empties, hww refetches one it has not seen for a month, and the settings panel prints the directory's path under both groups. Page info reports, on every page, how many marks came off your own disk and how many were fetched.
Before 0.4 this file was called library.json and bookmarks were called the library. hww does not look for the old file: if you are upgrading and want what is in it, rename it to archive.json yourself, and change every "kind": "kept" in it to "kind": "bookmark". The settings key moved with it — if you had turned page-keeping off, settings.json names it keep_library and hww now reads keep_bookmarks, so the switch comes back on until you set it again.
| File | Role |
|---|---|
src/bin/hww.rs | Parses command-line flags and starts the reader |
src/reader/ | Reading logic and settings; reader/ui drives the egui window |
src/reader/archive.rs | The bookmarks, the reading list, and the history, and the doctrine for anything hww is allowed to remember |
src/reader/iconcache.rs | Site-icon bytes on disk, for addresses the archive already names, and the one exception to that doctrine |
src/session.rs | Runs rewrite → fetch → decode → extract for a URL |
src/sites.rs | Builtin host rewrites and per-site extraction profiles |
src/search.rs | Turns a query into a URL and a result page into entries |
src/feed.rs | Parses RSS 2.0 and Atom into Document |
src/fetch.rs | HTTP client with no cookie jar, redirect inspection, and request limits |
src/html.rs | Parses HTML into Document: article scoring, cards, thread hooks |
src/thread.rs | Detects comment lists from repeated siblings with the same classes |
src/ir.rs | Semantic document intermediate representation (IR); extractors write the IR, renderers read it |
A stable Rust toolchain new enough for edition 2024 (1.85 or later), and a C toolchain for aws-lc-sys, which arrives under rustls and builds vendored sources rather than linking a system TLS library. No graphics, font, or windowing package has to be installed first, because every native library in the graph is opened at runtime. Windows also needs NASM on PATH; macOS needs only the Xcode Command Line Tools.
cargo run --features gui # the reader, URL bar focused
cargo run --features gui -- example.com/article # straight to a page
cargo build --release --features gui # ./target/release/hww
The application lives behind the gui feature, so core tests compile without the egui dependency graph or the image subresource path. hww takes --no-rewrite, --no-profile, --no-search, and --no-feed to switch off one way of reading a response for a single run, --show-rewrites, --show-profiles, and --show-engines to print a table and exit, and --why for triage. In the reader, Ctrl+Shift+R (Cmd+Shift+R on macOS) reloads with all four off at once.
cargo run --features gui -- --why https://example.com/article
cargo run --features gui --bin hww-shot -- --url https://example.com/article --out /tmp/look
--why fetches through the same pipeline as a normal load and prints, instead of the article, what the extractor did with it: every content-root candidate it weighed with the winner marked, what the thread detector saw and why each group was rejected or chosen, where each metadata field came from, and whether the <body> fallback fired. It is built by the same pass that builds the document, so it cannot describe a decision the extractor did not take. Every terminal print runs through render::sanitize_for_terminal, because untrusted page text on a terminal is a stream of commands.
hww-shot photographs the reader on a page, so you can look at the rendering instead of guessing at it. --keys "space space" scrolls first, --theme dark checks the other palette, and --out keeps an ad-hoc look out of the regression baseline. Its --all catalog is a separate regression run that owns the display for minutes at a time.
Five commands must pass:
cargo fmt --all -- --check
cargo clippy --all-targets --locked -- -D warnings
cargo test --locked
cargo clippy --all-targets --locked --features gui -- -D warnings
cargo test --locked --features gui
The first three run only on Linux. The last two run again on Windows and macOS, which block the same merges. Each push to main also attaches a development package to its workflow run, kept for 14 days and meant for testing unreleased code.
Cargo.lock is committed because this crate ships binaries.
Licensed under the GNU Affero General Public License, version 3 or later (LICENSE or https://www.gnu.org/licenses/agpl-3.0.html).
Section 13 does not arise for a desktop client, which serves nobody over a network; it is here for the shape this code would take if it ever did. The extraction pipeline is the part of hww worth lifting, and a hosted version of it is the one derivative that plain GPL would let stay closed.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you shall be licensed as above, without any additional terms or conditions.
The embedded faces keep their own terms: Atkinson Hyperlegible Next, IBM Plex, and Noto under the SIL Open Font License, DejaVu Serif under the Bitstream Vera license. The texts are in fonts/ and ship in every package.
The license grants rights in the code and none in the name hww or the logo under assets/logo/. Sections 7(d) and 7(e) of the AGPL provide for a notice of this kind, so this is an additional term under the license rather than a request standing beside it. It is stated in NOTICE, which ships in every package: a term that reached only this file would reach nobody holding the .deb or the .zip, who are the people it is addressed to.
Referring to the project needs no permission: call a fork "a fork of hww", say that a program reads hww's settings file, name it in a comparison, write about it. What needs permission is using the name or the logo as the identity of something distributed — a modified build published as hww, a package or executable named for it, or any presentation implying that this project produced or endorsed the result. Fork under the license and give the fork its own name.
Hacker News (1)
61 commits
1 commits
Rust
98.5%
Shell
1.1%