Skip to content

release v1.5.4

Latest

Choose a tag to compare

@github-actions github-actions released this 03 Sep 00:16
· 1 commit to main since this release

Release v1.5.4

Downloads

macOS (Universal) - Supports both Apple Silicon and Intel

Option 1: Installation Script (Recommended)

Install with a single command (version v1.5.4):

curl -fsSL https://raw.githubusercontent.com/Leadaxe/singbox-launcher/develop/scripts/install-macos.sh | bash -s -- v1.5.4

The 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

  1. Download: singbox-launcher-v1.5.4-macos.zip
  2. Extract the ZIP file
  3. Remove quarantine attribute (required):
    xattr -cr "singbox-launcher.app" && chmod +x "singbox-launcher.app/Contents/MacOS/singbox-launcher"
  4. Double-click singbox-launcher.app to 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)

  1. Download: singbox-launcher-v1.5.4-win64.zip
    • or singbox-launcher-v1.5.4-win64-full.zipfull bundle: sing-box.exe, wintun.dll, the config template and Mesa3D (mesa3d/, used only when no hardware OpenGL — RDP, VMs) are already inside, nothing is downloaded on first launch
  2. Extract the ZIP file to a folder, for example: C:\Program Files\singbox-launcher\
  3. Run singbox-launcher.exe from that folder
    • You may need administrator rights to install to Program Files
    • The regular archive downloads sing-box and wintun.dll on first launch

Windows 7 (x86, legacy)

  1. Download: singbox-launcher-v1.5.4-win7-32.zip
  2. 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

⚠️ Linux build temporarily unavailable - мы ищем тестировщика для ручного тестирования перед включением автоматической сборки.

Checksums

See checksums.txt for SHA256 checksums of all files.

v1.5.4

A large release: the source model was rebuilt from the ground up (schema v7),
folders arrived as a first-class container, and a long tail of subscription
handling was fixed — provider identity, relays, wg-quick originals and
WireGuard detours.

Everything below is user-visible unless it sits under "Technical / Internal".
Settings migrate automatically on first launch; the previous state file is
kept next to the new one as state.json.v6.bak.

EN

