TypeScript implementation of the sing-box binary rule-set (.srs) compiler and decompiler.
This project is a small JavaScript/TypeScript library for working with sing-box SRS files without running the Go sing-box binary. It mirrors the binary rule-set format implemented by sing-box, accepts the same plain rule-set JSON shape, and returns Uint8Array data that can be used in modern JavaScript runtimes.
It is not a TypeScript port of the full sing-box proxy platform. It does not load configs, match traffic, manage remote rule sets, or implement route/DNS behavior. It only serializes and deserializes plain headless rule sets.
- Compile sing-box plain rule-set JSON to
.srsbinary bytes. - Decompile
.srsbinary bytes back to plain rule-set JSON. - Support sing-box rule-set versions 1 through 5.
- Support default and logical headless rules.
- Use the sing-box SRS magic header, zlib payload, varint encoding, succinct domain matcher format, and IP set encoding.
- Run in browsers, Bun, Deno, workers, Node-compatible bundlers, and other runtimes that support standard
Uint8ArrayAPIs.
Default rules support these JSON fields:
query_typenetworkdomaindomain_suffixdomain_keyworddomain_regexsource_ip_cidrip_cidrsource_portsource_port_rangeportport_rangeprocess_nameprocess_pathprocess_path_regexpackage_namepackage_name_regexnetwork_typenetwork_is_expensivenetwork_is_constrainednetwork_interface_addressdefault_interface_addresswifi_ssidwifi_bssidinvert
Logical rules support type: "logical", mode: "and" | "or", nested rules, and invert.
Version-gated fields follow sing-box's binary format rules:
network_type,network_is_expensive, andnetwork_is_constrainedrequire version 3 or later.network_interface_addressanddefault_interface_addressrequire version 4 or later.package_name_regexrequires version 5 or later.
The binary-only AdGuard matcher item is intentionally unsupported and will throw if encountered, because sing-box does not expose it as a normal source JSON field.
import { compile, decompile } from "srs.ts";
const ruleSet = {
version: 4,
rules: [
{
domain: ["example.com"],
domain_suffix: ["example.org"],
ip_cidr: ["10.0.0.0/24"]
},
{
type: "logical",
mode: "and",
rules: [{ network: "tcp" }, { port: [80, 443] }]
}
]
};
const srsBytes = compile(ruleSet);
const decoded = decompile(srsBytes);compile() returns a Uint8Array containing the complete .srs file contents. decompile() accepts a Uint8Array containing .srs bytes and returns plain rule-set JSON.
The package also installs an srs.ts command for use with npx:
npx srs.ts compile rules.srs
npx srs.ts decompile rules.jsonYou can pass an explicit output path as a second argument:
npx srs.ts compile source.json output.srs
npx srs.ts decompile source.srs output.jsonfunction compile(ruleSet: PlainRuleSet): Uint8Array;
function decompile(data: Uint8Array): PlainRuleSet;The package also exports TypeScript types for PlainRuleSet, Rule, DefaultRule, LogicalRule, and related helper shapes.
Install dependencies with Bun:
bun installRun tests:
bun testBuild the package:
bun run buildIf sing-box is available on PATH, the tests also perform cross-compatibility checks with sing-box rule-set compile and sing-box rule-set decompile.