@singbox-iac/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +265 -0
- package/dist/cli/command-helpers.d.ts +6 -0
- package/dist/cli/command-helpers.js +34 -0
- package/dist/cli/command-helpers.js.map +1 -0
- package/dist/cli/commands/apply.d.ts +2 -0
- package/dist/cli/commands/apply.js +32 -0
- package/dist/cli/commands/apply.js.map +1 -0
- package/dist/cli/commands/author.d.ts +2 -0
- package/dist/cli/commands/author.js +194 -0
- package/dist/cli/commands/author.js.map +1 -0
- package/dist/cli/commands/build.d.ts +2 -0
- package/dist/cli/commands/build.js +198 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/check.d.ts +2 -0
- package/dist/cli/commands/check.js +23 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.js +35 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.js +23 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/reload.d.ts +2 -0
- package/dist/cli/commands/reload.js +21 -0
- package/dist/cli/commands/reload.js.map +1 -0
- package/dist/cli/commands/run.d.ts +2 -0
- package/dist/cli/commands/run.js +25 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/schedule.d.ts +2 -0
- package/dist/cli/commands/schedule.js +77 -0
- package/dist/cli/commands/schedule.js.map +1 -0
- package/dist/cli/commands/templates.d.ts +2 -0
- package/dist/cli/commands/templates.js +34 -0
- package/dist/cli/commands/templates.js.map +1 -0
- package/dist/cli/commands/update.d.ts +2 -0
- package/dist/cli/commands/update.js +52 -0
- package/dist/cli/commands/update.js.map +1 -0
- package/dist/cli/commands/verify.d.ts +2 -0
- package/dist/cli/commands/verify.js +49 -0
- package/dist/cli/commands/verify.js.map +1 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.js +55 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/load-config.d.ts +2 -0
- package/dist/config/load-config.js +29 -0
- package/dist/config/load-config.js.map +1 -0
- package/dist/config/schema.d.ts +548 -0
- package/dist/config/schema.js +92 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/domain/config.d.ts +8 -0
- package/dist/domain/config.js +2 -0
- package/dist/domain/config.js.map +1 -0
- package/dist/domain/node.d.ts +11 -0
- package/dist/domain/node.js +2 -0
- package/dist/domain/node.js.map +1 -0
- package/dist/domain/outbound.d.ts +15 -0
- package/dist/domain/outbound.js +2 -0
- package/dist/domain/outbound.js.map +1 -0
- package/dist/domain/subscription.d.ts +6 -0
- package/dist/domain/subscription.js +2 -0
- package/dist/domain/subscription.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/authoring/index.d.ts +41 -0
- package/dist/modules/authoring/index.js +596 -0
- package/dist/modules/authoring/index.js.map +1 -0
- package/dist/modules/build/index.d.ts +13 -0
- package/dist/modules/build/index.js +39 -0
- package/dist/modules/build/index.js.map +1 -0
- package/dist/modules/compiler/index.d.ts +10 -0
- package/dist/modules/compiler/index.js +305 -0
- package/dist/modules/compiler/index.js.map +1 -0
- package/dist/modules/doctor/index.d.ts +17 -0
- package/dist/modules/doctor/index.js +89 -0
- package/dist/modules/doctor/index.js.map +1 -0
- package/dist/modules/fetcher/index.d.ts +4 -0
- package/dist/modules/fetcher/index.js +42 -0
- package/dist/modules/fetcher/index.js.map +1 -0
- package/dist/modules/init/index.d.ts +12 -0
- package/dist/modules/init/index.js +41 -0
- package/dist/modules/init/index.js.map +1 -0
- package/dist/modules/manager/index.d.ts +29 -0
- package/dist/modules/manager/index.js +133 -0
- package/dist/modules/manager/index.js.map +1 -0
- package/dist/modules/natural-language/index.d.ts +54 -0
- package/dist/modules/natural-language/index.js +458 -0
- package/dist/modules/natural-language/index.js.map +1 -0
- package/dist/modules/parser/index.d.ts +10 -0
- package/dist/modules/parser/index.js +113 -0
- package/dist/modules/parser/index.js.map +1 -0
- package/dist/modules/preview/index.d.ts +22 -0
- package/dist/modules/preview/index.js +141 -0
- package/dist/modules/preview/index.js.map +1 -0
- package/dist/modules/rule-templates/index.d.ts +15 -0
- package/dist/modules/rule-templates/index.js +200 -0
- package/dist/modules/rule-templates/index.js.map +1 -0
- package/dist/modules/schedule/index.d.ts +32 -0
- package/dist/modules/schedule/index.js +155 -0
- package/dist/modules/schedule/index.js.map +1 -0
- package/dist/modules/update/index.d.ts +22 -0
- package/dist/modules/update/index.js +38 -0
- package/dist/modules/update/index.js.map +1 -0
- package/dist/modules/user-rules/index.d.ts +18 -0
- package/dist/modules/user-rules/index.js +98 -0
- package/dist/modules/user-rules/index.js.map +1 -0
- package/dist/modules/verification/index.d.ts +49 -0
- package/dist/modules/verification/index.js +432 -0
- package/dist/modules/verification/index.js.map +1 -0
- package/dist/shared/errors.d.ts +3 -0
- package/dist/shared/errors.js +7 -0
- package/dist/shared/errors.js.map +1 -0
- package/dist/shared/logger.d.ts +2 -0
- package/dist/shared/logger.js +5 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/result.d.ts +11 -0
- package/dist/shared/result.js +7 -0
- package/dist/shared/result.js.map +1 -0
- package/docs/antigravity-endpoints.md +77 -0
- package/docs/competitive-landscape.md +45 -0
- package/docs/development-workflow.md +80 -0
- package/docs/natural-language-authoring.md +376 -0
- package/docs/positioning.md +42 -0
- package/docs/releasing.md +72 -0
- package/docs/rule-templates.md +122 -0
- package/docs/rules-dsl.md +107 -0
- package/docs/runtime-on-macos.md +42 -0
- package/docs/sing-box-config-primer.md +39 -0
- package/docs/subscription-format.md +38 -0
- package/examples/builder.config.yaml +220 -0
- package/examples/custom.rules.yaml +18 -0
- package/package.json +51 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Rule Templates
|
|
2
|
+
|
|
3
|
+
Built-in rule templates are intended to cover the repetitive cases that most developer-oriented setups run into:
|
|
4
|
+
|
|
5
|
+
- third-party AI sites
|
|
6
|
+
- common third-party developer tooling sites
|
|
7
|
+
- international video sites that should exit through a specific region
|
|
8
|
+
- mainland video sites that should stay direct
|
|
9
|
+
|
|
10
|
+
Templates are not a replacement for the compiler's built-in policy. They sit on top of it and are meant for fast customization.
|
|
11
|
+
|
|
12
|
+
## Current Templates
|
|
13
|
+
|
|
14
|
+
### Developer
|
|
15
|
+
|
|
16
|
+
- `developer-ai-sites`
|
|
17
|
+
Routes common third-party AI sites to `AI-Out`.
|
|
18
|
+
Includes:
|
|
19
|
+
- `openrouter.ai`
|
|
20
|
+
- `perplexity.ai`
|
|
21
|
+
|
|
22
|
+
- `developer-common-sites`
|
|
23
|
+
Routes common third-party developer sites to `Dev-Common-Out`.
|
|
24
|
+
Includes:
|
|
25
|
+
- `gitlab.com`
|
|
26
|
+
- `npmjs.com`
|
|
27
|
+
- `registry.npmjs.org`
|
|
28
|
+
- `vercel.com`
|
|
29
|
+
- `cloudflare.com`
|
|
30
|
+
- `docker.com`
|
|
31
|
+
- `hub.docker.com`
|
|
32
|
+
- `stackoverflow.com`
|
|
33
|
+
- `huggingface.co`
|
|
34
|
+
|
|
35
|
+
### Video
|
|
36
|
+
|
|
37
|
+
- `video-us`
|
|
38
|
+
Routes international streaming sites to `US`.
|
|
39
|
+
|
|
40
|
+
- `video-hk`
|
|
41
|
+
Routes international streaming sites to `HK`.
|
|
42
|
+
|
|
43
|
+
- `video-sg`
|
|
44
|
+
Routes international streaming sites to `SG`.
|
|
45
|
+
|
|
46
|
+
- `video-jp`
|
|
47
|
+
Routes Japan-oriented video sites to `JP`.
|
|
48
|
+
|
|
49
|
+
- `cn-video-direct`
|
|
50
|
+
Keeps common mainland video sites on `direct`.
|
|
51
|
+
|
|
52
|
+
The international streaming templates currently cover:
|
|
53
|
+
|
|
54
|
+
- `youtube.com`
|
|
55
|
+
- `youtu.be`
|
|
56
|
+
- `netflix.com`
|
|
57
|
+
- `nflxvideo.net`
|
|
58
|
+
- `disneyplus.com`
|
|
59
|
+
- `disney-plus.net`
|
|
60
|
+
- `hulu.com`
|
|
61
|
+
- `max.com`
|
|
62
|
+
- `twitch.tv`
|
|
63
|
+
|
|
64
|
+
The JP template currently covers:
|
|
65
|
+
|
|
66
|
+
- `abema.tv`
|
|
67
|
+
- `niconico.jp`
|
|
68
|
+
- `dmm.com`
|
|
69
|
+
- `lemino.docomo.ne.jp`
|
|
70
|
+
|
|
71
|
+
The CN direct template currently covers:
|
|
72
|
+
|
|
73
|
+
- `bilibili.com`
|
|
74
|
+
- `bilibili.tv`
|
|
75
|
+
- `iqiyi.com`
|
|
76
|
+
- `iq.com`
|
|
77
|
+
- `youku.com`
|
|
78
|
+
- `mgtv.com`
|
|
79
|
+
|
|
80
|
+
## CLI Usage
|
|
81
|
+
|
|
82
|
+
List templates:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
./node_modules/.bin/tsx src/cli/index.ts templates list
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Show one template:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
./node_modules/.bin/tsx src/cli/index.ts templates show video-sg
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Natural-Language Mapping
|
|
95
|
+
|
|
96
|
+
The `author` command can infer templates from short prompts.
|
|
97
|
+
|
|
98
|
+
Examples:
|
|
99
|
+
|
|
100
|
+
- `开发者网站走香港,视频网站走新加坡`
|
|
101
|
+
- `AI 工具走香港,视频网站走美国,每45分钟自动更新`
|
|
102
|
+
- `国内视频网站直连,YouTube Netflix 走美国`
|
|
103
|
+
|
|
104
|
+
Typical mapping behavior:
|
|
105
|
+
|
|
106
|
+
- `开发者网站` -> `developer-common-sites`
|
|
107
|
+
- `AI 工具` -> `developer-ai-sites`
|
|
108
|
+
- `视频网站走美国` -> `video-us`
|
|
109
|
+
- `视频网站走香港` -> `video-hk`
|
|
110
|
+
- `视频网站走新加坡` -> `video-sg`
|
|
111
|
+
- `日本视频网站` -> `video-jp`
|
|
112
|
+
- `国内视频网站直连` -> `cn-video-direct`
|
|
113
|
+
|
|
114
|
+
## Design Boundary
|
|
115
|
+
|
|
116
|
+
Templates are intentionally coarse-grained. They are best for:
|
|
117
|
+
|
|
118
|
+
- "a whole class of sites should go to one region"
|
|
119
|
+
- "these common developer sites should use the developer selector"
|
|
120
|
+
- "these common AI sites should use the AI selector"
|
|
121
|
+
|
|
122
|
+
If a user needs one-off exceptions, prefer the DSL instead of adding more template complexity.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Rules DSL
|
|
2
|
+
|
|
3
|
+
## Design Goal
|
|
4
|
+
|
|
5
|
+
Users should customize routing intent without editing raw `sing-box` JSON.
|
|
6
|
+
|
|
7
|
+
## Layers
|
|
8
|
+
|
|
9
|
+
### Layer 1: Built-in system rules
|
|
10
|
+
|
|
11
|
+
These are protected invariants controlled by the compiler, such as:
|
|
12
|
+
|
|
13
|
+
- QUIC kill-switch for `udp:443`
|
|
14
|
+
- DNS handling
|
|
15
|
+
- `in-proxifier` high-priority routing
|
|
16
|
+
|
|
17
|
+
These rules always stay ahead of user rules.
|
|
18
|
+
|
|
19
|
+
### Layer 2: Declarative user rules
|
|
20
|
+
|
|
21
|
+
Users write a small YAML DSL with only two insertion points:
|
|
22
|
+
|
|
23
|
+
- `beforeBuiltins`
|
|
24
|
+
Inserted after protected system rules and before built-in service rules such as Stitch, OpenAI, AI rule sets, and developer rule sets.
|
|
25
|
+
- `afterBuiltins`
|
|
26
|
+
Inserted after built-in service rules and before China direct rules.
|
|
27
|
+
|
|
28
|
+
## File Shape
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
version: 1
|
|
32
|
+
|
|
33
|
+
beforeBuiltins:
|
|
34
|
+
- name: "OpenRouter uses AI"
|
|
35
|
+
domainSuffix:
|
|
36
|
+
- "openrouter.ai"
|
|
37
|
+
route: "AI-Out"
|
|
38
|
+
|
|
39
|
+
afterBuiltins:
|
|
40
|
+
- name: "Example mainland domain stays direct"
|
|
41
|
+
domainSuffix:
|
|
42
|
+
- "intranet.example.cn"
|
|
43
|
+
route: "direct"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Supported Matchers
|
|
47
|
+
|
|
48
|
+
Each rule may use one or more of these fields:
|
|
49
|
+
|
|
50
|
+
- `inbound`
|
|
51
|
+
- `protocol`
|
|
52
|
+
- `network`
|
|
53
|
+
- `port`
|
|
54
|
+
- `domain`
|
|
55
|
+
- `domainSuffix`
|
|
56
|
+
- `ruleSet`
|
|
57
|
+
|
|
58
|
+
Scalar values are allowed for convenience. These are normalized to arrays where needed.
|
|
59
|
+
|
|
60
|
+
## Supported Actions
|
|
61
|
+
|
|
62
|
+
- `route: "<outbound-or-group-tag>"`
|
|
63
|
+
- `action: "reject"`
|
|
64
|
+
|
|
65
|
+
Examples:
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
version: 1
|
|
69
|
+
|
|
70
|
+
beforeBuiltins:
|
|
71
|
+
- name: "OpenRouter uses the AI selector"
|
|
72
|
+
domainSuffix: "openrouter.ai"
|
|
73
|
+
route: "AI-Out"
|
|
74
|
+
|
|
75
|
+
- name: "Block a specific UDP port"
|
|
76
|
+
inbound: "in-mixed"
|
|
77
|
+
network: "udp"
|
|
78
|
+
port: 443
|
|
79
|
+
action: "reject"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Guardrails
|
|
83
|
+
|
|
84
|
+
- Every rule must define at least one matcher.
|
|
85
|
+
- Every rule must define exactly one action.
|
|
86
|
+
- Route targets must refer to an existing outbound or selector such as `AI-Out`, `HK`, `US`, `direct`, or `Global`.
|
|
87
|
+
- `ruleSet` matchers must refer to configured and active rule-set tags.
|
|
88
|
+
- User rules cannot be inserted ahead of protected system rules.
|
|
89
|
+
|
|
90
|
+
## Layer 3: Natural language to DSL
|
|
91
|
+
|
|
92
|
+
Natural-language authoring is now implemented as a separate front door. It still follows the same safety model:
|
|
93
|
+
|
|
94
|
+
- prompt -> generated DSL
|
|
95
|
+
- generated DSL -> validated user rules
|
|
96
|
+
- validated user rules -> compiled `sing-box` config
|
|
97
|
+
- optional schedule install only when explicitly requested
|
|
98
|
+
|
|
99
|
+
See:
|
|
100
|
+
|
|
101
|
+
- `/Users/lvyuanfang/Code/SingBoxConfig/docs/natural-language-authoring.md`
|
|
102
|
+
- `/Users/lvyuanfang/Code/SingBoxConfig/docs/rule-templates.md`
|
|
103
|
+
|
|
104
|
+
## Non-Goals for v1
|
|
105
|
+
|
|
106
|
+
- direct natural-language writes to live config
|
|
107
|
+
- arbitrary raw JSON mutation
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Runtime on macOS
|
|
2
|
+
|
|
3
|
+
## Runtime Goal
|
|
4
|
+
|
|
5
|
+
The target runtime is a headless macOS deployment:
|
|
6
|
+
|
|
7
|
+
- `sing-box` installed separately
|
|
8
|
+
- this CLI generates and validates config
|
|
9
|
+
- `launchd` handles periodic updates
|
|
10
|
+
|
|
11
|
+
## Planned Flow
|
|
12
|
+
|
|
13
|
+
1. Generate a staging config
|
|
14
|
+
2. Run `sing-box check -c <staging>`
|
|
15
|
+
3. If valid, publish to the live path
|
|
16
|
+
4. Reload `sing-box`
|
|
17
|
+
5. Keep the last-known-good config for recovery
|
|
18
|
+
|
|
19
|
+
## Current CLI Flow
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
singbox-iac init
|
|
23
|
+
singbox-iac doctor
|
|
24
|
+
singbox-iac build
|
|
25
|
+
singbox-iac verify
|
|
26
|
+
singbox-iac update
|
|
27
|
+
singbox-iac schedule install
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Launchd Notes
|
|
31
|
+
|
|
32
|
+
- In source-tree development, `schedule install` emits a LaunchAgent that runs `node_modules/.bin/tsx src/cli/index.ts update --config <path>`.
|
|
33
|
+
- In built distributions, the same logic emits a LaunchAgent that runs the compiled CLI entrypoint with `node`.
|
|
34
|
+
- Use `--no-load` during testing to validate the generated plist without calling `launchctl bootstrap`.
|
|
35
|
+
|
|
36
|
+
## Why `launchd`
|
|
37
|
+
|
|
38
|
+
For macOS, `launchd` is the correct scheduler primitive. It integrates better with user sessions than `cron` and matches the product's OS target.
|
|
39
|
+
|
|
40
|
+
## Runtime Safety
|
|
41
|
+
|
|
42
|
+
The tool must never overwrite the live config with an unchecked file.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# sing-box Config Primer
|
|
2
|
+
|
|
3
|
+
## Top-Level Areas
|
|
4
|
+
|
|
5
|
+
The generated config will primarily work with:
|
|
6
|
+
|
|
7
|
+
- `dns`
|
|
8
|
+
- `inbounds`
|
|
9
|
+
- `outbounds`
|
|
10
|
+
- `route`
|
|
11
|
+
|
|
12
|
+
## Product Model
|
|
13
|
+
|
|
14
|
+
This project will generate:
|
|
15
|
+
|
|
16
|
+
- fixed inbound listeners
|
|
17
|
+
- dynamic proxy outbounds derived from subscriptions
|
|
18
|
+
- dynamic selector and `urltest` groups
|
|
19
|
+
- rule sets and route rules assembled with stable precedence
|
|
20
|
+
|
|
21
|
+
## Compatibility Direction
|
|
22
|
+
|
|
23
|
+
Target `sing-box` version:
|
|
24
|
+
|
|
25
|
+
- `1.8.x` or newer, with preference for current rule set and rule action formats
|
|
26
|
+
|
|
27
|
+
The implementation should prefer:
|
|
28
|
+
|
|
29
|
+
- external `rule_set` references
|
|
30
|
+
- current route actions
|
|
31
|
+
- avoiding deprecated legacy structures where newer forms exist
|
|
32
|
+
|
|
33
|
+
## Key Invariants
|
|
34
|
+
|
|
35
|
+
- `udp:443` rejection must stay near the top of route processing
|
|
36
|
+
- DNS handling must happen before ordinary traffic policy
|
|
37
|
+
- `in-proxifier` traffic must have absolute precedence over later domain-based rules
|
|
38
|
+
- China direct-routing rules must remain after higher-priority process and AI rules
|
|
39
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Subscription Format Primer
|
|
2
|
+
|
|
3
|
+
## Reality of Provider Subscriptions
|
|
4
|
+
|
|
5
|
+
Provider subscriptions are not a `sing-box` native format. In practice they are ecosystem-specific feeds that commonly look like:
|
|
6
|
+
|
|
7
|
+
1. an HTTP endpoint
|
|
8
|
+
2. returning a Base64-encoded payload
|
|
9
|
+
3. which decodes into plain text
|
|
10
|
+
4. where each line is a share-link URI
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
trojan://password@host:443?sni=example.com#HK-01
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Implication for This Project
|
|
19
|
+
|
|
20
|
+
This project should not treat provider subscriptions as a final configuration format. It should treat them as a source of nodes to parse into an intermediate representation.
|
|
21
|
+
|
|
22
|
+
Pipeline:
|
|
23
|
+
|
|
24
|
+
`fetch -> decode -> parse -> normalize -> compile`
|
|
25
|
+
|
|
26
|
+
## Phase 1 Scope
|
|
27
|
+
|
|
28
|
+
Phase 1 supports:
|
|
29
|
+
|
|
30
|
+
- Base64 line-based subscriptions
|
|
31
|
+
- `trojan://` share links
|
|
32
|
+
|
|
33
|
+
Later phases may support:
|
|
34
|
+
|
|
35
|
+
- `vless://`
|
|
36
|
+
- `vmess://`
|
|
37
|
+
- `hysteria2://`
|
|
38
|
+
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
|
|
3
|
+
subscription:
|
|
4
|
+
url: "https://example.com/subscription"
|
|
5
|
+
format: "base64-lines"
|
|
6
|
+
protocols:
|
|
7
|
+
- trojan
|
|
8
|
+
|
|
9
|
+
output:
|
|
10
|
+
stagingPath: "~/.config/singbox-iac/generated/config.staging.json"
|
|
11
|
+
livePath: "~/.config/sing-box/config.json"
|
|
12
|
+
backupPath: "~/.config/singbox-iac/generated/config.last-known-good.json"
|
|
13
|
+
|
|
14
|
+
runtime:
|
|
15
|
+
checkCommand: "sing-box check -c {{stagingPath}}"
|
|
16
|
+
reload:
|
|
17
|
+
kind: "signal"
|
|
18
|
+
processName: "sing-box"
|
|
19
|
+
signal: "HUP"
|
|
20
|
+
|
|
21
|
+
listeners:
|
|
22
|
+
mixed:
|
|
23
|
+
enabled: true
|
|
24
|
+
listen: "127.0.0.1"
|
|
25
|
+
port: 39097
|
|
26
|
+
proxifier:
|
|
27
|
+
enabled: true
|
|
28
|
+
listen: "127.0.0.1"
|
|
29
|
+
port: 39091
|
|
30
|
+
|
|
31
|
+
ruleSets:
|
|
32
|
+
- tag: "geosite-cn"
|
|
33
|
+
format: "binary"
|
|
34
|
+
type: "local"
|
|
35
|
+
path: "~/.config/sing-box/rule-set/geosite-cn.srs"
|
|
36
|
+
- tag: "geoip-cn"
|
|
37
|
+
format: "binary"
|
|
38
|
+
type: "local"
|
|
39
|
+
path: "~/.config/sing-box/rule-set/geoip-cn.srs"
|
|
40
|
+
- tag: "geosite-google"
|
|
41
|
+
format: "binary"
|
|
42
|
+
type: "local"
|
|
43
|
+
path: "~/.config/sing-box/rule-set/geosite-google.srs"
|
|
44
|
+
- tag: "geosite-google-gemini"
|
|
45
|
+
format: "binary"
|
|
46
|
+
type: "local"
|
|
47
|
+
path: "~/.config/sing-box/rule-set/geosite-google-gemini.srs"
|
|
48
|
+
- tag: "geosite-google-deepmind"
|
|
49
|
+
format: "binary"
|
|
50
|
+
type: "local"
|
|
51
|
+
path: "~/.config/sing-box/rule-set/geosite-google-deepmind.srs"
|
|
52
|
+
- tag: "geosite-anthropic"
|
|
53
|
+
format: "binary"
|
|
54
|
+
type: "local"
|
|
55
|
+
path: "~/.config/sing-box/rule-set/geosite-anthropic.srs"
|
|
56
|
+
- tag: "geosite-github"
|
|
57
|
+
format: "binary"
|
|
58
|
+
type: "local"
|
|
59
|
+
path: "~/.config/sing-box/rule-set/geosite-github.srs"
|
|
60
|
+
- tag: "geosite-github-copilot"
|
|
61
|
+
format: "binary"
|
|
62
|
+
type: "local"
|
|
63
|
+
path: "~/.config/sing-box/rule-set/geosite-github-copilot.srs"
|
|
64
|
+
- tag: "geosite-cursor"
|
|
65
|
+
format: "binary"
|
|
66
|
+
type: "local"
|
|
67
|
+
path: "~/.config/sing-box/rule-set/geosite-cursor.srs"
|
|
68
|
+
- tag: "geosite-figma"
|
|
69
|
+
format: "binary"
|
|
70
|
+
type: "local"
|
|
71
|
+
path: "~/.config/sing-box/rule-set/geosite-figma.srs"
|
|
72
|
+
|
|
73
|
+
groups:
|
|
74
|
+
processProxy:
|
|
75
|
+
type: "selector"
|
|
76
|
+
includes:
|
|
77
|
+
- "US"
|
|
78
|
+
- "SG"
|
|
79
|
+
- "JP"
|
|
80
|
+
- "HK"
|
|
81
|
+
defaultNodePattern: "OnlyAI"
|
|
82
|
+
aiOut:
|
|
83
|
+
type: "selector"
|
|
84
|
+
includes:
|
|
85
|
+
- "HK"
|
|
86
|
+
- "SG"
|
|
87
|
+
- "US"
|
|
88
|
+
- "JP"
|
|
89
|
+
defaultTarget: "HK"
|
|
90
|
+
devCommonOut:
|
|
91
|
+
type: "selector"
|
|
92
|
+
includes:
|
|
93
|
+
- "HK"
|
|
94
|
+
- "SG"
|
|
95
|
+
- "US"
|
|
96
|
+
- "JP"
|
|
97
|
+
defaultTarget: "HK"
|
|
98
|
+
stitchOut:
|
|
99
|
+
type: "selector"
|
|
100
|
+
includes:
|
|
101
|
+
- "US"
|
|
102
|
+
- "SG"
|
|
103
|
+
- "JP"
|
|
104
|
+
defaultTarget: "US"
|
|
105
|
+
global:
|
|
106
|
+
type: "urltest"
|
|
107
|
+
includes:
|
|
108
|
+
- "HK"
|
|
109
|
+
- "SG"
|
|
110
|
+
- "JP"
|
|
111
|
+
- "US"
|
|
112
|
+
|
|
113
|
+
rules:
|
|
114
|
+
userRulesFile: "~/.config/singbox-iac/rules/custom.rules.yaml"
|
|
115
|
+
|
|
116
|
+
verification:
|
|
117
|
+
scenarios:
|
|
118
|
+
- id: "antigravity-auth"
|
|
119
|
+
name: "Antigravity auth via proxifier stays on the OnlyAI US node"
|
|
120
|
+
url: "https://accounts.google.com/favicon.ico"
|
|
121
|
+
inbound: "in-proxifier"
|
|
122
|
+
expectedOutbound: "Process-Proxy"
|
|
123
|
+
- id: "antigravity-oauth"
|
|
124
|
+
name: "Antigravity OAuth metadata via proxifier stays on the OnlyAI US node"
|
|
125
|
+
url: "https://oauth2.googleapis.com/.well-known/openid-configuration"
|
|
126
|
+
inbound: "in-proxifier"
|
|
127
|
+
expectedOutbound: "Process-Proxy"
|
|
128
|
+
- id: "antigravity-docs"
|
|
129
|
+
name: "Antigravity docs via proxifier stay on the OnlyAI US node"
|
|
130
|
+
url: "https://antigravity.google/docs"
|
|
131
|
+
inbound: "in-proxifier"
|
|
132
|
+
expectedOutbound: "Process-Proxy"
|
|
133
|
+
- id: "antigravity-rules-docs"
|
|
134
|
+
name: "Antigravity rules docs via proxifier stay on the OnlyAI US node"
|
|
135
|
+
url: "https://antigravity.google/docs/rules"
|
|
136
|
+
inbound: "in-proxifier"
|
|
137
|
+
expectedOutbound: "Process-Proxy"
|
|
138
|
+
- id: "antigravity-mcp-docs"
|
|
139
|
+
name: "Antigravity MCP docs via proxifier stay on the OnlyAI US node"
|
|
140
|
+
url: "https://antigravity.google/docs/mcp"
|
|
141
|
+
inbound: "in-proxifier"
|
|
142
|
+
expectedOutbound: "Process-Proxy"
|
|
143
|
+
- id: "antigravity-google-apis"
|
|
144
|
+
name: "Antigravity Google API discovery traffic via proxifier stays on the OnlyAI US node"
|
|
145
|
+
url: "https://www.googleapis.com/discovery/v1/apis"
|
|
146
|
+
inbound: "in-proxifier"
|
|
147
|
+
expectedOutbound: "Process-Proxy"
|
|
148
|
+
- id: "stitch-us"
|
|
149
|
+
name: "Google Stitch always uses the dedicated US exit"
|
|
150
|
+
url: "https://stitch.withgoogle.com/favicon.ico"
|
|
151
|
+
inbound: "in-mixed"
|
|
152
|
+
expectedOutbound: "Stitch-Out"
|
|
153
|
+
- id: "cn-direct"
|
|
154
|
+
name: "China traffic stays direct"
|
|
155
|
+
url: "https://www.baidu.com/favicon.ico"
|
|
156
|
+
inbound: "in-mixed"
|
|
157
|
+
expectedOutbound: "direct"
|
|
158
|
+
- id: "chatgpt-hk"
|
|
159
|
+
name: "ChatGPT uses the HK default AI path"
|
|
160
|
+
url: "https://chatgpt.com/favicon.ico"
|
|
161
|
+
inbound: "in-mixed"
|
|
162
|
+
expectedOutbound: "AI-Out"
|
|
163
|
+
- id: "openrouter-hk"
|
|
164
|
+
name: "OpenRouter custom DSL rules send traffic to the HK AI path"
|
|
165
|
+
url: "https://openrouter.ai/favicon.ico"
|
|
166
|
+
inbound: "in-mixed"
|
|
167
|
+
expectedOutbound: "AI-Out"
|
|
168
|
+
- id: "github-hk"
|
|
169
|
+
name: "GitHub uses the HK default developer path"
|
|
170
|
+
url: "https://github.com/favicon.ico"
|
|
171
|
+
inbound: "in-mixed"
|
|
172
|
+
expectedOutbound: "Dev-Common-Out"
|
|
173
|
+
|
|
174
|
+
schedule:
|
|
175
|
+
enabled: true
|
|
176
|
+
intervalMinutes: 30
|
|
177
|
+
|
|
178
|
+
authoring:
|
|
179
|
+
provider: "deterministic"
|
|
180
|
+
timeoutMs: 4000
|
|
181
|
+
# To try a local AI CLI safely, switch provider to "auto" or "exec".
|
|
182
|
+
# provider: "auto"
|
|
183
|
+
# provider: "exec"
|
|
184
|
+
# exec:
|
|
185
|
+
# command: "gemini"
|
|
186
|
+
# args:
|
|
187
|
+
# - "-p"
|
|
188
|
+
# - "{{full_prompt}}"
|
|
189
|
+
#
|
|
190
|
+
# provider: "exec"
|
|
191
|
+
# exec:
|
|
192
|
+
# command: "codebuddy"
|
|
193
|
+
# args:
|
|
194
|
+
# - "--print"
|
|
195
|
+
# - "--output-format"
|
|
196
|
+
# - "json"
|
|
197
|
+
# - "{{full_prompt}}"
|
|
198
|
+
#
|
|
199
|
+
# provider: "exec"
|
|
200
|
+
# exec:
|
|
201
|
+
# command: "codex"
|
|
202
|
+
# args:
|
|
203
|
+
# - "exec"
|
|
204
|
+
# - "--skip-git-repo-check"
|
|
205
|
+
# - "--output-schema"
|
|
206
|
+
# - "{{schema_file}}"
|
|
207
|
+
# - "--output-last-message"
|
|
208
|
+
# - "{{output_file}}"
|
|
209
|
+
# - "{{full_prompt}}"
|
|
210
|
+
#
|
|
211
|
+
# provider: "exec"
|
|
212
|
+
# exec:
|
|
213
|
+
# command: "claude"
|
|
214
|
+
# args:
|
|
215
|
+
# - "-p"
|
|
216
|
+
# - "--output-format"
|
|
217
|
+
# - "json"
|
|
218
|
+
# - "--json-schema"
|
|
219
|
+
# - "{{schema}}"
|
|
220
|
+
# - "{{prompt}}"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
|
|
3
|
+
beforeBuiltins:
|
|
4
|
+
- name: "OpenRouter uses the AI selector"
|
|
5
|
+
domainSuffix:
|
|
6
|
+
- "openrouter.ai"
|
|
7
|
+
route: "AI-Out"
|
|
8
|
+
|
|
9
|
+
- name: "Perplexity uses the AI selector"
|
|
10
|
+
domainSuffix:
|
|
11
|
+
- "perplexity.ai"
|
|
12
|
+
route: "AI-Out"
|
|
13
|
+
|
|
14
|
+
afterBuiltins:
|
|
15
|
+
- name: "Example mainland-only host stays direct"
|
|
16
|
+
domainSuffix:
|
|
17
|
+
- "intranet.example.cn"
|
|
18
|
+
route: "direct"
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@singbox-iac/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Policy-first subscription compiler for sing-box on macOS.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"files": ["dist", "README.md", "docs", "examples"],
|
|
8
|
+
"bin": {
|
|
9
|
+
"singbox-iac": "dist/cli/index.js"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=20.19.0"
|
|
23
|
+
},
|
|
24
|
+
"keywords": ["sing-box", "proxy", "subscription", "macos", "cli", "proxifier"],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc -p tsconfig.json",
|
|
27
|
+
"dev": "tsx src/cli/index.ts",
|
|
28
|
+
"prepare": "npm run build",
|
|
29
|
+
"prepack": "npm run build",
|
|
30
|
+
"release:check": "node ./scripts/release-check.mjs",
|
|
31
|
+
"release:dry-run": "node ./scripts/release-dry-run.mjs",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:watch": "vitest",
|
|
34
|
+
"lint": "biome check .",
|
|
35
|
+
"format": "biome format --write .",
|
|
36
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"commander": "^13.1.0",
|
|
40
|
+
"pino": "^9.7.0",
|
|
41
|
+
"yaml": "^2.8.0",
|
|
42
|
+
"zod": "^3.24.3"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@biomejs/biome": "^1.9.4",
|
|
46
|
+
"@types/node": "^22.15.3",
|
|
47
|
+
"tsx": "^4.19.3",
|
|
48
|
+
"typescript": "^5.8.3",
|
|
49
|
+
"vitest": "^3.1.2"
|
|
50
|
+
}
|
|
51
|
+
}
|