GrabLine
Most download managers wire up their browser extension through a local HTTP server, which leaves a port open on your machine for as long as the app runs. I did not want to ship that, so GrabLine talks to the browser over Native Messaging instead.
- Type
- Desktop application
- State
- Active · v1.31.0
- Role
- Solo, end to end
- Python
- PySide6
- SQLite
- yt-dlp
- libtorrent
- FFmpeg
At a glance
- Six installers per release across Windows, macOS and Linux
- Signed Firefox extension on AMO
- No listen port: Native Messaging only, enforced in CI
What I owned
Solo project. I own the architecture, the segmented download engine, the PySide6 shell, the browser extension and native messaging host, and the release pipeline that produces six build artifacts across Windows, macOS and Linux.
Decisions, and what they cost
Native Messaging instead of a localhost listen port
The common pattern is a small HTTP server on 127.0.0.1 that the extension posts to. It is easy to build and behaves the same in every browser. It also means an open port on the user's machine, reachable by anything else running locally. GrabLine registers a native messaging host instead, so the browser starts the process and speaks to it over stdio. There is no socket to find.
How the browser reaches the app Usual approach (not used)
ExtensionHTTP on 127.0.0.1AppA port stays open, reachable by anything running locally.
GrabLine
BrowserNative Messaging, stdioGrabLineThe browser starts the host process. There is no socket to find.
What I gave upI gave up one-click, identical install across browsers. Native messaging hosts are registered per browser, per platform: Firefox is signed and distributed through AMO, while Chrome, Edge and Brave are paired through an in-app setup step. That friction is the cost of not opening a port.
Work-stealing segmentation over fixed equal splits
The naive way to parallelise a download is to cut the file into N equal ranges, one per connection. That works until one connection lands on a slow route and the whole download waits on its last few megabytes. In GrabLine a connection that finishes early steals the remaining range from the slowest one, so the tail gets narrower as the download progresses. Per-host speed buckets stop one site from starving the others.
What I gave upFar more bookkeeping. Every segment boundary and handoff is checkpointed to SQLite, so there are many more small writes than a fixed-split downloader needs. The payoff is that progress survives a hard kill: resume across power loss and VPN reconnects comes for free, because the checkpoint is always on disk.
FFmpeg fetched on demand rather than bundled
Bundling FFmpeg would make the installer self-contained but several times larger, and would tie every release to whatever FFmpeg version I happened to vendor. The app downloads it on first use when a job actually needs remuxing, and FFmpeg and Deno downloads are pinned by SHA-256 so a fetched binary is verified before it runs.
What I gave upThe installer stays small and FFmpeg updates independently, but first run is no longer fully offline. A user with no network on first launch cannot finish a job that needs remuxing.
Where it went wrong
A native messaging host that worked on my machine and nowhere else
The extension paired correctly on my development machine and silently failed on a clean install. No error surfaced in the browser; the download just never arrived in the app. The cause was the registry-based host registration: the manifest path that resolved on my machine did not resolve on a fresh install, so the browser had nothing to launch and reported nothing useful. I now test host registration on a clean profile rather than my own.
Known limitations
- No DRM circumvention. Netflix, Prime Video, Disney+ and Spotify tracks are refused explicitly rather than half-attempted.
- No login bypass. If a site needs an account to reach a file, GrabLine will not work around that.
- Builds are unsigned, so Windows and macOS warn once on first launch.
- First run needs a network connection if a job requires FFmpeg.
Where it stands
Actively maintained. v1.31.0 ships six artifacts: a Windows installer and portable zip, an Apple Silicon .dmg, a .deb, an AppImage and a Linux tarball, with SHA256SUMS. Beyond HTTP it handles magnets and torrent files through libtorrent, SFTP, FTP, S3 and WebDAV with OS keychain secrets, and a quality picker for video and audio on sites yt-dlp supports. CI refuses shell=True and enforces pinned dependencies.
