Releases: Leadaxe/singbox-launcher
Release list
release v1.4.2
Release v1.4.2
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v1.4.2):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.4.2The script will:
- Download the release archive
- Extract and install to
/Applications/ - Fix macOS quarantine attributes and permissions
- Launch the application automatically
Option 2: Manual Installation
- Download:
singbox-launcher-v1.4.2-macos.zip - Extract the ZIP file
- Remove quarantine attribute (required):
xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
- Double-click
singbox-launcher.appto run- If macOS blocks the app, go to System Settings → Privacy & Security and click "Open Anyway"
- Alternatively, right-click the app and select "Open" (first time only)
Windows (amd64)
- Download:
singbox-launcher-v1.4.2-win64.zip - Extract the ZIP file to a folder, for example:
C:\Program Files\singbox-launcher\ - Run
singbox-launcher.exefrom that folder- You may need administrator rights to install to Program Files
- The launcher will automatically download
sing-boxandwintun.dllon first launch
Windows 7 (x86, legacy)
- Download:
singbox-launcher-v1.4.2-win7-32.zip - Extract the ZIP file to a folder and run
singbox-launcher-win7-32.exe- For Windows 7 / 32-bit or legacy compatibility only
Linux Support
Checksums
See checksums.txt for SHA256 checksums of all files.
v1.4.2
EN
Highlights
- The window now opens over RDP and on GPU-less servers/VMs (issue #105). The launcher UI needs OpenGL 2.1+, but an RDP session on Windows Server without a GPU only provides the "GDI Generic" OpenGL 1.1 — the window silently failed to render while the tray stayed alive. On Windows the launcher now probes the OpenGL version before starting the UI; when hardware OpenGL 2.1 is missing, a native dialog offers to download the Mesa3D (llvmpipe) software renderer (~24 MB) from this repository's
mesa3d-26.2.0release (ghproxy fallback for networks where GitHub is blocked). The DLLs are extracted next tosingbox-launcher.exeand the window renders immediately — no restart needed. On subsequent starts the Windows loader picks the localopengl32.dllby itself and the probe is skipped. Manual install stays possible for offline servers — seedocs/RDP_OPENGL.md. - Rollback: delete
opengl32.dll,libgallium_wgl.dll,dxil.dllfrom the launcher folder. Escape hatches:SINGBOX_LAUNCHER_NO_MESA=1disables the probe entirely,SINGBOX_LAUNCHER_FORCE_MESA=1forces the offer (debugging aid).
Technical / Internal
- Internal
-gl-probeflag: the launcher re-runs itself to measure the WGL version in a subprocess, so the parent process never loads the systemopengl32.dlland can preload Mesa by full path (the Windows loader then reuses the module by base name for GLFW'sLoadLibrary("opengl32.dll")). The gate runs before the first Fyne window is created. - Win7 32-bit build: no auto-install (modern Mesa needs Windows 10+) — a native dialog points to the manual
docs/WIN7_OPENGL.mdguide instead. - Docs:
docs/DAEMON_AND_REMOTE(.ru).mdcaught up with SPEC 100 (Remote in Debug API: stateless addressing, deploy parity, snapshot streams, raw passthrough,/daemon/*, capabilities manifest) and the 1.4.1 Remote-tab fixes (Restart ↻, node-list self-healing, resilient gRPC streams).
RU
Основное
- Окно теперь открывается по RDP и на серверах/ВМ без GPU (issue #105). UI лаунчера нужен OpenGL 2.1+, а RDP-сессия на Windows Server без GPU отдаёт только «GDI Generic» OpenGL 1.1 — окно молча не отрисовывалось, живым оставался лишь трей. Теперь на Windows лаунчер проверяет версию OpenGL до старта UI; если аппаратного 2.1 нет, нативный диалог предлагает скачать программный рендерер Mesa3D (llvmpipe, ~24 МБ) с релиза
mesa3d-26.2.0этого репозитория (фолбэк через ghproxy для сетей, где GitHub заблокирован). DLL распаковываются рядом сsingbox-launcher.exe, окно отрисовывается сразу — перезапуск не нужен. На следующих стартах локальныйopengl32.dllподхватывает сам загрузчик Windows, проверка пропускается. Ручная установка остаётся для серверов без интернета — см.docs/RDP_OPENGL.ru.md. - Откат: удалить
opengl32.dll,libgallium_wgl.dll,dxil.dllиз папки лаунчера. Служебные переменные:SINGBOX_LAUNCHER_NO_MESA=1полностью отключает проверку,SINGBOX_LAUNCHER_FORCE_MESA=1принудительно предлагает установку (для отладки).
Техническое / Внутреннее
- Служебный флаг
-gl-probe: лаунчер перезапускает сам себя и меряет WGL-версию в подпроцессе — родительский процесс не грузит системныйopengl32.dllи может подгрузить Mesa по полному пути (дальше загрузчик Windows переиспользует модуль по базовому имени для GLFW-шногоLoadLibrary("opengl32.dll")). Гейт отрабатывает до создания первого окна Fyne. - Win7 32-bit сборка: автозагрузки нет (современной Mesa нужна Windows 10+) — вместо этого нативный диалог со ссылкой на ручную инструкцию
docs/WIN7_OPENGL.ru.md. - Docs:
docs/DAEMON_AND_REMOTE(.ru).mdдогнал SPEC 100 (Remote в Debug API: stateless-адресация, паритет деплоя, снапшот-стримы, raw passthrough,/daemon/*, манифест capabilities) и фиксы вкладки Remote из 1.4.1 (Restart ↻, самолечение списка узлов, живучие gRPC-подписки).
release v1.4.1
Release v1.4.1
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v1.4.1):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.4.1The script will:
- Download the release archive
- Extract and install to
/Applications/ - Fix macOS quarantine attributes and permissions
- Launch the application automatically
Option 2: Manual Installation
- Download:
singbox-launcher-v1.4.1-macos.zip - Extract the ZIP file
- Remove quarantine attribute (required):
xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
- Double-click
singbox-launcher.appto run- If macOS blocks the app, go to System Settings → Privacy & Security and click "Open Anyway"
- Alternatively, right-click the app and select "Open" (first time only)
Windows (amd64)
- Download:
singbox-launcher-v1.4.1-win64.zip - Extract the ZIP file to a folder, for example:
C:\Program Files\singbox-launcher\ - Run
singbox-launcher.exefrom that folder- You may need administrator rights to install to Program Files
- The launcher will automatically download
sing-boxandwintun.dllon first launch
Windows 7 (x86, legacy)
- Download:
singbox-launcher-v1.4.1-win7-32.zip - Extract the ZIP file to a folder and run
singbox-launcher-win7-32.exe- For Windows 7 / 32-bit or legacy compatibility only
Linux Support
Checksums
See checksums.txt for SHA256 checksums of all files.
v1.4.1
EN
Highlights
- Debug API now covers the whole remote-machines feature set (SPEC 100): pair/re-pair/remove machines, health, start/stop/rollback of the machine's core, deploy (resources + config in one call), per-machine wizard state mirrors (
/remote/machines/{id}/state/*), observability (proxies, switch, url-test, pool, rules, connections, DNS/log windows, host telemetry, LAN clients), and the machine's resource store. - Debug API: local lxd-daemon group
/daemon/*(macOS) — status, pair/unpair, address/secret, engine switch (classic|daemon), and ready-to-run sudo commands (the API never executes them). - Debug API: raw passthrough to any paired daemon —
POST …/raw/rest(arbitrary admin-REST call) andPOST …/raw/grpc(arbitrarydaemon.*gRPC call resolved via protoregistry; unary + server-stream windows), plusGET /grpc/methodsdiscovery. The tunnel only reaches the paired daemon's control channel — it is not an open proxy. - Debug API manifest (
GET /) now carriescapabilities(remote/daemon/raw_grpc) so agents know up front which groups this build exposes. - Debug API: UI remote-override control —
GET /remote/ui,POST /remote/machines/{id}/ui/connect,POST /remote/ui/disconnectdo exactly what the Remote tab's Connect/Disconnect buttons do (switch the Servers tab to a machine and back). Health-gated;503when the launcher runs headless. - Detour through a single server (SPEC 101): the Source dialog's "Detour server" picker now offers other single-server sources (marked
») alongside groups. The hop is referenced by node identity hash, so it survives renames/prefixes; if the hop disappears, the dependent source's nodes are dropped from the config (fail-closed) instead of silently dialing direct. WireGuard endpoints can now be chained too (detour is applied to them; onlylisten_portendpoints stay direct — the core rejects that combination). - WireGuard share-URI/.conf keys (private/public/preshared) are validated at parse time: non-32-byte/non-base64 values (e.g. Proton's masked
*****placeholder) degrade that node with a warning instead of emitting a config that failssing-box checkwholesale; URL-safe/unpadded key variants are normalized to the std form the core requires. - Node identity hashes for WireGuard nodes now cover the full endpoint (keys, addresses): previously all WG nodes on one server:port collapsed into one identity, so a per-node disable mark covered all of them. Existing disable marks on WG nodes reset once.
Fixed
- Renaming a template-derived outbound group no longer breaks the config: on save the entry is materialized as a standalone one, and already-orphaned template references are dropped from the build with a warning instead of emitting an empty-type outbound that failed the whole config (
unknown outbound type: ""). - A dangling node/endpoint detour (its target group renamed or removed) is stripped at final assembly with a warning instead of failing the whole deploy with
dependency not found. - Traffic profiler shows the connection path as two labeled lines —
Outbound:(selection chain, root→leaf) andVia:(transport/detour tail in packet hop order) — instead of one garbled merged chain; per-client grouping now uses the true root outbound. - Remote machine gRPC subscriptions (connections, DNS, status, group selection) survive Deploy/Start/Stop: streams resubscribe automatically instead of dying silently until Disconnect/Connect.
- The server list recovers on its own after the machine's core restarts: the selected group is re-asserted and the auto-refresh tick re-reads the machine's groups — no more permanent "Reading the machine's selector groups…".
- Remote tab: protocol/transport subtitles are resolved against the connected machine's own config — nodes that exist only on that machine (its endpoints, its local sources) show their subtitle again.
- Machine row: new Restart button (↻) — Stop + Start with a single confirmation.
- Config Wizard, Outbounds tab: mouse-wheel scrolling works over the outbounds list.
Technical / Internal
- Deploy chain (resources-before-config) extracted from
ui/machine_list_panel.gointoservices.(*RemoteRegistry).Deploy— UI and API call the same function. services.TransportPool: cached per-machine gRPC transports for the API (lazy dial, 90s idle close, invalidation on remove/re-pair/addr change).lxdclient.(*Client).Do: raw admin-REST passthrough primitive.- debugapi
Serverbuilds its router atStart()(notNew()), so optional endpoint groups registered in between land in routing and/help. runResilientStream(lxd remote transport): shared resubscribe-with-backoff loop for all machine gRPC streams.- Parsed-config cache for server-list subtitles is per-path — the Local and Remote panels no longer evict each other's cache on every row redraw.
RU
Основное
- Debug API покрывает весь remote-функционал (SPEC 100): сопряжение/пере-сопряжение/удаление машин, health, start/stop/rollback ядра машины, deploy (ресурсы + конфиг одним вызовом), зеркала состояния визарда per-machine (
/remote/machines/{id}/state/*), наблюдаемость (узлы, переключение, url-test, пул, правила, соединения, окна DNS/лога, телеметрия хоста, клиенты сети) и ресурс-стор машины. - Debug API: группа локального демона
/daemon/*(macOS) — статус, pair/unpair, адрес/секрет, переключение движка (classic|daemon) и готовые sudo-команды (API их не исполняет). - Debug API: произвольные вызовы к сопряжённому демону —
POST …/raw/rest(любой admin-REST запрос) иPOST …/raw/grpc(любойdaemon.*gRPC-метод через protoregistry; unary + окна server-stream), плюс discoveryGET /grpc/methods. Туннель ведёт только на управляющий канал сопряжённого демона — это не открытый прокси. - Манифест Debug API (
GET /) несётcapabilities(remote/daemon/raw_grpc) — агент заранее видит, какие группы есть в этой сборке. - Debug API: управление remote-override UI —
GET /remote/ui,POST /remote/machines/{id}/ui/connect,POST /remote/ui/disconnectделают ровно то же, что кнопки Connect/Disconnect вкладки Remote (переводят вкладку Servers на машину и обратно). С health-гейтом;503при headless-запуске. - Detour через одиночный сервер (SPEC 101): пикер «Detour server» в диалоге источника теперь предлагает и другие server-источники (с маркером
»), не только группы. Хоп адресуется identity-хешем узла — переживает переименования и префиксы; если хоп пропал, ноды зависимого источника выкидываются из конфига (fail-closed), а не уходят молча напрямую. WireGuard-endpoint'ы теперь тоже можно пускать цепочкой (detour к ним применяется; напрямую остаются только endpoints сlisten_port— ядро отвергает эту комбинацию). - Ключи WireGuard из share-URI/.conf (private/public/preshared) валидируются при парсинге: значение не из 32 байт base64 (например, маскированный
*****у Proton) деградирует только эту ноду с warning, а не валит весьsing-box check; URL-safe/беспаддинговые варианты нормализуются в std-форму, которую требует ядро. - Identity-хеш WireGuard-узлов теперь считается от полного endpoint (ключи, адреса): раньше все WG-ноды одного server:port схлопывались в одну идентичность, и отметка «выключить ноду» накрывала их все. Существующие отметки на WG-нодах сбросятся один раз.
Исправлено
- Переименование группы, взятой из шаблона, больше не ломает конфиг: при сохранении запись материализуется в самостоятельную, а уже осиротевшие ссылки на шаблон дропаются при сборке с warning — вместо outbound'а с пустым type, валившего весь конфиг (
unknown outbound type: ""). - Висячий detour ноды/endpoint'а (целевую группу переименовали или удалили) зачищается при финальной сборке с warning — вместо отказа всего деплоя с
dependency not found. - Профайлер трафика показывает путь соединения двумя подписанными строками —
Outbound:(цепочка выбора, корень→лист) иVia:(транспортный хвост в порядке следования пакета) — вместо одной перемешанной цепочки; группировка by-client берёт честный корневой outbound. - gRPC-подписки удалённой машины (соединения, DNS, статус, выбор группы) переживают Deploy/Start/Stop: стримы перепо...
Mesa3D 26.2.0 (llvmpipe) — software OpenGL for Windows
Зеркало Mesa3D 26.2.0 (llvmpipe, MSVC x64) из mesa-dist-win для автоустановки программного OpenGL-рендерера лаунчером (issue #105: пустое окно в RDP-сессии / на сервере без GPU).
Содержимое mesa3d-26.2.0-win64.zip: opengl32.dll, libgallium_wgl.dll, dxil.dll из каталога x64/ оригинального архива mesa3d-26.2.0-release-msvc.7z. Лицензия Mesa — MIT.
Не устанавливайте вручную, если аппаратный OpenGL работает: лаунчер сам предложит установку, когда обнаружит OpenGL < 2.1.
release v1.4.0
Release v1.4.0
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v1.4.0):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.4.0The script will:
- Download the release archive
- Extract and install to
/Applications/ - Fix macOS quarantine attributes and permissions
- Launch the application automatically
Option 2: Manual Installation
- Download:
singbox-launcher-v1.4.0-macos.zip - Extract the ZIP file
- Remove quarantine attribute (required):
xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
- Double-click
singbox-launcher.appto run- If macOS blocks the app, go to System Settings → Privacy & Security and click "Open Anyway"
- Alternatively, right-click the app and select "Open" (first time only)
Windows (amd64)
- Download:
singbox-launcher-v1.4.0-win64.zip - Extract the ZIP file to a folder, for example:
C:\Program Files\singbox-launcher\ - Run
singbox-launcher.exefrom that folder- You may need administrator rights to install to Program Files
- The launcher will automatically download
sing-boxandwintun.dllon first launch
Windows 7 (x86, legacy)
- Download:
singbox-launcher-v1.4.0-win7-32.zip - Extract the ZIP file to a folder and run
singbox-launcher-win7-32.exe- For Windows 7 / 32-bit or legacy compatibility only
Linux Support
Checksums
See checksums.txt for SHA256 checksums of all files.
v1.4.0
EN
Highlights
-
Every remote machine now has its own config. Until now a single profile was shared by all of them: one wizard state, one built config. Configuring a second machine silently overwrote the first, and Deploy sent whichever config happened to be written last — a router could receive a config built for a VPS. Each machine now owns a directory holding its wizard state, snapshots, built
config.json, rule sets and subscription bodies, so machines can't overwrite or delete each other's files. Existing setups migrate automatically when exactly one machine is paired; with several paired the old files are left untouched and a warning is logged, because there is no way to tell whose they were. -
Machine management moved into one place: the new Local and Remote tabs. They replace Core and Servers and share one layout — proxy list on the left, management on the right. Local pairs the proxy list with your own core's controls; Remote pairs it with the list of machines, each row showing name, platform, address and core status, with Configure / Start-Stop / Deploy / edit / remove right there. Previously this was scattered across three screens (the Servers header, the connection window, the wizard), and none of them showed a machine as a whole.
-
Picking a machine and choosing what to build for are no longer separate switches. Configure on a machine's row opens the wizard rooted on that machine's profile, and Deploy on the same row sends that machine's own config — so "built for one, deployed to another" is impossible by construction rather than by validation. A machine's platform and architecture now belong to its registry entry (edit them in its row), which is also what the config is built for.
-
The main window now opens at 1000×700 and won't shrink below it. Both tabs are two-column, and below that size the columns stop fitting and labels get cut off. It can still be stretched.
-
Daemon mode for the core (macOS). The launcher can now run the VPN core inside a long-lived system service (
sing-box lxd) instead of spawningsing-box runitself — the same in-process, reload-surviving model the Android app uses. Configure it in the new connection settings window: Servers → ⚙ → Local (the Remote tab keeps the SPEC 064 remote Clash override). What it buys you:- Sudo once, in your own Terminal. Installing the service is a single command the launcher prepares for you (copy or open in Terminal — full launchctl output, your own sudo; the launcher itself never runs anything privileged). After that, starting/stopping the VPN and applying config changes need no password at all.
- Quitting the launcher can keep the VPN up. By default, closing the launcher leaves the core running in the daemon; a "Stop VPN when quitting" toggle restores the classic behavior.
- In-process config swaps. Applying a new config no longer kills and restarts a process: the daemon swaps the core in-place, validates the config in a subprocess before touching the running instance, and auto-rolls-back to the last working config if the new one fails to start.
- Richer observability over gRPC. Proxy groups, node selection, latency tests, live status/traffic, connections, and core logs all flow over the daemon's gRPC channel (the CommandClient protocol shared with the Android line) — including a new balancer pool view on the Servers tab showing each urltest slot and its delay.
- Pairing. The launcher pairs with the daemon over mTLS using a one-time invite (
address#fingerprint#code). The install command prints one at the end — paste it into the pairing field; mint a fresh one any time withsudo sing-box lxd client add(works for remote daemons too). The daemon fully owns its home directory and credentials (daemon.jsonwith the listen address and admin secret lives in its state dir, reported overGET /admin/info); the launcher keeps only its own client keypair — a trusted client certificate is the whole credential.
The classic engine remains the default and is unchanged; daemon mode is opt-in and requires a core build with the
lxdsubcommand (shipped by the pinned1.14.0-lx.26). -
Host telemetry for a remote machine. A machine's row now opens a Host window next to its traffic profiler: CPU and load, memory with swap, temperature, file descriptors, disks and interfaces, read from the daemon's
/admin/host. The profiler answers "what is the core doing"; this answers "is the box itself in trouble" — a core can be perfectly healthy while one CPU sits pinned, the overlay is full, and the board is thermally throttling. A missing value shows a dash rather than a zero: zero in these numbers is an assertion, and substituting it for "we don't know" would lie exactly where someone is looking for a diagnosis. Read-only filesystems (a squashfs image packed to fit its data) are marked as intentional instead of being drawn as a bar pinned at 100% — a full bar is the language of an emergency that isn't happening here. -
A broken pairing can be repaired without losing the machine's setup. When the channel breaks on the machine's side — the daemon was reinstalled, its state directory wiped, this client revoked, or its server certificate changed so the pin no longer matches — the only cure used to be "remove the machine and pair it again", and the registry entry took everything with it: wizard state, snapshots, the built config, rule sets and subscription bodies. Re-pair in the machine's edit window swaps the pin, the client key and (optionally) the address, keeping the ID — and therefore the machine's directory and everything in it. The key is re-issued rather than reused: the old one may have been revoked on the far side, in which case enrolling with it would succeed while mTLS work still failed, leaving you "paired but not connecting".
-
Settings can be copied from another machine. A second router rarely needs a setup built from scratch — Copy settings from another machine carries the wizard setup (sources, rules, DNS, variables) across. Pairing is not copied: each machine keeps its own client key, because one shared key would mean revoking access on one machine revokes it on both. The built config and rule-set files are rebuilt for the receiving machine on its next Save and Deploy.
-
Editing a machine now opens a window rather than a modal dialog. Two actions with their own inputs and statuses joined the four fields, and a tall modal popup in Fyne balloons to fill the screen.
Fixed
- "Copy server link" works for WireGuard and AmneziaWG nodes. Since sing-box 1.11 those live in
endpoints[]rather thanoutbounds[], and the lookup only ever searchedoutbounds[]— so every WireGuard node answered withoutbound with tag ... not found. A miss inoutbounds[]now falls through toendpoints[]; a miss in both is still an error rather than a silent empty string. - A machine's settings no longer escape into the shared folder.
TargetSpecdropped the machine ID and its directories on three paths — restoring state from file, switching the target platform, and toggling local⇄remote — so the first Save after any of them wrote into the singletonbin/wizard_states/remote/instead of the machine's own profile. The ID travels with the open wizard (it is a property of the registry entry, deliberately not written into the state file, which is what makes copying a profile between machines safe). - Only the genuinely connected machine shows Disconnect and Deploy. There is a single transport in
APIService, so exactly one machine can be connected — but a row whose channel had been taken over by a neighbour kept showing its own status and buttons, and those buttons spoke over the other machine's channel. Deploy would then send a config to a machine other than the one named in the row. Connecting a machine now tears down the previous one in the UI too, closing its profiler and host windows while its transport is still alive. - Connecting a remote machine no longer breaks the Local tab. Pairing over lxd sets a global override, but the Clash-co...
prerelease v1.3.1-52-gb97f13e-prerelease
Release v1.3.1-52-gb97f13e-prerelease
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v1.3.1-52-gb97f13e-prerelease):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.3.1-52-gb97f13e-prereleaseThe script will:
- Download the release archive
- Extract and install to
/Applications/ - Fix macOS quarantine attributes and permissions
- Launch the application automatically
Option 2: Manual Installation
- Download:
singbox-launcher-v1.3.1-52-gb97f13e-prerelease-macos.zip - Extract the ZIP file
- Remove quarantine attribute (required):
xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
- Double-click
singbox-launcher.appto run- If macOS blocks the app, go to System Settings → Privacy & Security and click "Open Anyway"
- Alternatively, right-click the app and select "Open" (first time only)
Windows (amd64)
- Download:
singbox-launcher-v1.3.1-52-gb97f13e-prerelease-win64.zip - Extract the ZIP file to a folder, for example:
C:\Program Files\singbox-launcher\ - Run
singbox-launcher.exefrom that folder- You may need administrator rights to install to Program Files
- The launcher will automatically download
sing-boxandwintun.dllon first launch
Windows 7 (x86, legacy)
- Download:
singbox-launcher-v1.3.1-52-gb97f13e-prerelease-win7-32.zip - Extract the ZIP file to a folder and run
singbox-launcher-win7-32.exe- For Windows 7 / 32-bit or legacy compatibility only
Linux Support
Checksums
See checksums.txt for SHA256 checksums of all files.
⚠️ Pre-release build offv1.3.1-52-gb97f13e-prerelease— for testing only, not for production. Use the latest stable release on the Releases page if you are not sure.
Upcoming release — черновик
Сюда складываем пункты, которые войдут в следующий релиз. Перед релизом переносим в X-Y-Z.md и очищаем этот файл.
Не добавлять сюда мелкие правки только UI (порядок виджетов, выравнивание, стиль кнопок без смены действия и т.п.). Писать новое поведение: данные, форматы, сохранение, заметные для пользователя возможности.
EN
Highlights
-
Every remote machine now has its own config. Until now a single profile was shared by all of them: one wizard state, one built config. Configuring a second machine silently overwrote the first, and Deploy sent whichever config happened to be written last — a router could receive a config built for a VPS. Each machine now owns a directory holding its wizard state, snapshots, built
config.json, rule sets and subscription bodies, so machines can't overwrite or delete each other's files. Existing setups migrate automatically when exactly one machine is paired; with several paired the old files are left untouched and a warning is logged, because there is no way to tell whose they were. -
Machine management moved into one place: the new Local and Remote tabs. They replace Core and Servers and share one layout — proxy list on the left, management on the right. Local pairs the proxy list with your own core's controls; Remote pairs it with the list of machines, each row showing name, platform, address and core status, with Configure / Start-Stop / Deploy / edit / remove right there. Previously this was scattered across three screens (the Servers header, the connection window, the wizard), and none of them showed a machine as a whole.
-
Picking a machine and choosing what to build for are no longer separate switches. Configure on a machine's row opens the wizard rooted on that machine's profile, and Deploy on the same row sends that machine's own config — so "built for one, deployed to another" is impossible by construction rather than by validation. A machine's platform and architecture now belong to its registry entry (edit them in its row), which is also what the config is built for.
-
The main window now opens at 1000×700 and won't shrink below it. Both tabs are two-column, and below that size the columns stop fitting and labels get cut off. It can still be stretched.
-
Daemon mode for the core (macOS). The launcher can now run the VPN core inside a long-lived system service (
sing-box lxd) instead of spawningsing-box runitself — the same in-process, reload-surviving model the Android app uses. Configure it in the new connection settings window: Servers → ⚙ → Local (the Remote tab keeps the SPEC 064 remote Clash override). What it buys you:- Sudo once, in your own Terminal. Installing the service is a single command the launcher prepares for you (copy or open in Terminal — full launchctl output, your own sudo; the launcher itself never runs anything privileged). After that, starting/stopping the VPN and applying config changes need no password at all.
- Quitting the launcher can keep the VPN up. By default, closing the launcher leaves the core running in the daemon; a "Stop VPN when quitting" toggle restores the classic behavior.
- In-process config swaps. Applying a new config no longer kills and restarts a process: the daemon swaps the core in-place, validates the config in a subprocess before touching the running instance, and auto-rolls-back to the last working config if the new one fails to start.
- Richer observability over gRPC. Proxy groups, node selection, latency tests, live status/traffic, connections, and core logs all flow over the daemon's gRPC channel (the CommandClient protocol shared with the Android line) — including a new balancer pool view on the Servers tab showing each urltest slot and its delay.
- Pairing. The launcher pairs with the daemon over mTLS using a one-time invite (
address#fingerprint#code). The install command prints one at the end — paste it into the pairing field; mint a fresh one any time withsudo sing-box lxd client add(works for remote daemons too). The daemon fully owns its home directory and credentials (daemon.jsonwith the listen address and admin secret lives in its state dir, reported overGET /admin/info); the launcher keeps only its own client keypair — a trusted client certificate is the whole credential.
The classic engine remains the default and is unchanged; daemon mode is opt-in and requires a core build with the
lxdsubcommand (sing-box-lx 1.14.0-lx.23 or newer).
Fixed
- Quit from the tray actually terminates the process. Quitting via the tray menu (or the Exit button) with the main window hidden or unfocused left the process alive: on Windows the tray icon stayed behind as a ghost, and relaunching the
.exereported "already running" because the dead-looking process still held the single-instance lock. Root cause is in Fyne's glfw driver:Quit()runs its tray teardown only when one of our windows currently holds focus — exactly the opposite of the quit-from-tray situation. The launcher now tears the tray icon down explicitly (systray.Quit(), the same call the driver skips: on Windows it deletes the notification-area icon immediately and stops the systray message pump), and a shutdown watchdog force-exits the process within 3 seconds if the Fyne event loop still refuses to unwind — by that point sing-box is already stopped and log files are closed, so nothing is lost.
Technical / Internal
GracefulExitis now idempotent (sync.Once): it is reachable both from the tray/Exit button and frommain()afterapp.Run()returns, and used to run the whole teardown twice.fyne.io/systraypromoted from indirect to direct dependency ingo.win7.mod(v1.12.0, version unchanged);go.modalready had it direct (v1.12.2).- Core engine abstraction (
CoreBackend). The UI, tray, shortcuts, and debug-API no longer call the process manager or Clash API directly; everything routes through the active backend (LegacyBackend= classic spawn,DaemonBackend= lxd). Proxy-group operations go through aProxyTransportseam (Clash HTTP for classic, gRPC for daemon), so the Servers tab is engine-agnostic. Daemon mode addsgoogle.golang.org/grpc+protobuf(darwin-only build tags — the win7 build is untouched); the daemon protobuf stubs are vendored from the fork viascripts/sync_daemonpb.sh. - Daemon mode requires a core built with
with_lx_command(thelxdsubcommand).RequiredCoreVersionmust be bumped to a fork release that ships it (1.14.0-lx.23+) before the feature is usable by end users; until then it is developed against a locally built core. - Cleanup pass over the SPEC 094–099 code. Dead code removed (
pickMainXrayVLESS,xrayBuildJumpFromOutbound,containsStringValue,activateDaemonEngineIfPossible— all orphaned by their own refactors). Copy-to-clipboard unified: oneNewCopyButtonreplaces three drifting copies of the "icon turns into a checkmark" feedback, andfynewidget.SetClipboardreplaces the deprecated per-windowWindow.Clipboard()across both UI packages. Deploy's resource collection moved out of the machine-list panel intoservices.CollectDeployResources(no widgets in it — it now has unit tests, which the GUI-excludeduipackage could not have).ProcessBaseis shared instead of duplicated in the machine profiler. ui/componentsno longer drags incore.ClickRedirect— the only widget there that needed app state — took the whole*core.AppControllerjust to focus the wizard window, and through the shared widget package that dependency reached every file importing the gutter helpers from it (20+, acrossui,ui/configurator/*andui/traffic). It now takes*uiservice.UIService, a leaf package. `ui/traf...
prerelease v1.3.1-50-g47f3dbf-prerelease
Release v1.3.1-50-g47f3dbf-prerelease
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v1.3.1-50-g47f3dbf-prerelease):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.3.1-50-g47f3dbf-prereleaseThe script will:
- Download the release archive
- Extract and install to
/Applications/ - Fix macOS quarantine attributes and permissions
- Launch the application automatically
Option 2: Manual Installation
- Download:
singbox-launcher-v1.3.1-50-g47f3dbf-prerelease-macos.zip - Extract the ZIP file
- Remove quarantine attribute (required):
xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
- Double-click
singbox-launcher.appto run- If macOS blocks the app, go to System Settings → Privacy & Security and click "Open Anyway"
- Alternatively, right-click the app and select "Open" (first time only)
Windows (amd64)
- Download:
singbox-launcher-v1.3.1-50-g47f3dbf-prerelease-win64.zip - Extract the ZIP file to a folder, for example:
C:\Program Files\singbox-launcher\ - Run
singbox-launcher.exefrom that folder- You may need administrator rights to install to Program Files
- The launcher will automatically download
sing-boxandwintun.dllon first launch
Windows 7 (x86, legacy)
- Download:
singbox-launcher-v1.3.1-50-g47f3dbf-prerelease-win7-32.zip - Extract the ZIP file to a folder and run
singbox-launcher-win7-32.exe- For Windows 7 / 32-bit or legacy compatibility only
Linux Support
Checksums
See checksums.txt for SHA256 checksums of all files.
⚠️ Pre-release build offv1.3.1-50-g47f3dbf-prerelease— for testing only, not for production. Use the latest stable release on the Releases page if you are not sure.
Upcoming release — черновик
Сюда складываем пункты, которые войдут в следующий релиз. Перед релизом переносим в X-Y-Z.md и очищаем этот файл.
Не добавлять сюда мелкие правки только UI (порядок виджетов, выравнивание, стиль кнопок без смены действия и т.п.). Писать новое поведение: данные, форматы, сохранение, заметные для пользователя возможности.
EN
Highlights
-
Every remote machine now has its own config. Until now a single profile was shared by all of them: one wizard state, one built config. Configuring a second machine silently overwrote the first, and Deploy sent whichever config happened to be written last — a router could receive a config built for a VPS. Each machine now owns a directory holding its wizard state, snapshots, built
config.json, rule sets and subscription bodies, so machines can't overwrite or delete each other's files. Existing setups migrate automatically when exactly one machine is paired; with several paired the old files are left untouched and a warning is logged, because there is no way to tell whose they were. -
Machine management moved into one place: the new Local and Remote tabs. They replace Core and Servers and share one layout — proxy list on the left, management on the right. Local pairs the proxy list with your own core's controls; Remote pairs it with the list of machines, each row showing name, platform, address and core status, with Configure / Start-Stop / Deploy / edit / remove right there. Previously this was scattered across three screens (the Servers header, the connection window, the wizard), and none of them showed a machine as a whole.
-
Picking a machine and choosing what to build for are no longer separate switches. Configure on a machine's row opens the wizard rooted on that machine's profile, and Deploy on the same row sends that machine's own config — so "built for one, deployed to another" is impossible by construction rather than by validation. A machine's platform and architecture now belong to its registry entry (edit them in its row), which is also what the config is built for.
-
The main window now opens at 1000×700 and won't shrink below it. Both tabs are two-column, and below that size the columns stop fitting and labels get cut off. It can still be stretched.
-
Daemon mode for the core (macOS). The launcher can now run the VPN core inside a long-lived system service (
sing-box lxd) instead of spawningsing-box runitself — the same in-process, reload-surviving model the Android app uses. Configure it in the new connection settings window: Servers → ⚙ → Local (the Remote tab keeps the SPEC 064 remote Clash override). What it buys you:- Sudo once, in your own Terminal. Installing the service is a single command the launcher prepares for you (copy or open in Terminal — full launchctl output, your own sudo; the launcher itself never runs anything privileged). After that, starting/stopping the VPN and applying config changes need no password at all.
- Quitting the launcher can keep the VPN up. By default, closing the launcher leaves the core running in the daemon; a "Stop VPN when quitting" toggle restores the classic behavior.
- In-process config swaps. Applying a new config no longer kills and restarts a process: the daemon swaps the core in-place, validates the config in a subprocess before touching the running instance, and auto-rolls-back to the last working config if the new one fails to start.
- Richer observability over gRPC. Proxy groups, node selection, latency tests, live status/traffic, connections, and core logs all flow over the daemon's gRPC channel (the CommandClient protocol shared with the Android line) — including a new balancer pool view on the Servers tab showing each urltest slot and its delay.
- Pairing. The launcher pairs with the daemon over mTLS using a one-time invite (
address#fingerprint#code). The install command prints one at the end — paste it into the pairing field; mint a fresh one any time withsudo sing-box lxd client add(works for remote daemons too). The daemon fully owns its home directory and credentials (daemon.jsonwith the listen address and admin secret lives in its state dir, reported overGET /admin/info); the launcher keeps only its own client keypair — a trusted client certificate is the whole credential.
The classic engine remains the default and is unchanged; daemon mode is opt-in and requires a core build with the
lxdsubcommand (sing-box-lx 1.14.0-lx.23 or newer).
Fixed
- Quit from the tray actually terminates the process. Quitting via the tray menu (or the Exit button) with the main window hidden or unfocused left the process alive: on Windows the tray icon stayed behind as a ghost, and relaunching the
.exereported "already running" because the dead-looking process still held the single-instance lock. Root cause is in Fyne's glfw driver:Quit()runs its tray teardown only when one of our windows currently holds focus — exactly the opposite of the quit-from-tray situation. The launcher now tears the tray icon down explicitly (systray.Quit(), the same call the driver skips: on Windows it deletes the notification-area icon immediately and stops the systray message pump), and a shutdown watchdog force-exits the process within 3 seconds if the Fyne event loop still refuses to unwind — by that point sing-box is already stopped and log files are closed, so nothing is lost.
Technical / Internal
GracefulExitis now idempotent (sync.Once): it is reachable both from the tray/Exit button and frommain()afterapp.Run()returns, and used to run the whole teardown twice.fyne.io/systraypromoted from indirect to direct dependency ingo.win7.mod(v1.12.0, version unchanged);go.modalready had it direct (v1.12.2).- Core engine abstraction (
CoreBackend). The UI, tray, shortcuts, and debug-API no longer call the process manager or Clash API directly; everything routes through the active backend (LegacyBackend= classic spawn,DaemonBackend= lxd). Proxy-group operations go through aProxyTransportseam (Clash HTTP for classic, gRPC for daemon), so the Servers tab is engine-agnostic. Daemon mode addsgoogle.golang.org/grpc+protobuf(darwin-only build tags — the win7 build is untouched); the daemon protobuf stubs are vendored from the fork viascripts/sync_daemonpb.sh. - Daemon mode requires a core built with
with_lx_command(thelxdsubcommand).RequiredCoreVersionmust be bumped to a fork release that ships it (1.14.0-lx.23+) before the feature is usable by end users; until then it is developed against a locally built core. - Cleanup pass over the SPEC 094–099 code. Dead code removed (
pickMainXrayVLESS,xrayBuildJumpFromOutbound,containsStringValue,activateDaemonEngineIfPossible— all orphaned by their own refactors). Copy-to-clipboard unified: oneNewCopyButtonreplaces three drifting copies of the "icon turns into a checkmark" feedback, andfynewidget.SetClipboardreplaces the deprecated per-windowWindow.Clipboard()across both UI packages. Deploy's resource collection moved out of the machine-list panel intoservices.CollectDeployResources(no widgets in it — it now has unit tests, which the GUI-excludeduipackage could not have).ProcessBaseis shared instead of duplicated in the machine profiler. ui/componentsno longer drags incore.ClickRedirect— the only widget there that needed app state — took the whole*core.AppControllerjust to focus the wizard window, and through the shared widget package that dependency reached every file importing the gutter helpers from it (20+, acrossui,ui/configurator/*andui/traffic). It now takes*uiservice.UIService, a leaf package. `ui/traf...
prerelease v1.3.1-49-gf025350-prerelease
Release v1.3.1-49-gf025350-prerelease
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v1.3.1-49-gf025350-prerelease):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.3.1-49-gf025350-prereleaseThe script will:
- Download the release archive
- Extract and install to
/Applications/ - Fix macOS quarantine attributes and permissions
- Launch the application automatically
Option 2: Manual Installation
- Download:
singbox-launcher-v1.3.1-49-gf025350-prerelease-macos.zip - Extract the ZIP file
- Remove quarantine attribute (required):
xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
- Double-click
singbox-launcher.appto run- If macOS blocks the app, go to System Settings → Privacy & Security and click "Open Anyway"
- Alternatively, right-click the app and select "Open" (first time only)
Windows (amd64)
- Download:
singbox-launcher-v1.3.1-49-gf025350-prerelease-win64.zip - Extract the ZIP file to a folder, for example:
C:\Program Files\singbox-launcher\ - Run
singbox-launcher.exefrom that folder- You may need administrator rights to install to Program Files
- The launcher will automatically download
sing-boxandwintun.dllon first launch
Windows 7 (x86, legacy)
- Download:
singbox-launcher-v1.3.1-49-gf025350-prerelease-win7-32.zip - Extract the ZIP file to a folder and run
singbox-launcher-win7-32.exe- For Windows 7 / 32-bit or legacy compatibility only
Linux Support
Checksums
See checksums.txt for SHA256 checksums of all files.
⚠️ Pre-release build offv1.3.1-49-gf025350-prerelease— for testing only, not for production. Use the latest stable release on the Releases page if you are not sure.
Upcoming release — черновик
Сюда складываем пункты, которые войдут в следующий релиз. Перед релизом переносим в X-Y-Z.md и очищаем этот файл.
Не добавлять сюда мелкие правки только UI (порядок виджетов, выравнивание, стиль кнопок без смены действия и т.п.). Писать новое поведение: данные, форматы, сохранение, заметные для пользователя возможности.
EN
Highlights
-
Every remote machine now has its own config. Until now a single profile was shared by all of them: one wizard state, one built config. Configuring a second machine silently overwrote the first, and Deploy sent whichever config happened to be written last — a router could receive a config built for a VPS. Each machine now owns a directory holding its wizard state, snapshots, built
config.json, rule sets and subscription bodies, so machines can't overwrite or delete each other's files. Existing setups migrate automatically when exactly one machine is paired; with several paired the old files are left untouched and a warning is logged, because there is no way to tell whose they were. -
Machine management moved into one place: the new Local and Remote tabs. They replace Core and Servers and share one layout — proxy list on the left, management on the right. Local pairs the proxy list with your own core's controls; Remote pairs it with the list of machines, each row showing name, platform, address and core status, with Configure / Start-Stop / Deploy / edit / remove right there. Previously this was scattered across three screens (the Servers header, the connection window, the wizard), and none of them showed a machine as a whole.
-
Picking a machine and choosing what to build for are no longer separate switches. Configure on a machine's row opens the wizard rooted on that machine's profile, and Deploy on the same row sends that machine's own config — so "built for one, deployed to another" is impossible by construction rather than by validation. A machine's platform and architecture now belong to its registry entry (edit them in its row), which is also what the config is built for.
-
The main window now opens at 1000×700 and won't shrink below it. Both tabs are two-column, and below that size the columns stop fitting and labels get cut off. It can still be stretched.
-
Daemon mode for the core (macOS). The launcher can now run the VPN core inside a long-lived system service (
sing-box lxd) instead of spawningsing-box runitself — the same in-process, reload-surviving model the Android app uses. Configure it in the new connection settings window: Servers → ⚙ → Local (the Remote tab keeps the SPEC 064 remote Clash override). What it buys you:- Sudo once, in your own Terminal. Installing the service is a single command the launcher prepares for you (copy or open in Terminal — full launchctl output, your own sudo; the launcher itself never runs anything privileged). After that, starting/stopping the VPN and applying config changes need no password at all.
- Quitting the launcher can keep the VPN up. By default, closing the launcher leaves the core running in the daemon; a "Stop VPN when quitting" toggle restores the classic behavior.
- In-process config swaps. Applying a new config no longer kills and restarts a process: the daemon swaps the core in-place, validates the config in a subprocess before touching the running instance, and auto-rolls-back to the last working config if the new one fails to start.
- Richer observability over gRPC. Proxy groups, node selection, latency tests, live status/traffic, connections, and core logs all flow over the daemon's gRPC channel (the CommandClient protocol shared with the Android line) — including a new balancer pool view on the Servers tab showing each urltest slot and its delay.
- Pairing. The launcher pairs with the daemon over mTLS using a one-time invite (
address#fingerprint#code). The install command prints one at the end — paste it into the pairing field; mint a fresh one any time withsudo sing-box lxd client add(works for remote daemons too). The daemon fully owns its home directory and credentials (daemon.jsonwith the listen address and admin secret lives in its state dir, reported overGET /admin/info); the launcher keeps only its own client keypair — a trusted client certificate is the whole credential.
The classic engine remains the default and is unchanged; daemon mode is opt-in and requires a core build with the
lxdsubcommand (sing-box-lx 1.14.0-lx.23 or newer).
Fixed
- Quit from the tray actually terminates the process. Quitting via the tray menu (or the Exit button) with the main window hidden or unfocused left the process alive: on Windows the tray icon stayed behind as a ghost, and relaunching the
.exereported "already running" because the dead-looking process still held the single-instance lock. Root cause is in Fyne's glfw driver:Quit()runs its tray teardown only when one of our windows currently holds focus — exactly the opposite of the quit-from-tray situation. The launcher now tears the tray icon down explicitly (systray.Quit(), the same call the driver skips: on Windows it deletes the notification-area icon immediately and stops the systray message pump), and a shutdown watchdog force-exits the process within 3 seconds if the Fyne event loop still refuses to unwind — by that point sing-box is already stopped and log files are closed, so nothing is lost.
Technical / Internal
GracefulExitis now idempotent (sync.Once): it is reachable both from the tray/Exit button and frommain()afterapp.Run()returns, and used to run the whole teardown twice.fyne.io/systraypromoted from indirect to direct dependency ingo.win7.mod(v1.12.0, version unchanged);go.modalready had it direct (v1.12.2).- Core engine abstraction (
CoreBackend). The UI, tray, shortcuts, and debug-API no longer call the process manager or Clash API directly; everything routes through the active backend (LegacyBackend= classic spawn,DaemonBackend= lxd). Proxy-group operations go through aProxyTransportseam (Clash HTTP for classic, gRPC for daemon), so the Servers tab is engine-agnostic. Daemon mode addsgoogle.golang.org/grpc+protobuf(darwin-only build tags — the win7 build is untouched); the daemon protobuf stubs are vendored from the fork viascripts/sync_daemonpb.sh. - Daemon mode requires a core built with
with_lx_command(thelxdsubcommand).RequiredCoreVersionmust be bumped to a fork release that ships it (1.14.0-lx.23+) before the feature is usable by end users; until then it is developed against a locally built core. - Cleanup pass over the SPEC 094–099 code. Dead code removed (
pickMainXrayVLESS,xrayBuildJumpFromOutbound,containsStringValue,activateDaemonEngineIfPossible— all orphaned by their own refactors). Copy-to-clipboard unified: oneNewCopyButtonreplaces three drifting copies of the "icon turns into a checkmark" feedback, andfynewidget.SetClipboardreplaces the deprecated per-windowWindow.Clipboard()across both UI packages. Deploy's resource collection moved out of the machine-list panel intoservices.CollectDeployResources(no widgets in it — it now has unit tests, which the GUI-excludeduipackage could not have).ProcessBaseis shared instead of duplicated in the machine profiler. ui/componentsno longer drags incore.ClickRedirect— the only widget there that needed app state — took the whole*core.AppControllerjust to focus the wizard window, and through the shared widget package that dependency reached every file importing the gutter helpers from it (20+, acrossui,ui/configurator/*andui/traffic). It now takes*uiservice.UIService, a leaf package. `ui/traf...
release v1.3.1
Release v1.3.1
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v1.3.1):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.3.1The script will:
- Download the release archive
- Extract and install to
/Applications/ - Fix macOS quarantine attributes and permissions
- Launch the application automatically
Option 2: Manual Installation
- Download:
singbox-launcher-v1.3.1-macos.zip - Extract the ZIP file
- Remove quarantine attribute (required):
xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
- Double-click
singbox-launcher.appto run- If macOS blocks the app, go to System Settings → Privacy & Security and click "Open Anyway"
- Alternatively, right-click the app and select "Open" (first time only)
Windows (amd64)
- Download:
singbox-launcher-v1.3.1-win64.zip - Extract the ZIP file to a folder, for example:
C:\Program Files\singbox-launcher\ - Run
singbox-launcher.exefrom that folder- You may need administrator rights to install to Program Files
- The launcher will automatically download
sing-boxandwintun.dllon first launch
Windows 7 (x86, legacy)
- Download:
singbox-launcher-v1.3.1-win7-32.zip - Extract the ZIP file to a folder and run
singbox-launcher-win7-32.exe- For Windows 7 / 32-bit or legacy compatibility only
Linux Support
Checksums
See checksums.txt for SHA256 checksums of all files.
v1.3.1
Патч-релиз: исправлено переключение группы селектора, когда ядро запущено не лаунчером, и добавлена информация о текущем выборе группы в список серверов.
EN
Highlights
- Selector group switching now works with an externally started core. Picking a different group in the Servers tab reloaded the node list only when sing-box had been launched by the launcher itself. If the core was started manually or the launcher was pointed at a remote Clash API endpoint (SPEC 064), the status line updated but the list kept showing nodes from the previous group. The reload is now gated on Clash API reachability instead of process ownership.
- Group rows show the node currently in use. A group's subtitle now reads
🚩 [11] fastest ‣ AL:🇫🇷-Франция— the mode, the pool size, and the member the core has selected right now (nowfrom the Clash API, taken from the/proxiesresponse the launcher already fetches, so no extra requests). Country badges remain as a fallback until the core reports a selection. - Glyph catalogue for UI icon picking — a new tab in the top row renders every glyph of the theme's fonts at the exact size used in list subtitles, with filters for "safe in all text fonts" and "emoji only", plus copy buttons for the glyph and its Go literal. Added because a symbol that looks fine in an editor can silently fail to render, turn into tofu on Cyrillic text, or arrive as an uncolourable colour emoji.
Fixed
- Stale auto-load results no longer overwrite the current group. The retry loop runs for up to ~100 seconds; switching groups while it was running was ignored ("already in progress"), and its late response then clobbered the list of the newly selected group. Runs are now superseded via a generation counter, and results are re-validated before every write.
- Scrollbar gutter in server list rows is no longer double-counted. The row padding added a fourth side on the right that stacked with the reserved gutter (~18pt instead of 14). A dedicated
components.NewListRowPaddedomits the right side, so every screen now reserves the same width from the single shared constant. - Saved traffic sessions list reserves the scrollbar gutter — the scrollbar used to paint over the row's
Deletebutton. - Group mode icons render reliably. The previous marks failed in the bundled emoji font:
⚡(U+26A1) has an empty glyph and drew nothing at all, and🔀collapsed into an unreadable blob at subtitle size. - macOS: the install script no longer leaves the app unlaunchable.
-ire-signed only the executable, so the bundle seal drifted out of sync withContents/and macOS refused to start the app (Launchd job spawn failed, POSIX 162). The seal check only caught a missing_CodeSignature, not a stale one; it now verifies the seal with working data moved aside and re-seals when needed.
RU
Основное
- Переключение группы селектора работает с ядром, запущенным не лаунчером. Выбор другой группы на вкладке «Серверы» перезагружал список узлов только если sing-box был поднят самим лаунчером. При ядре, запущенном вручную, или при подключении к внешнему Clash API (SPEC 064) статус менялся, а список продолжал показывать узлы предыдущей группы. Теперь условие — доступность Clash API, а не принадлежность процесса.
- Строки групп показывают текущий выбор. Подзаголовок группы читается как
🚩 [11] fastest ‣ AL:🇫🇷-Франция— режим, размер пула и узел, выбранный ядром прямо сейчас (полеnowиз Clash API, берётся из ответа/proxies, который лаунчер и так запрашивает, — дополнительных запросов нет). Флаги стран остаются запасным вариантом, пока ядро не сообщило выбор. - Каталог глифов для подбора значков UI — новая вкладка в верхнем ряду показывает все символы шрифтов темы на том же кегле, что и подзаголовки списка, с фильтрами «безопасные во всех текстовых шрифтах» и «только эмодзи» и кнопками копирования символа и Go-литерала. Появился потому, что символ, красивый в редакторе, в приложении может не отрисоваться вовсе, стать тофу на кириллице или прийти нередактируемой цветной картинкой.
Исправлено
- Устаревший результат автозагрузки больше не затирает текущую группу. Retry-цикл живёт до ~100 секунд; смена группы во время его работы игнорировалась («уже выполняется»), а поздний ответ затем перезаписывал список уже выбранной группы. Теперь запуски вытесняются по счётчику поколений, а результат сверяется перед каждой записью.
- Отступ под полосу прокрутки в строках списка серверов больше не удваивается. Padding строки добавлял справа четвёртую сторону, складывавшуюся с зарезервированным gutter'ом (~18pt вместо 14). Отдельный
components.NewListRowPaddedне ставит правый отступ, и все экраны резервируют одинаковую ширину из единой общей константы. - Список сохранённых сессий трафика резервирует место под полосу прокрутки — раньше она наезжала на кнопку «Delete».
- Значки режимов групп рисуются надёжно. Прежние символы не работали во встроенном эмодзи-шрифте: у
⚡(U+26A1) пустой глиф и он не отрисовывался вовсе, а🔀на кегле подзаголовка схлопывался в неразличимое пятно. - macOS: скрипт установки больше не оставляет приложение незапускаемым.
-iпереподписывал только исполняемый файл, печать бандла расходилась с содержимымContents/, и macOS отказывался стартовать приложение (Launchd job spawn failed, POSIX 162). Проверка ловила только отсутствие_CodeSignature, но не устаревшую печать; теперь она проверяет печать с вынесенными рабочими данными и пересоздаёт её при необходимости.
Техническое / Внутреннее
api.ProxyInfoполучил поляNow/NowDisplay— тег, выбранный группой, для каждой группы из ответа/proxies.components.NewListRowPadded— общий механизм padding'а строки списка без правой стороны; локальная константаserversListRowScrollbarGutterWidthудалена в пользуcomponents.ScrollbarGutterWidth.github.com/go-text/typesettingпереведён из косвенных зависимостей в прямые — используется каталогом глифов для чтения покрытия шрифтов.
release v1.3.0
Release v1.3.0
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v1.3.0):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.3.0The script will:
- Download the release archive
- Extract and install to
/Applications/ - Fix macOS quarantine attributes and permissions
- Launch the application automatically
Option 2: Manual Installation
- Download:
singbox-launcher-v1.3.0-macos.zip - Extract the ZIP file
- Remove quarantine attribute (required):
xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
- Double-click
singbox-launcher.appto run- If macOS blocks the app, go to System Settings → Privacy & Security and click "Open Anyway"
- Alternatively, right-click the app and select "Open" (first time only)
Windows (amd64)
- Download:
singbox-launcher-v1.3.0-win64.zip - Extract the ZIP file to a folder, for example:
C:\Program Files\singbox-launcher\ - Run
singbox-launcher.exefrom that folder- You may need administrator rights to install to Program Files
- The launcher will automatically download
sing-boxandwintun.dllon first launch
Windows 7 (x86, legacy)
- Download:
singbox-launcher-v1.3.0-win7-32.zip - Extract the ZIP file to a folder and run
singbox-launcher-win7-32.exe- For Windows 7 / 32-bit or legacy compatibility only
Linux Support
Checksums
See checksums.txt for SHA256 checksums of all files.
v1.3.0
Подписка теперь может быть целым конфигом sing-box, а не только списком ссылок:
приезжают узлы, цепочки прокси и группы. Xray-подписки перестали терять
большинство узлов. Каждая нода в списке подписана — протокол, транспорт,
защита, — и её можно выключить по отдельности.
A subscription can now be a whole sing-box config rather than a list of links:
nodes, proxy chains and groups all come across. Xray subscriptions stopped
losing most of their nodes. Every node in the list says what it is — protocol,
transport, security — and can be switched off individually.
EN
Highlights
- Import sing-box JSON subscriptions (SPEC 094). A subscription may now return a sing-box config instead of a URI list: a single outbound, an array of outbounds, a whole config, or an array of configs. Previously any body starting with
{produced zero nodes. - Proxy chains of any depth.
detourchains from an imported config are followed up to 8 hops (previously a single hop, SOCKS/VLESS only). Chains that loop back on themselves are broken at one edge — both nodes survive instead of disappearing. - Groups come with the config — as ordinary nodes.
selectorandurltestentries arrive as regular entries in the subscription's node list, not as channels in the Outbounds tab: routing rules never reference them and their membership is not user-editable. Members are remapped onto the final node tags; a group left without resolvable members is dropped rather than emitted (an emptyurltestrefuses to start the core). - Duplicate nodes are collapsed. A server listed several times within one subscription now yields a single node; the first one wins. Nodes differing only in SNI or transport are kept apart — those are distinct ways around filtering, not duplicates. Deduplication never spans subscriptions.
- Xray JSON subscriptions no longer lose most of their nodes. VMess, Trojan, Shadowsocks and Hysteria2 entries are parsed (previously VLESS only), and every node of an element is imported rather than just one.
xhttpandhttpupgradetransports are recognised, and dialerProxy chains follow up to 8 hops through any supported protocol instead of a single SOCKS/VLESS hop. Tags of existing single-node elements are unchanged. - Nodes with a space in the login are no longer lost. Public lists sometimes paste a promo login like
user:name @host;net/urlrejected the whole URI, silently dropping the node. - Every node now says what it is (SPEC 095). Under each tag in the server list sits a subtitle —
vless·tcp·Reality+Vision,wireguard,hysteria2·TLS— so two servers a provider gives the same name are finally distinguishable. Groups show their selection mode and pool instead:⚖️ [37] balanced,🎯 [11] fastest. The same subtitle appears on a source's Preview tab. - Latency is a coloured, clickable value. The ping button became the reading itself: green under 150 ms, yellow under 300, orange above, red on failure; «Ping» when nothing has been measured yet. Clicking it runs a fresh measurement.
- Node info window. Right-click any node — in the server list or on a source's Preview tab — for everything known about it: server, transport, TLS/REALITY details, detour chain, group membership and selection parameters, plus the exact outbound JSON on its own tab.
- Switch individual nodes off. A checkbox on every node in a source's Preview tab. The choice is bound to a hash of the node's identity, so it survives subscription updates, restarts, and the provider renaming or reordering the node. Marks for nodes long gone from the subscription are garbage-collected.
Technical / Internal
- Core pinned to
1.14.0-lx.22. Three fixes matter here. Connections through a silently dead path (Wi-Fi that stopped passing tunnel traffic, a node off the air) now fail in 15 seconds instead of hanging ~127 seconds with no error — the connect phase only, established downloads and streams are untouched. An auto-selecting group no longer keeps routing through a node that stopped answering: it moves to a working one on the spot rather than waiting for its next scheduled test. And REALITY nodes on freshly updated Xray servers work again. - Format detection is now a single function (
ClassifySubscriptionBody) instead of two independent, disagreeing checks.route,dns,inboundsandexperimentalof an imported config are ignored by design and reported to the UI. - Imported outbounds are sanitized with the same rules as URI nodes — uTLS allowlist, REALITY
public_key/short_id,flow,packet_encoding, hysteria2obfs, and uTLS/REALITY stripped on QUIC transports. A malformed entry drops that node only; the rest of the subscription is unaffected. - Fixed a crash when saving the wizard.
UpdateTemplatePreviewAsynctouched Fyne widgets directly while running inside a background goroutine — a data race Fyne itself flagged as «Error in Fyne call thread». It surfaced as the app simply closing on the last step of a save, most reliably after changing language and switching a group's mode. state.jsonno longer escapes&,<and>into&-style sequences. The values were always correct — Go escapes HTML by default — but subscription URLs and preview strings were unreadable in a file people open by hand.build/build_darwin.shwith no build type now targets the host architecture instead of always building universal — the common local case, and much faster. Release builds are unaffected: CI passesuniversal/catalinaexplicitly.build/build_darwin.sh -iverifies the bundle seal after installing and re-seals it ifContents/_CodeSignaturewent missing — macOS otherwise refuses the app with an unhelpful "cannot be opened" dialog. Re-sealing movesbin/andlogs/aside first: they live inside the signed area and may be root-owned after the core ran elevated.
RU
Основное
- Импорт подписок в формате sing-box JSON (SPEC 094). Подписка теперь может отдавать конфиг sing-box вместо списка ссылок: одиночный outbound, массив outbound'ов, целый конфиг или массив конфигов. Раньше любое тело, начинающееся с
{, давало ноль нод. - Цепочки прокси любой глубины. Цепочки
detourиз импортированного конфига разворачиваются до 8 хопов (раньше — ровно один, только SOCKS/VLESS). Кольцевые ссылки рвутся по одному ребру: обе ноды остаются, а не исчезают. - Группы приезжают вместе с конфигом — обычными узлами.
selectorиurltestпопадают в список нод подписки как рядовые записи, а не как каналы во вкладке Outbounds: правила роутинга на них не ссылаются, состав пользователем не редактируется. Члены перепривязываются на итоговые теги; группа, оставшаяся без разрешимых членов, не создаётся — пустойurltestне даёт ядру стартовать. - Дубли нод схлопываются. Сервер, перечисленный в одной подписке несколько раз, теперь даёт одну ноду — выживает первая. Ноды, различающиеся только SNI или транспортом, сохраняются обе: это разные способы обойти блокировку, а не дубли. Между разными подписками дедуп не применяется.
- Xray JSON-подписки больше не теряют большинство нод. Разбираются VMess, Trojan, Shadowsocks и Hysteria2 (раньше — только VLESS), и берутся все узлы элемента, а не один. Распознаются транспорты
xhttpиhttpupgrade, а цепочки dialerProxy разворачиваются до 8 хопов через любой поддерживаемый протокол вместо единственного SOCKS/VLESS. Теги существующих одноузловых элементов не изменились. - Ноды с пробелом в логине больше не теряются. В публичных списках встречается промо-логин вида
user:name @host;net/urlотвергал такой URI целиком, и нода пропадала молча. - Каждый узел теперь подписан (SPEC 095). Под тегом в списке серверов идёт описание —
vless·tcp·Reality+Vision,wireguard,hysteria2·TLS, — и два сервера, которым провайдер дал одно имя, наконец различимы. У групп вместо этого режим отбора и пул:⚖️ [37] по кругу,🎯 [11] быстрейший. То же описание появилось на вкладке Preview источника. - Задержка — цветное значение, а не кнопка. Кнопка «Ping» стала самим замером: зелёный до 150 мс, жёлтый до 300, оранжевый выше, красный при ошибке; «Ping», пока заме...
release v1.2.7
Release v1.2.7
Downloads
macOS (Universal) - Supports both Apple Silicon and Intel
Option 1: Installation Script (Recommended)
Install with a single command (version v1.2.7):
curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.2.7The script will:
- Download the release archive
- Extract and install to
/Applications/ - Fix macOS quarantine attributes and permissions
- Launch the application automatically
Option 2: Manual Installation
- Download:
singbox-launcher-v1.2.7-macos.zip - Extract the ZIP file
- Remove quarantine attribute (required):
xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
- Double-click
singbox-launcher.appto run- If macOS blocks the app, go to System Settings → Privacy & Security and click "Open Anyway"
- Alternatively, right-click the app and select "Open" (first time only)
Windows (amd64)
- Download:
singbox-launcher-v1.2.7-win64.zip - Extract the ZIP file to a folder, for example:
C:\Program Files\singbox-launcher\ - Run
singbox-launcher.exefrom that folder- You may need administrator rights to install to Program Files
- The launcher will automatically download
sing-boxandwintun.dllon first launch
Windows 7 (x86, legacy)
- Download:
singbox-launcher-v1.2.7-win7-32.zip - Extract the ZIP file to a folder and run
singbox-launcher-win7-32.exe- For Windows 7 / 32-bit or legacy compatibility only
Linux Support
Checksums
See checksums.txt for SHA256 checksums of all files.
v1.2.7 — одна нода с fp=HelloChrome_120 больше не роняет весь конфиг
Core pinned: sing-box-lx 1.14.0-lx.5 (unchanged from v1.2.6). No config migration needed.
A one-bug release. If any node in your subscription carried a raw uTLS identifier in fp=, sing-box refused to start at all — not just that node, the entire config. Nothing connected, and the log said unknown uTLS fingerprint.
EN
Highlights
-
A single node with an unknown
fp=value no longer takes down the whole config. Some lists ship the uTLS library's Go identifier —fp=HelloChrome_120— instead of the short name sing-box expects. The launcher only lowercased it, sohellochrome_120landed inconfig.jsonverbatim. sing-box validates that field against a fixed set and aborts on anything else:FATAL create service: initialize outbound[26]: unknown uTLS fingerprint: hellochrome_120That is a config-load failure, not a per-node one: outbound #26 being bad meant outbounds #0–25 never started either. The value is now checked against the set sing-box actually accepts, and raw uTLS identifiers are mapped onto their browser family (
HelloChrome_120→chrome,HelloFirefox_Auto→firefox, and so on). -
Unrecognised fingerprints degrade the node instead of poisoning the config. Anything that cannot be mapped is dropped, and the node falls back to a valid fingerprint rather than carrying junk into
config.json. Same policy as the REALITYpbkvalidation in v1.1.7 and the malformed?ed=handling in v1.2.6.
Technical / Internal
- The accepted set was taken from sing-box's own source, not from memory.
uTLSClientHelloIDincommon/tls/utls_client.goacceptschrome,firefox,edge,safari,360,qq,ios,android,random,randomized,""— plus five Chrome ClientHello variants that are easy to overlook:chrome_psk,chrome_psk_shuffle,chrome_padding_psk_shuffle,chrome_pq,chrome_pq_psk. Guessing the list would have silently broken nodes that legitimately use those. - Alias matching ignores separators.
_,-and spaces are stripped before the prefix match, soHelloChrome_120,hellochrome-106andHelloChrome 120all resolve tochrome. Ordering matters:hellorandomizedis tested beforehellorandom, otherwiseHelloRandomizedwould collapse intorandom. - The emitter needed its own fix.
GenerateNodeJSONre-normalises the fingerprint, but previously would have written"fingerprint":""for a rejected value. It now omits the key entirely, letting sing-box fall back to its default Chrome hello. This matters for templates: atls.utlsblock placed by hand or seeded intowizard_template.jsonnever passes through a parser, so the emitter is the only gate it meets. - Verified against sing-box's validator rather than by assertion. Every value the normaliser can emit was run through a verbatim copy of the upstream switch, confirming all outputs are accepted — and that the original
hellochrome_120really was rejected, so the check proves something. - Tests: 5 new cases — a normaliser table (sing-box names, Chrome variants, raw uTLS identifiers, junk), two parser regressions, and two emitter regressions. The existing
QQcasing test from issue #45 still passes.
Notes
sing-box checkdid catch this one — unlike the?ed=bug in v1.2.6, the failure was loud and at config-load time. The launcher surfaced it asRebuildConfigIfDirty: sing-box check failed, retrying every few seconds.- Nothing else changed. If no node in your subscription carries an unusual
fp=value, this release is a no-op for you.
RU
Основное
-
Одна нода с неизвестным
fp=больше не роняет весь конфиг. Некоторые списки кладут вfp=Go-идентификатор из библиотеки uTLS —fp=HelloChrome_120— вместо короткого имени, которое ждёт sing-box. Лаунчер только приводил строку к нижнему регистру, иhellochrome_120уезжал вconfig.jsonкак есть. sing-box сверяет это поле с фиксированным набором и на всём остальном прекращает загрузку:FATAL create service: initialize outbound[26]: unknown uTLS fingerprint: hellochrome_120Это отказ загрузки всего конфига, а не одной ноды: из-за битого outbound #26 не поднимались и outbound'ы #0–25. Теперь значение проверяется по набору, который sing-box действительно принимает, а сырые uTLS-идентификаторы отображаются на своё семейство браузера (
HelloChrome_120→chrome,HelloFirefox_Auto→firefoxи т.д.). -
Нераспознанный fingerprint деградирует ноду, а не портит конфиг. Всё, что не удалось сопоставить, отбрасывается, и нода откатывается на валидный fingerprint вместо того, чтобы тащить мусор в
config.json. Та же политика, что при валидации REALITYpbkв v1.1.7 и при разборе битого?ed=в v1.2.6.
Техническое / Внутреннее
- Набор допустимых значений взят из исходников sing-box, а не по памяти.
uTLSClientHelloIDвcommon/tls/utls_client.goпринимаетchrome,firefox,edge,safari,360,qq,ios,android,random,randomized,""— плюс пять вариантов Chrome ClientHello, которые легко пропустить:chrome_psk,chrome_psk_shuffle,chrome_padding_psk_shuffle,chrome_pq,chrome_pq_psk. Угадывание списка молча сломало бы ноды, которые их законно используют. - Сопоставление алиасов игнорирует разделители.
_,-и пробелы вычищаются перед сравнением префикса, поэтомуHelloChrome_120,hellochrome-106иHelloChrome 120одинаково даютchrome. Порядок важен:hellorandomizedпроверяется доhellorandom, иначеHelloRandomizedсхлопнулся бы вrandom. - Эмиттеру потребовалась отдельная правка.
GenerateNodeJSONперенормализует fingerprint, но раньше на отклонённом значении записал бы"fingerprint":"". Теперь ключ не пишется вовсе, и sing-box берёт свой Chrome-hello по умолчанию. Это важно для шаблонов: блокtls.utls, положенный руками или засеянный вwizard_template.json, не проходит через парсер вообще — эмиттер для него единственный барьер. - Проверено против валидатора sing-box, а не на слово. Все значения, которые может вернуть нормализатор, прогнаны через дословную копию upstream-switch: подтверждено, что ядро принимает каждое — и что исходный
hellochrome_120действительно отвергался, иначе проверка ничего не доказывала бы. - Тесты: 5 новых кейсов — таблица нормализатора (имена sing-box, варианты Chrome, сырые uTLS-идентификаторы, мусор), две регрессии парсера и две регрессии эмиттера. Старый тест на регистр
QQиз issue #45 продолжает проходить.
Примечания
sing-box checkэту проблему как раз ловил — в отличие от бага с?ed=из v1.2.6, отказ был громким и на этапе загрузки конфига. Лаунчер показывал его какRebuildConfigIfDirty: sing-box check failedи повторял попытку каждые несколько секунд.- Больше ничего не изменилось. Если ни в одной вашей ноде нет необычного
fp=, этот релиз для вас пустой.