About
I learn by building the entire thing. Not the demo, the thing: the app, the engine underneath it, the servers it talks to, the page that explains it. Nothing here was assembled from a template, which is slower, and the point.
I work alone, and I do every part myself: the Swift, the shaders, the cryptography, the servers, the support site, the words you are reading. One pair of hands is not a virtue on its own, but the seams between people are where software quietly rots, and this way there are no seams.
I am hard to satisfy, mostly with myself. The wind blowing across this page was rebuilt four times, because the first three were the wrong kind of wind. Most of what I make goes through that. It is the temperament everything below came from.
Privacy is not a niche I picked off a list. Software that watches people reads to me as a defect, in the same category as a crash. So I build the versions that cannot watch, and I put the proof in the architecture instead of in a promise.
Not all of it is software. I follow SpaceX and SpaceXAI closely, the launches, the engineering, where it is all heading, and I write it up every day. It is the same instinct as the code, wanting to get close to a hard thing and understand it all the way down instead of watching from across the room.
The short version
Everything here runs on your own machine unless it genuinely cannot, and each exception is printed next to the feature it belongs to.
That is most of the philosophy. The rest is just doing the work carefully enough that the claim stays true.
for nearly everything on this page
blocking rules compiled into the browser
is all Maximum makes in its entire life
leave this page for anywhere else
Work
Searxly
- Platform
- macOS 15+, Apple Silicon
- Stack
- Swift · SwiftUI · WebKit · XPC
- Engine
- SearXNG on embedded CPython 3.12
- Licence
- PolyForm Noncommercial · AGPL parts
A native SwiftUI browser that bundles its own metasearch engine, so searching does not involve a company.
Searxly ships a full SearXNG instance inside the app bundle and runs it on your Mac. Your queries reach the engines they are meant to reach and nowhere else. There is no Searxly server in the search path, because there is no Searxly server.
Getting there meant deleting Docker. The engine now runs on a relocatable CPython 3.12.13 with every dependency installed as a prebuilt arm64 wheel and zero compilation, all twenty-odd Mach-O binaries codesigned with a hardened runtime so the whole thing survives being moved into an app bundle. That change was one commit: 797 lines added, 1,602 removed, across 21 files.
The rest is the browser you would expect from someone who cares about this. Tor with pluggable transports and per-tab circuit isolation, 257,000 blocking rules compiled across 14 lists, a native results page with client-side ranking, Reader Mode, on-device page translation, and a password vault. It is source available, notarized, and free.
Searxly Maximum
- Price
- $25 once, perpetual
- Built from
- One source tree, two targets
- Licensing
- Offline Ed25519, hardware bound
- Network calls
- Exactly one, ever
The same source tree, compiled into a second app that assumes you are actually being watched.
Maximum is one compile flag and one source of truth away from the free app. It forces maximum privacy and Tor at every launch, refuses to be downgraded, and strips out every surface the free app has that touches a network for a non-privacy reason.
The hardening is in the engine, not in JavaScript. WebKit's experimental and internal feature flags are enumerated at runtime and the privacy relevant ones turned off inside the engine: WebRTC, gamepad, NFC, serial, HID, USB, Bluetooth, battery, prefetch, prerender. Real Lockdown Mode and a Tor Browser style Standard, Safer, Safest slider sit on top. Every private call is guarded, so a missing symbol degrades instead of crashing. JavaScript shims stay as the floor, not the ceiling.
Because Maximum blocks native egress in Tor mode, Sparkle could never check for updates, which is a genuine hole. So the updater is replaced. It fetches the appcast over the fail-closed Tor lane, parses it, downloads over a delegated Tor session, and verifies the Ed25519 signature independently with CryptoKit before anything is trusted.
Licensing is offline. An Ed25519 signature verified against a bundled public key, bound to the machine. The app contacts a server exactly once in its life, at activation, and the privacy page says so in those words.
Searxly for iPhone
- Platform
- iOS 26+, iPhone and iPad
- Architecture
- Shared source group, UIKit browser layer
- Search
- Hosted instance, disclosed as a trust shift
The same browser on iOS, minus the parts that could not honestly come along.
A second target inside the existing Xcode project, sharing a synchronised source group with the Mac app and re-implementing the browser layer as UIKit representables.
It has no wallet, no crypto, no VPN, no Tor, and no bundled search engine. Partly App Review, partly physics. Search rides a hosted instance instead of one on your device, which is a real shift in who you have to trust. The product page says that plainly rather than burying it, because the alternative is a privacy app that lies in its first paragraph.
It is on public TestFlight now. The floor is iOS 26, which keeps the tester pool small and was a deliberate trade for Liquid Glass.
TethrX
- Bridge
- Zero-dependency Node · Apache-2.0
- Transport
- ACP over HTTP/SSE, pinned TLS
- Push
- Hand-rolled APNs, ES256 + HTTP/2
Driving a terminal coding agent from a phone, over a connection with no middleman.
An iPhone app and a local daemon that pair over a QR code and talk directly. No relay, no account, no cloud.
The bridge is zero-dependency Node, which meant writing the parts a dependency would have handed me. Apple Push over hand-rolled ES256 JWTs and HTTP/2 straight to Apple. TLS pinned to a SHA-256 certificate fingerprint that travels inside the pairing QR code itself, so the very first connection is verified rather than trusted.
On the phone: a WidgetKit widget and Live Activities, a slash command palette, voice dictation, a project file browser jailed to the working directory, git review, Siri intents, Bonjour discovery, and a French localisation of about 200 hand-written keys.
Bulwark
- Licence
- MIT
- Languages
- Swift (complete) · Python · TypeScript
- Detection
- 70 signatures, 15 languages
- Tests
- 87 passing (Swift)
Prompt injection defence for agent loops. MIT, because this is not the kind of thing to keep.
A pipeline of sanitize, detect, spotlight, harden, validate, with 70 detection signatures across 15 languages, noisy-OR scored, folding leetspeak and composed obfuscation.
ToolGuard is the part I would keep if I could keep one thing. It guards the three choke points of an agent loop: the arguments going in, with exfiltration URL heuristics, invisible Unicode smuggling checks and a scheme allowlist; the outputs coming back; and the loop itself, with rate limiting, duplicate call detection, and a taint model that refuses any call above read-only once the agent has read untrusted content.
Rampart, added in 0.5.0, is deterministic zero-dependency PII redaction for email, phone, card via Luhn, SSN, IP and IBAN, with typed placeholders and rehydration. It is a clean-room reimplementation rather than a port, for licence reasons.
The Swift implementation is complete and covered by 87 passing tests. The Python and TypeScript ports have the detection layer but not yet ToolGuard.
ScanRecords
- Tracked
- 31 companies, 96 documents, daily
- Record
- Git history, one commit per real change
- Site
- 78 pages, 5 languages, no client JavaScript
- Licence
- MIT code, CC0 data
A public archive that records, every day, what the messaging platforms say they do with your messages, so that a quiet policy edit stops being quiet.
The EU's Chat Control derogation makes scanning private communications voluntary, so each provider decides for itself, and that decision, where it becomes public at all, becomes public as a small edit to a policy page. Nobody was keeping that record, and it is not a record you can reconstruct later. A measurement of 26 July can only be taken on 26 July.
So it is taken every day. At 06:17 UTC a zero-dependency tool fetches 96 tracked documents across 31 companies and 3 institutions, extracts the readable text, hashes it, and commits only when the text actually changed, so presentation churn never becomes a headline. Git history is the timestamped record, the repository is public so anyone can re-run it, and the Internet Archive is asked for an independent capture the same day. Alongside the policies it tracks 25 App Store privacy labels and 29 Play data safety declarations.
Most of the engineering is in not crying wolf. American CI runners were being served different pages than the European baselines, so every fetch now goes out through a relay in Paris. Google Play reshuffles its declarations on every request, so those are canonicalised before they are hashed. A failed fetch once got published as a policy change, so a capture that collapses to nothing can no longer overwrite a good one. When a record does turn out to be false it is withdrawn rather than deleted, and it keeps its page and its URL.
The site is 78 pages in five languages, generated by a script with no dependencies, and it ships no JavaScript at all except on the opt-in alerts page. It publishes observations and never conclusions: a recorded change means the document changed, and where the archive is silent it says so in those words, because silence measures disclosure and not behaviour.
searxly.app
- Stack
- Next.js 16 · Tailwind v4 · Vercel
- Home page
- 17 segments over 3,400vh
- Support auth
- OTP + stateless HMAC, no accounts
- Help assistant
- No LLM, no network egress
A marketing site that is a scroll-driven film, and a support portal with no accounts.
The home page is not a page with animations on it. It is a seventeen-segment film across 3,400 viewport heights, with a CSS 3D MacBook whose lid opens on the hinge, a five-chapter iPhone act, and a canvas globe of 940 points drawing great circle arcs. Film grain, letterboxing and per-act colour grading throughout. Four locales, and untranslated routes noindex themselves rather than pretending.
The support portal has no accounts. Everything is email OTP and stateless HMAC tokens: the admin session, the fifteen-minute magic link, the per-ticket view key. It carries tickets, a public governance board, and translation across 20 languages, in 11 serverless functions, because the limit is 12.
The help assistant on every page has no model behind it. It fetches and indexes the site's own 28 pages in your browser and answers out of an IDF retrieval engine I wrote, with typo tolerance, light stemming, phrase bonuses and coverage weighting. No API key, no egress, no cost. A help widget should not be a data collection surface.
Approach
It should not need to be trusted
Trust is a promise, and promises break. I would rather remove the need: no server holding your data, no account behind it, no log to leak. When the dangerous part does not exist, nobody has to wonder about my character.
Write the dangerous parts yourself
The parts I do not understand are the parts that break. So the cryptography gets written by hand and tested until I know exactly how it fails, instead of imported and hoped about.
The limit sits next to the claim
Where something is built but not released, it says so. Where an app has to trust a server, that goes in the same paragraph as the feature, not in a policy nobody opens.
Stack
Languages
07- Swift
- TypeScript
- JavaScript
- Python
- SQL
- Bash
- Objective-C interop
Apple platforms
16- SwiftUI
- UIKit
- AppKit
- WebKit / WKWebView
- XPC Services
- App Sandbox
- CryptoKit
- Keychain
- Secure Enclave
- NetworkExtension
- Network.framework
- WidgetKit
- Live Activities
- App Intents
- Translation
- codesign / notarytool
Cryptography
13- Ed25519
- secp256k1
- X25519
- ChaCha20-Poly1305
- AES-GCM
- PBKDF2
- HKDF
- Keccak-256
- HMAC
- ES256 JWT
- PKCS#8 / #12 / DER
- Certificate pinning
- Constant time comparison
Web
09- Next.js
- React
- Tailwind CSS
- Canvas 2D
- CSS 3D
- IntersectionObserver
- Web Push
- i18n
- Accessibility
Systems & infra
11- Node
- Vercel
- Postgres
- Caddy
- systemd
- Tor + pluggable transports
- IKEv2 / IPSec
- SearXNG
- OpenSSL
- GitHub Actions
- Playwright
Also
07- ONNX Runtime on-device inference
- Model Context Protocol
- BIP-32/39/44
- EIP-1559 / 191 / 712
- Threat modelling
- AGPL / GPL compliance
- Notarized distribution
Timeline
Almost all of this happened in about eight weeks. I am not sure that is a virtue, but it is the truth, so here it is.
June
JunApp Sandbox and the XPC migration land. Every process spawn and file write in the browser starts going through a hardened helper.
- 18 Jun
Keccak-256 and BIP-32 derivation bugs found. Every address the wallet had ever produced was wrong.
- 21 Jun
Source published. PolyForm Noncommercial.
- 23 Jun
Docker eliminated. SearXNG runs natively on an embedded, codesigned CPython.
- 27 Jun
Deployment floor lowered to macOS 15. XPC helper hardened with a runtime code signature requirement and a symlink resolving path allowlist.
- 30 Jun
iOS port begins. Scaffold to working native results page in a day.
July
2 JulAudit tail closed. Search history encrypted, wallet egress gated, ranking regression suite written. It caught a live bug while being written.
- 5 Jul
The WebRTC leak found and closed. Reader Mode and on-device translation ship.
- 6 Jul
Public launch at 0.9.5, notarized, with a signed update feed. Per-user VPN certificates go live the same day.
- 8 Jul
Integrated AI removed, about 10,000 lines deleted, and replaced with a local MCP server so your own model drives the browser instead of mine.
- 9 Jul
First iOS TestFlight build. AGPL compliance remediated across the bundled engine.
- 10 Jul
Bulwark 0.4.0 and 0.5.0 arrive, bringing ToolGuard and Rampart.
- 12 Jul
Support portal live, including a public governance board proved by wallet signature.
- 13 Jul
searxly.app rebuilt in Next.js and shipped.
- 16 Jul
1.0 released, discovered to launch only on my own Mac, fixed, and re-shipped and verified the same day.
- 18 Jul
Public iOS beta opens. The launch film and the no-LLM help assistant go to production.
- 19 Jul
TethrX published to npm.
- 21 Jul
Searxly 1.1 ships. This site goes live the same day.
- 23 Jul
Apple grants the restricted web browser entitlement for passkeys and hardware security keys.
- 25 Jul
TethrX 1.0 enters App Store review.
- 26 Jul
ScanRecords goes live. A daily public archive of what the messaging platforms say about reading your messages, and of the day each sentence changed.
- 28 Jul
The archive stops resting on a third party for who scans which service and reads the providers' own filings instead. Two of the four it had listed turned out to be wrong.
Elsewhere
No form, no newsletter, no analytics telling me you were here. No email and no phone number either, on purpose. These three are personal and they are the whole list: the products have their own channels, over on searxly.app.