Right traffic. Right route.
Iranian and private traffic stays on the local internet.
Everything else follows the Hiddify connection you already use.
Features · How it works · Architecture · Develop · FAQ
- Split routing — Iranian sites, Iranian IP ranges, and private/LAN traffic stay DIRECT. Everything else uses the Hiddify connection you already have.
- Connect, Pause, Resume, Disconnect — One operation at a time. The active button shows the real stage (Start Hiddify, Start Mihomo, and so on) with an in-button progress fill.
- Basic and Advanced — First launch opens Basic. Advanced adds component health, live traffic routes, and extra tools.
- Direct rules — Pin hosts to DIRECT or VPN in a sortable table with one-click route switching. Refresh the bundled Iran domain and IP lists from the BiFlow cloud snapshot.
- Live connections — One row per domain with a connection count, resolved IPs, route, and matched rule. Sort any column and send a host to the opposite route without leaving the table.
- Diagnostics — Test whether a host would go DIRECT or through the VPN, then move it. Export or clear the local
debug.log. Fresh Hiddify start repairs a blank Hiddify window without touching subscriptions. - DIRECT DNS presets — Fake-ip by default; Shecan, Electro, Radar, Mokhaberat, or custom resolvers are one Settings choice away for DIRECT domains. DIRECT domains always resolve to their real addresses.
- Browser-friendly routing — Clears a Hiddify-owned system proxy while connected so browsers actually use the split routing, and rejects VPN-bound QUIC so pages fall back to working TCP instead of hanging.
- Status bar — Internet reachability, public IP, approximate country, and lifetime sent/received totals.
- In-app install — Connect can install the privileged helper, Hiddify, and the bundled Mihomo build when they are missing.
- English and Persian — Built-in UI languages, with a tray menu for Connect/Disconnect, Pause/Resume, and Quit.
- Linux and Windows — Debian package, AppImage, portable
.exe, and NSIS setup. Signed AppImage and NSIS builds can update in-app. - Fits the window — Desktop sidebar, phone-sized bottom navigation, and a resizable window down to 390×640.
BiFlow is a desktop app for split routing. It keeps Iranian websites, Iranian IP ranges, and private/local networks DIRECT. Other destinations go through your existing Hiddify local proxy, using Mihomo as the split engine.
The window always runs as your normal user. Privileged work (TUN device, routes) stays in a small helper process with a strict command list. BiFlow does not replace Hiddify. It sits beside it and chooses the path for each destination.
English and Persian are built in. The dashboard reports exact helper, Hiddify, Mihomo, TUN, and DNS state; its status bar shows internet reachability, public IP, and approximate country. Mihomo and the full Iran rule snapshot ship inside the OS package, so their first use does not need a download. Hiddify remains an allowlisted official download when it is missing.
- Install BiFlow (Linux
.deb, or Windows app / NSIS setup). - Keep Hiddify installed and able to listen locally. BiFlow installs its bundled Mihomo build when needed.
- Open Direct rules if you want extra sites or IPs to stay DIRECT, or to refresh Iran domain and IP lists from the cloud.
- Press Connect. BiFlow prepares a routing generation, starts Mihomo, and asks the helper to attach the TUN and routes. Pause stops owned routing and Mihomo while leaving Hiddify running; Resume rebuilds the split stack. Disconnect tears owned state down and may also stop Hiddify when that setting is on.
- Iranian, private, and your custom rules stay DIRECT. Other traffic uses
Hiddify. The dashboard animates both routes while connected, and
Diagnostics can test a host and show DIRECT vs VPN before you rely on it.
Its support export includes the permanent, locally redacted
debug.log, which records Rust actions, warnings, errors, causes, initiators, and trace IDs for troubleshooting. Diagnostics shows its size and lets you reveal or delete it when you choose. - Disconnect tears the owned TUN and routes down. A failed start rolls back instead of leaving a half-applied network.
Cloud rule updates fetch the BiFlow-owned manifest, then the files from that
same snapshot. A failed refresh keeps the last good cache, or the snapshot
bundled with the app. Maintainers refresh the bundled snapshot with
./scripts/update-rules.sh (also pnpm rules:update); that command does not
commit or push.
flowchart LR
You[Your apps] --> BiFlow
BiFlow --> Decide{Match rules?}
Decide -->|Iran, private, or custom| Direct[DIRECT / local internet]
Decide -->|Everything else| Mihomo
Mihomo --> Hiddify[Hiddify local proxy]
Hiddify --> World[Rest of the internet]
BiFlow is a Tauri 2 desktop app: a React UI in a webview, a Rust engine in the same process, and a privileged helper in a separate process.
flowchart TB
UI[React UI<br/>Dashboard, rules, diagnostics, settings]
API[Typed desktop API]
Engine[Rust engine<br/>lifecycle, rules, Mihomo config]
Helper[Privileged helper<br/>TUN, routes, process control]
Mihomo[Mihomo split core]
Hiddify[Hiddify<br/>already running locally]
UI --> API --> Engine
Engine -->|framed, allowlisted IPC| Helper
Engine --> Mihomo
Mihomo --> Hiddify
Helper --> Net[TUN and routes]
| Piece | Role |
|---|---|
| UI | Basic or Advanced shell, Connect/Pause/Resume/Disconnect, install missing apps, cloud and custom DIRECT rules, flow tests, About/updates. No shell and no general filesystem access. |
| Engine | Owns configuration, rule decisions, Mihomo YAML, and rollback. Talks to the UI only through the typed API. |
| Helper | Applies TUN and routes. Accepts generation IDs and hashes, never executable paths, shell strings, or arbitrary URLs. |
| Mihomo | Enforces split routing. Controller binds to loopback with a generated secret. |
| Hiddify | Upstream proxy you already use. BiFlow does not log into it or replace it. |
| Rules | Bundled Iran lists, optional refresh from devlifeX/BiFlow, plus your extra DIRECT domains and IPs. |
Internal Rust crates still use the iran-split-* names. The product name, window
title, and install identifiers are BiFlow.
Prerequisites: Node.js 24+, pnpm 9.0.1, Rust 1.88. Linux desktop builds also need WebKitGTK 4.1 and GTK 3 development packages.
Optional workflow lint (do not install act on this machine):
# actionlint v1.7.7
go install github.com/rhysd/actionlint/cmd/actionlint@v1.7.7
actionlint./dev.sh # native Tauri app (UI talks to Rust)
./dev.sh web # browser UI with a safe mock backend
./dev.sh check # format, lint, typecheck, tests
./dev.sh e2e # Playwright primary flows against the mock UI./dev.sh and ./dev.sh desktop compile the real app and, on Linux, ask for
sudo to run a hardened transient helper for your developer UID. The helper
socket and runtime stay under /run/biflow-dev-<uid>; verified helper and
Mihomo binaries live under /var/lib/biflow-dev-<uid> because /run is
typically mounted noexec. Everything is stopped and removed when dev.sh
exits. Run the script as your normal account, not as root. ./dev.sh web never
touches TUN, routes, DNS, or system services.
Release packages:
./build.sh check-frontend # pnpm check and pnpm build
./build.sh check-rust iran-split-core # per-crate tests + Clippy
./build.sh ci-linux # GitHub-hosted native Linux packaging
./build.sh ci-windows # GitHub-hosted native Windows packaging
./build.sh linux # artifacts/linux/BiFlow_<version>_amd64.deb
./build.sh windows # artifacts/windows/BiFlow.exe and NSIS setup
./build.sh linux --from appimage # resume after a late AppImage failure
./build.sh linux --force # rebuild every Linux packaging stageDo not run ./build.sh all or ci-windows on a disk-constrained Linux
developer machine. Native packaging evidence comes from GitHub: tag v*
publishes, and Package dry-run (workflow_dispatch) uploads artifacts
without gh release.
./build.sh installs missing Node.js 24, pnpm, Rust, Linux desktop libraries,
NSIS, and cargo-xwin, then writes files under artifacts/. Version comes from
the root version file. Change that file only, then run pnpm version:sync.
pnpm test # UI unit tests
cargo test -p <crate> # tests for a crate you changed
pnpm test:e2e # Playwright
pnpm check # format, lint, typecheck, unit tests, version sync
cargo run -p iran-split-cli -- demoDeeper notes: helper IPC, architecture decisions, implementation roadmap.
Does BiFlow replace my VPN? No. It uses the Hiddify connection you already have. Iranian and private destinations skip that tunnel; other destinations still use it.
Do I have to install Hiddify and Mihomo myself? Mihomo is included in each OS package and installs locally. Hiddify is detected from common locations; if it is missing, BiFlow offers the official release and keeps a manual guide as fallback.
Will sites like Digikala go through the VPN? No, if they match the Iran domain or IP lists, or a custom DIRECT rule you added. Use Diagnostics → Test flow to confirm a host.
What if cloud rule update fails?
Routing keeps working. BiFlow keeps the last successful cache, or the lists
shipped with the app. Live refreshes come only from devlifeX/BiFlow.
How do updates install?
Signed AppImage and Windows NSIS builds can install in-app from GitHub
Releases. Debian .deb installs stay a download/open from the Release page.
Why is the Linux window blank?
WebKitGTK 2.44+ can paint an empty view on VMware and NVIDIA GPUs. Current
builds disable that renderer at startup and, on virtual machines, force
Mesa software GL. Closing the window leaves BiFlow in the tray: a new
AppImage or .deb of a different version starts its own process, but
the same version still activates the running instance. Quit from the tray
before testing a newly installed build of the same version.
To confirm on an older AppImage:
WEBKIT_DISABLE_DMABUF_RENDERER=1 WEBKIT_DISABLE_COMPOSITING_MODE=1 LIBGL_ALWAYS_SOFTWARE=1 ./BiFlow_*.AppImageIs the app window a root process? No. The UI runs as your user. Only the helper performs privileged network changes, over a versioned, size-limited, allowlisted local protocol.
Which platforms are supported?
Linux (Debian package and AppImage) and Windows (portable .exe and NSIS
installer). GitHub-hosted native jobs build those artifacts. Pushing a v*
tag publishes them together with signed updater metadata (latest.json).
AppImage and NSIS can self-update; .deb remains download/open.
Can I add my own DIRECT sites? Yes. Direct rules stores extra domains and IPs. They take precedence over the Iran lists.
Where does the version number come from?
The version file in the repository root. Installers, the UI, and Cargo
manifests follow that file after pnpm version:sync.