Highlights

  • Windows "full" archive. singbox-launcher-<version>-win64-full.zip ships with everything inside: the pinned sing-box core (1.14.0-lx.30), wintun.dll, the config template and the Mesa3D software renderer in mesa3d/ (used only when the machine has no hardware OpenGL — RDP sessions, VMs). Nothing is downloaded on first launch. The regular archive is unchanged.

  • macOS install script pre-installs the core and the template. install-macos.sh now drops the release's pinned sing-box (Apple Silicon) and the config template into the bundle, so the first launch does not go online for them.

  • Core 1.14.0-lx.30. The launcher is pinned to the latest sing-box-lx release.

  • Folders: your own containers for nodes. "Add folder" in the Sources ⋮ menu creates an empty folder — a container you fill yourself, with no URL, no update interval and no node cap. Paste links, import files (multi-select; a node with no #fragment name takes its tag from the file name), add a WARP or a hand-written server, copy or move nodes in from other containers, and drag them into the order you want. A folder gets the same prefix/postfix tag policy and the same shared detour as a subscription, and can be folded into a group the same way.

  • Fill a folder from a subscription — and keep your edits. "Fill from subscription…" copies a subscription's nodes into a folder. Repeat it later and the folder is merged, not overwritten: a node you turned off stays off, its personal detour survives, and its position is kept. A node that disappeared at the provider is not deleted — it stays in the folder and simply loses its link to the subscription. If the subscription was cut short by the node limit, nothing is unlinked (there is no telling "gone" from "past the cap"), and a failed or empty response leaves the folder untouched entirely.

  • Editing a copied node unlinks it, and says so. Change a node's tag, its outbound JSON, or rebuild it from the original URI, and its link to the subscription is dropped with a notice. The next fill of that subscription will not touch it — your edit cannot vanish silently under an update.

  • Nodes a provider sends that we cannot parse are now visible. A rejected entry no longer disappears: it stays in the list on its own position, marked with the reason we could not read it, with the original line shown on hover and on click. It cannot be enabled (there is nothing to build from it) and it never reaches the config, a backup, or a JSON export. It does not consume a node number or a tag slot either, so one broken line at the provider no longer shifts the final tags of its neighbours. If the provider fixes it, it comes back as a normal, enabled node in the same place.

  • "Copy nodes as JSON" hands you the whole folder. The JSON tab of a folder copies every emitted node as a valid array of sing-box outbounds, with the final tags the build would use — accepted by sing-box check as a config fragment.

  • A copied source record pastes back. "Copy JSON" on a source row hands you its storage record — kind, nodes, detour, tag policy, replace. That record is now accepted by the Add field: pasted at the top level, a folder becomes a new folder with a fresh ID (its inner node-to-node links follow, links to Directions stay), a subscription becomes a subscription (deduplicated by URL), a single node becomes a node. Pasted inside an open folder, a folder record pours its nodes into that folder. Previously the field did not recognise the format and the Add button silently did nothing.

  • The Add button always reports. A parse error is shown in a dialog instead of the debug log only; a successful add shows what landed ("Added: 1 folder, 3 nodes"); an input that is already in the list says so instead of looking like a broken button.

  • The right-click menu on a server row got a re-test. "Re-test now" measures that row on demand — for a urltest group it is the same url-test the core runs on its interval, so you no longer have to wait out a cycle when the result went stale. The first line of that menu, which shows the outbound's type, is now visibly inactive: it was never an action, but it highlighted under the cursor and closed the menu doing nothing.

  • A group's Info window shows each member's last delay. The member list now carries the latest measured latency next to every entry, taken from the same data the servers list uses — no extra probing when the window opens.

  • Deleting a folder asks what to do with its nodes. You can move them out to the top level — the count, the order and every on/off mark are preserved — or delete them along with the folder, which asks for confirmation.

  • Folders travel in a backup. Folder members are exported as plain server records carrying the folder name (contract 0.12, servers[].folder), and the folder is rebuilt from them on import. The folder's own settings (tag policy, replacement, shared detour) and non-server members do not travel and are named in the export report.

  • Your settings are migrated automatically on first launch. The state file moves to a new format (schema v7) where every node of a subscription is stored explicitly instead of being re-parsed from a cached response on every build. The original file is kept next to it as state.json.v6.bak — nothing is overwritten until the new file has been written successfully.

  • A migration report tells you what changed. Anything that could not be carried over one-to-one is listed by name — never dropped silently — and shown once when you first open the configurator (it is also written to bin/migration_report.txt). Typical entries: a subscription that has never been fetched has no nodes yet (they appear after the first update); a folded subscription's auto-group is renamed from PREFIX:auto to <replace tag>-auto, so the core's saved pick for that group resets once.

  • Per-subscription defaults moved into application settings. "Default update interval" and "Default max nodes" now live in Settings and apply to subscriptions that do not set their own value. Each subscription can still override both.

  • The node limit is now real. max nodes actually stops parsing once the limit is reached and marks the subscription as truncated, instead of being counted after the fact. The hard ceiling is 3000 nodes per subscription; a larger value entered in Settings is clamped to it.

  • Each subscription can introduce itself its own way. A provider may hand out a different node list depending on the client that asks, and may bind the subscription to a device by its ID. User-Agent and the device ID (HWID) are now set per subscription, next to its URL: pick a client from the list or type your own, give this subscription its own device ID, or leave "as in system" to inherit the global setting. One provider's needs no longer distort what the others receive.

  • Provider relays are real nodes now. Some providers route a node through an intermediate socks5 relay instead of a direct path — that is how their "BYPASS" entries work when the direct route to their servers is cut. Such a relay used to live inside its node's body, invisible: you could not see it, switch it off, or point anything at it. It is now a node of its own, marked with a gear, with the owner dialing through it; it stays out of the Directions picker by default, and a checkbox in the subscription's settings puts it there if you want it.

  • A pasted wg-quick config keeps its original text. A WireGuard [Interface]/[Peer] block pasted into Sources is stored as it came — comments and all — instead of being replaced by a link derived from it. Editing the node's JSON no longer overwrites that original, and it survives an export/import as well. The node's name is taken from the peer's own comment (# US-FREE#137), not from the endpoint address.

  • A WireGuard node accepts a detour. Setting a detour on a WireGuard node — personally or shared by its folder — used to be silently dropped between the settings and the config: the field looked set and did nothing. The core accepts it, so it now reaches the config like any other node's.

  • A subscription that lists a server twice keeps both entries. Two entries pointing at one server, differing only in the way they dial it (one direct, one through a relay), stay two nodes: the dialing path is part of what makes them different.

  • The detour picker offers only enabled nodes. A disabled node never reaches the config, so choosing it would drop the whole source on the next build. A choice made before the target was switched off stays visible so you can see and clear it.

Technical / Internal

  • Importing a backup now merges by identity instead of replacing: subscriptions match by address, single servers by what they connect to (the name and the #fragment are not part of the comparison), folder members by body within their folder, chains and Directions by tag. Anything of yours that is not in the file stays — sources, DNS resolvers and WARP registrations alike. Routing rules remain the one section replaced wholesale.

  • A folder's fill and the top-level "add sources" field now go through one and the same parser: the same classifier, the same materialization, the same node either way.

  • A node moved or copied between containers carries its enabled and its detour with it; every reference whose target changed its final tag is either rewritten automatically (detour, chain hops, group members, a group's default) or named out loud in the dialog. A tag already taken in the destination is resolved with the same -2, -3 suffix the build uses.

  • The build's own tag guard no longer reports a Direction and its auto-group as two claimants of one tag.

  • Emission warnings now carry an address: the source or Direction they belong to, so the Sources row can mark itself and the report can point at the right line. The "Result" tab states the build outcome explicitly above the list instead of hiding a failure inside it.

  • Config assembly no longer parses subscription bodies. Outbounds are emitted from the materialized nodes[] in the state; the raw response cache (bin/subscriptions/*.raw) is read once by the migration and then removed.

  • Per-node on/off is stored on the node itself (enabled) instead of a separate map of hashed identity keys with a TTL and garbage collection. Keys that could not be matched during migration are reported.

  • Folding a subscription became "replace": the same modes, plus an explicit tag field, so the group name no longer has to be derived from the tag prefix.

  • Backup files moved to contract 0.12: a subscription carries its request identity as an optional identity object (user-agent, HWID and the sending mode), folder membership as servers[].folder; label is no longer written for servers and chains (a node is named by its tag) and is accepted from older files as a legacy input. Every lossy conversion is named in the warnings list shown after the operation; the full list of warning codes lives in contract/registry/backup_warnings.json.

  • Remote profiles: POST /profile/copy-from and PATCH /state/* refuse a state file whose schema major version is newer than this build's, naming both versions. Older files are accepted and migrated. GET is not gated, so diagnostics keep working during a mismatch.

  • Subscription fetch carries per-source identity: User-Agent and the HWID family of headers fall back to the global settings when a subscription does not set its own. UA presets live in an embedded asset (core/config/subscription/assets/user_agents.json), so refreshing the client list is a JSON edit.

  • Provider relays (Xray sockopt.dialerProxy) are materialized into nodes[] as service nodes and linked to their owner through Detour; they are always materialized, since without them the owner would dial direct — that is, into the block.

  • Deduplication of subscription entries takes the dialing path into account: two records on one server that differ only by their relay are no longer collapsed into one node.

  • Node rows are built from a single template shared by every list (root, folder, subscription): one layout, differences passed as data.

  • Diagnostic strings that reach the user are localized; core logs are English-only.

  • The node list of an opened container renders in a window: for containers above 250 nodes only the visible rows plus 100 above and below are built, hidden rows are stood in for by spacers, the window shifts as you scroll and stays frozen while a row is being dragged; the container's emission is cached per model revision, so a click no longer re-emits and rebuilds every node.

RU

Основное

  • Архив Windows «full». singbox-launcher-<version>-win64-full.zip содержит всё сразу: запиненное ядро sing-box (1.14.0-lx.30), wintun.dll, шаблон конфигуратора и программный рендерер Mesa3D в папке mesa3d/ (подхватывается только когда аппаратного OpenGL нет — RDP, виртуалки). Первый запуск ничего не качает. Обычный архив не изменился.

  • Mac-скрипт установки кладёт ядро и шаблон. install-macos.sh теперь докачивает в бандл запиненное ядро sing-box (Apple Silicon) и шаблон конфигуратора того же релиза — первый запуск за ними в сеть не ходит.

  • Ядро 1.14.0-lx.30. Лаунчер запинен на последний релиз sing-box-lx.

  • Папки — свои контейнеры для узлов. «Add folder» в ⋮-меню «Источников» заводит пустую папку: контейнер, который вы наполняете сами, — без URL, без интервала обновления и без ограничения на число узлов. Вставляйте ссылки, импортируйте файлы (мультивыбор; узлу без имени во #fragment тег даётся из имени файла), добавляйте WARP или сервер руками, копируйте и переносите узлы из других контейнеров, перетаскивайте их в нужном порядке. У папки та же политика тегов (префикс/постфикс) и тот же общий detour, что у подписки, и её так же можно свернуть в группу.

  • Заливка подписки в папку не затирает ваши правки. «Fill from subscription…» копирует узлы подписки в папку. Повторите позже — папка сливается, а не переписывается: выключенный узел останется выключенным, личный detour уцелеет, позиция сохранится. Узел, исчезнувший у провайдера, не удаляется — он остаётся в папке и просто теряет связь с подпиской. Если разбор подписки обрезан лимитом узлов, связь не рвётся ни у кого (не отличить «исчез» от «за лимитом»), а ошибка сети или пустой ответ не трогают папку вообще.

  • Правка скопированного узла разрывает связь — и говорит об этом. Смените узлу тег, поправьте его outbound-JSON или пересоберите его из исходного URI — связь с подпиской снимается с уведомлением. Следующая заливка этой подписки узел не тронет: ваша правка не может молча пропасть под обновлением.

  • Узлы, которые провайдер прислал, а мы не разобрали, теперь видны. Отбракованная запись больше не исчезает: она остаётся в списке на своём месте, с причиной, по которой её не прочли, и с исходной строкой — в подсказке по наведению и по клику. Включить её нельзя (собирать из неё нечего), и в конфиг, бэкап и выгрузку JSON она не попадает. Она не занимает ни номер узла, ни слот тега — одна битая строка у провайдера больше не сдвигает финальные теги соседей. Починит провайдер — запись вернётся обычным включённым узлом на то же место.

  • «Copy nodes as JSON» отдаёт папку целиком. Вкладка JSON у папки копирует все собираемые узлы валидным массивом outbound'ов sing-box, с теми же финальными тегами, что и в сборке; sing-box check принимает результат как фрагмент конфига.

  • Скопированная запись источника вставляется обратно. «Copy JSON» в меню строки источника отдаёт его запись хранения — kind, узлы, detour, политика тегов, replace. Теперь поле Add принимает такую запись: в корне папка становится новой папкой со свежим ID (внутренние ссылки узлов друг на друга переезжают, ссылки на Направления остаются), подписка — подпиской с дедупом по URL, одиночный узел — узлом. Внутри открытой папки запись папки высыпает в неё свои узлы. Раньше поле этот формат не узнавало, и кнопка Add молча не делала ничего.

  • Кнопка Add отчитывается всегда. Ошибка разбора показывается диалогом, а не только в debug-логе; успешное добавление говорит, что легло («Добавлено: папок 1, узлов 3»); вход, который уже есть в списке, называется дубликатом, а не выглядит как сломанная кнопка.

  • В меню строки сервера появился принудительный замер. «Замерить сейчас» меряет эту строку по требованию: для группы urltest это тот же url-тест, который ядро гоняет по интервалу, — не нужно ждать следующего цикла, когда результат протух. Первая строка того же меню, показывающая тип outbound'а, стала явно неактивной: действием она никогда не была, но подсвечивалась под курсором и закрывала меню, ничего не сделав.

  • В окне Info у группы видны задержки участников. Рядом с каждым участником состава стоит его последний замер — из тех же данных, что рисуют список серверов, без дополнительных проб при открытии окна.

  • Удаление папки спрашивает, что делать с узлами. Их можно вынести в корень — число, порядок и все галки «включён» сохраняются — либо удалить вместе с папкой, и это требует подтверждения.

  • Папки едут в бэкап. Члены папки выгружаются обычными записями серверов с именем папки (контракт 0.12, servers[].folder), и на импорте папка собирается из них обратно. Настройки самой папки (политика тегов, замена, общий detour) и члены не-серверы не едут и названы в отчёте экспорта.

  • Настройки мигрируют сами при первом запуске. Файл состояния переезжает на новый формат (схема v7): узлы подписки хранятся явно, а не разбираются заново из кэша ответа на каждой сборке. Исходный файл остаётся рядом как state.json.v6.bak — он не трогается, пока новый не записан успешно.

  • Отчёт миграции показывает, что изменилось. Всё, что не удалось перенести один-в-один, названо поимённо (молчаливых потерь нет) и показывается один раз при первом открытии конфигуратора; отчёт также пишется в bin/migration_report.txt. Типичные пункты: у подписки, которая ни разу не обновлялась, узлов пока нет (появятся после первого обновления); у свёрнутой подписки авто-группа переименована из ПРЕФИКС:auto в <тег замены>-auto, поэтому сохранённый в ядре выбор для неё один раз сбрасывается.

  • Умолчания подписок переехали в настройки приложения. «Интервал обновления по умолчанию» и «Максимум узлов по умолчанию» живут в Настройках и применяются к подпискам без собственного значения. У каждой подписки по-прежнему можно задать своё.

  • Ограничение на число узлов стало настоящим. max nodes реально останавливает разбор по достижении лимита и помечает подписку как усечённую, а не считается постфактум. Жёсткий потолок — 3000 узлов на подписку; большее значение в Настройках к нему прижимается.

  • Каждая подписка представляется по-своему. Провайдер может отдавать разный список узлов в зависимости от клиента, который спрашивает, и привязывать подписку к устройству по его ID. User-Agent и идентификатор устройства (HWID) теперь задаются у каждой подписки, рядом с её URL: выберите клиента из списка или впишите свой, дайте этой подписке отдельный ID устройства — или оставьте «как в системе» и наследуйте общую настройку. Нужды одного провайдера больше не искажают то, что приходит от остальных.

  • Релеи провайдера стали настоящими узлами. Некоторые провайдеры ведут узел не напрямую, а через промежуточный socks5-релей — так работают их «BYPASS»-записи, когда прямой путь к серверам перекрыт. Раньше такой релей жил внутри тела своего узла и человеку не существовал: его нельзя было увидеть, выключить или на него сослаться. Теперь это отдельный узел с шестерёнкой, а владелец дозванивается через него. В выборе Направлений релей по умолчанию не предлагается — за это отвечает галка в настройках подписки.

  • Вставленный конфиг wg-quick хранится как есть. Блок WireGuard [Interface]/[Peer], вставленный в «Источники», сохраняется в исходном виде — со всеми комментариями, — а не подменяется выведенной из него ссылкой. Правка JSON узла больше не затирает этот исходник, и он переживает экспорт-импорт. Имя узла берётся из собственного комментария пира (# US-FREE#137), а не из адреса endpoint'а.

  • Узел WireGuard принимает detour. Detour у WireGuard-узла — личный или общий от папки — раньше молча снимался между настройками и конфигом: поле выглядело заданным и не делало ничего. Ядро его принимает, поэтому теперь он доезжает до конфига, как у любого другого узла.

  • Подписка, перечисляющая один сервер дважды, сохраняет обе записи. Две записи на один сервер, отличающиеся только способом дозвона (одна напрямую, вторая через релей), остаются двумя узлами: путь дозвона — часть того, чем они различаются.

  • В выборе detour предлагаются только включённые узлы. Выключенный узел в конфиг не идёт, и выбор на него уронил бы весь источник на следующей сборке. Выбор, сделанный до выключения цели, остаётся видимым — чтобы его можно было увидеть и снять.

Техническое / Внутреннее

  • Импорт бэкапа теперь сливает по идентичности, а не заменяет: подписки сходятся по адресу, одиночные серверы — по телу (имя и #фрагмент в сравнении не участвуют), члены папки — по телу внутри своей папки, цепочки и Направления — по тегу. Всё локальное, чего в файле нет, остаётся: и источники, и DNS-резолверы, и регистрации WARP. Единственная секция полной замены — правила маршрутизации.
  • Наполнение папки и поле «добавить источники» в корне идут через один и тот же разбор: тот же классификатор, та же материализация, тот же узел на выходе обоими путями.
  • Узел, перенесённый или скопированный между контейнерами, увозит с собой enabled и detour; всякая ссылка, чья цель сменила финальный тег, либо переписана автоматически (detour, хопы цепочки, члены группы, default группы), либо названа вслух в диалоге. Занятый в приёмнике тег разводится тем же суффиксом -2, -3, что и на сборке.
  • Гард тегов сборки больше не считает Направление и его авто-группу двумя претендентами на один тег.
  • У предупреждений эмиссии появился адресат — источник или Направление, к которому они относятся: строка «Источников» ставит себе ⚠, а отчёт указывает на нужную строку. Вкладка «Итог» объявляет исход сборки явно над списком, а не прячет провал внутри него.
  • Сборка конфига больше не разбирает тела подписок: outbound'ы эмитятся из материализованных nodes[] состояния. Кэш сырых ответов (bin/subscriptions/*.raw) читается один раз миграцией и удаляется.
  • Отметка «узел выключен» хранится на самом узле (enabled), а не отдельной картой хэш-ключей с TTL и сборкой мусора. Ключи, которые миграция не смогла сопоставить, попадают в отчёт.
  • Свёртка подписки стала «заменой»: те же режимы плюс явное поле тега — имя группы больше не обязано быть производным от префикса тегов.
  • Файлы бэкапа переведены на контракт 0.12: подписка везёт идентификацию запроса необязательным объектом identity (User-Agent, HWID и режим отправки), принадлежность к папке — полем servers[].folder; label у серверов и цепочек больше не пишется (узел зовут его тегом) и принимается из старых файлов как legacy-вход. Каждая потеря конвертации названа в списке предупреждений после операции; полный перечень кодов — в contract/registry/backup_warnings.json.
  • Удалённые профили: POST /profile/copy-from и PATCH /state/* отклоняют файл состояния, чья мажорная версия схемы новее этой сборки, называя обе версии. Файлы постарше принимаются и мигрируются. GET не гейтуется — диагностика обязана работать в момент расхождения.
  • Загрузка подписки несёт идентификацию источника: User-Agent и семейство HWID-заголовков откатываются на глобальные настройки, если у подписки своего значения нет. Пресеты UA живут во встроенном ассете (core/config/subscription/assets/user_agents.json) — обновление списка клиентов это правка одного JSON.
  • Релеи провайдера (Xray sockopt.dialerProxy) материализуются в nodes[] служебными узлами и связываются с владельцем полем Detour; материализуются они всегда — без релея владелец пошёл бы напрямую, то есть в блокировку.
  • Дедупликация записей подписки учитывает путь дозвона: две записи на один сервер, различающиеся только релеем, больше не схлопываются в один узел.
  • Строки узлов во всех списках (корень, папка, подписка) строятся одним общим шаблоном: одна вёрстка, различия передаются данными.
  • Диагностика, которую видит пользователь, локализована; логи ядра — только на английском.
  • Список узлов открытого контейнера рисуется окном: у контейнеров больше 250 узлов строятся только видимые строки плюс 100 сверху и снизу, скрытые заменены распорками, окно сдвигается при прокрутке и замирает на время перетаскивания; эмиссия контейнера кэшируется по ревизии модели, и клик больше не переэмитит и не перестраивает все узлы.