@singbox-iac/cli 0.1.15 → 0.1.17
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/README.md +70 -24
- package/dist/cli/commands/author.d.ts +2 -0
- package/dist/cli/commands/author.js +49 -19
- package/dist/cli/commands/author.js.map +1 -1
- package/dist/cli/commands/build.js +25 -13
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/diagnose.d.ts +2 -0
- package/dist/cli/commands/diagnose.js +120 -0
- package/dist/cli/commands/diagnose.js.map +1 -0
- package/dist/cli/commands/doctor.js +21 -1
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/restart.js +42 -2
- package/dist/cli/commands/restart.js.map +1 -1
- package/dist/cli/commands/rulesets.d.ts +2 -0
- package/dist/cli/commands/rulesets.js +125 -0
- package/dist/cli/commands/rulesets.js.map +1 -0
- package/dist/cli/commands/runtime-watchdog.d.ts +2 -0
- package/dist/cli/commands/runtime-watchdog.js +45 -0
- package/dist/cli/commands/runtime-watchdog.js.map +1 -0
- package/dist/cli/commands/setup.js +190 -20
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/start.js +29 -1
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/commands/status.js +135 -28
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/stop.js +19 -1
- package/dist/cli/commands/stop.js.map +1 -1
- package/dist/cli/commands/use.js +3 -1
- package/dist/cli/commands/use.js.map +1 -1
- package/dist/cli/index.js +12 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/config/schema.d.ts +49 -6
- package/dist/config/schema.js +17 -0
- package/dist/config/schema.js.map +1 -1
- package/dist/modules/authoring/index.js +25 -8
- package/dist/modules/authoring/index.js.map +1 -1
- package/dist/modules/build/index.d.ts +4 -1
- package/dist/modules/build/index.js +17 -4
- package/dist/modules/build/index.js.map +1 -1
- package/dist/modules/bundle-registry/index.d.ts +46 -0
- package/dist/modules/bundle-registry/index.js +650 -0
- package/dist/modules/bundle-registry/index.js.map +1 -0
- package/dist/modules/desktop-runtime/index.d.ts +11 -0
- package/dist/modules/desktop-runtime/index.js +41 -0
- package/dist/modules/desktop-runtime/index.js.map +1 -1
- package/dist/modules/diagnostics/index.d.ts +28 -0
- package/dist/modules/diagnostics/index.js +288 -0
- package/dist/modules/diagnostics/index.js.map +1 -0
- package/dist/modules/layered-authoring/index.d.ts +45 -0
- package/dist/modules/layered-authoring/index.js +549 -0
- package/dist/modules/layered-authoring/index.js.map +1 -0
- package/dist/modules/natural-language/index.d.ts +6 -3
- package/dist/modules/natural-language/index.js +74 -69
- package/dist/modules/natural-language/index.js.map +1 -1
- package/dist/modules/proxifier/index.d.ts +1 -14
- package/dist/modules/proxifier/index.js +10 -139
- package/dist/modules/proxifier/index.js.map +1 -1
- package/dist/modules/rule-set-catalog/index.d.ts +25 -0
- package/dist/modules/rule-set-catalog/index.js +135 -0
- package/dist/modules/rule-set-catalog/index.js.map +1 -0
- package/dist/modules/runtime-watchdog/index.d.ts +73 -0
- package/dist/modules/runtime-watchdog/index.js +532 -0
- package/dist/modules/runtime-watchdog/index.js.map +1 -0
- package/dist/modules/status/index.d.ts +48 -0
- package/dist/modules/status/index.js +254 -23
- package/dist/modules/status/index.js.map +1 -1
- package/dist/modules/system-proxy/index.d.ts +31 -0
- package/dist/modules/system-proxy/index.js +164 -0
- package/dist/modules/system-proxy/index.js.map +1 -0
- package/docs/agent-context.md +131 -0
- package/docs/natural-language-authoring.md +106 -1
- package/docs/proxifier-onboarding.md +15 -4
- package/docs/rule-templates.md +2 -0
- package/docs/runtime-modes.md +84 -0
- package/docs/runtime-on-macos.md +53 -4
- package/examples/builder.config.yaml +60 -0
- package/package.json +3 -2
- package/dist/cli/commands/quickstart.d.ts +0 -2
- package/dist/cli/commands/quickstart.js +0 -54
- package/dist/cli/commands/quickstart.js.map +0 -1
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Agent Context
|
|
2
|
+
|
|
3
|
+
This file is the shared entrypoint for new AI sessions.
|
|
4
|
+
|
|
5
|
+
Read this first. Then follow the task-specific reading path instead of loading the whole repo.
|
|
6
|
+
|
|
7
|
+
## What This Project Is
|
|
8
|
+
|
|
9
|
+
`Singbox IaC` is a developer-focused control plane for `sing-box` on macOS.
|
|
10
|
+
|
|
11
|
+
It is not:
|
|
12
|
+
|
|
13
|
+
- a generic GUI proxy client
|
|
14
|
+
- a pure subscription converter
|
|
15
|
+
- a thin wrapper around raw `sing-box` JSON
|
|
16
|
+
|
|
17
|
+
It is:
|
|
18
|
+
|
|
19
|
+
- a policy-first subscription compiler
|
|
20
|
+
- a runtime verifier and publisher
|
|
21
|
+
- a macOS-oriented desktop/headless control layer
|
|
22
|
+
|
|
23
|
+
## Core Pipeline
|
|
24
|
+
|
|
25
|
+
The current architectural spine is:
|
|
26
|
+
|
|
27
|
+
`subscription / natural language / DSL -> Intent IR -> DNSPlan / VerificationPlan -> compile -> apply transaction -> runtime`
|
|
28
|
+
|
|
29
|
+
This spine is the main constraint for future changes.
|
|
30
|
+
|
|
31
|
+
## Current Product Phase
|
|
32
|
+
|
|
33
|
+
The current priority is to make the existing `system-proxy + process-proxy + real-ip` path stable and trustworthy enough to replace Clash Verge for daily developer use.
|
|
34
|
+
|
|
35
|
+
That means:
|
|
36
|
+
|
|
37
|
+
- strengthen runtime stability before widening the feature surface
|
|
38
|
+
- keep `TUN + FakeIP` as the next major phase, not the current default
|
|
39
|
+
- improve authoring so one-sentence policy changes remain maintainable over time
|
|
40
|
+
|
|
41
|
+
## Current Runtime Strategy
|
|
42
|
+
|
|
43
|
+
Today the default desktop runtime is still:
|
|
44
|
+
|
|
45
|
+
- desktop profile: `system-proxy`
|
|
46
|
+
- process-aware path: `in-proxifier`
|
|
47
|
+
- DNS mode: `real-ip`
|
|
48
|
+
|
|
49
|
+
Why:
|
|
50
|
+
|
|
51
|
+
- it is easier to debug and validate
|
|
52
|
+
- it avoids introducing `TUN + FakeIP` complexity too early
|
|
53
|
+
- it already covers the user's real current path: browser/system-proxy plus Proxifier for process-aware traffic
|
|
54
|
+
|
|
55
|
+
The next phase is expected to add a first-class `tun + fake-ip` mode, but only after the current runtime path is stabilized.
|
|
56
|
+
|
|
57
|
+
## Near-Term Roadmap
|
|
58
|
+
|
|
59
|
+
The next active change proposals are:
|
|
60
|
+
|
|
61
|
+
1. `detect-system-proxy-drift`
|
|
62
|
+
2. `add-runtime-watchdog-and-proxy-reassert`
|
|
63
|
+
3. `recover-from-sleep-and-network-change`
|
|
64
|
+
4. `add-network-diagnostics-command`
|
|
65
|
+
5. `intent-patch-and-layered-authoring`
|
|
66
|
+
6. `smart-site-and-process-bundle-discovery`
|
|
67
|
+
|
|
68
|
+
These changes have higher priority than wider protocol support or UI work.
|
|
69
|
+
|
|
70
|
+
## Product Decisions To Preserve
|
|
71
|
+
|
|
72
|
+
- `sing-box` is still an external binary dependency.
|
|
73
|
+
- `singbox-iac` manages config, verification, publish, and runtime orchestration.
|
|
74
|
+
- `go / use / update` are the main everyday commands.
|
|
75
|
+
- `start / stop / restart / status` are the main runtime commands.
|
|
76
|
+
- `use` should evolve toward patch semantics by default, not full replacement semantics.
|
|
77
|
+
- Built-in site bundles and process bundles are part of the product, not just docs.
|
|
78
|
+
|
|
79
|
+
## Progressive Reading Path
|
|
80
|
+
|
|
81
|
+
### Always Read
|
|
82
|
+
|
|
83
|
+
1. `/Users/lvyuanfang/Code/SingBoxConfig/README.md`
|
|
84
|
+
2. `/Users/lvyuanfang/Code/SingBoxConfig/docs/agent-context.md`
|
|
85
|
+
3. `/Users/lvyuanfang/Code/SingBoxConfig/openspec/project.md`
|
|
86
|
+
|
|
87
|
+
### If You Touch Natural-Language Authoring Or DSL
|
|
88
|
+
|
|
89
|
+
1. `/Users/lvyuanfang/Code/SingBoxConfig/docs/natural-language-authoring.md`
|
|
90
|
+
2. `/Users/lvyuanfang/Code/SingBoxConfig/docs/rules-dsl.md`
|
|
91
|
+
3. `/Users/lvyuanfang/Code/SingBoxConfig/src/domain/intent.ts`
|
|
92
|
+
4. `/Users/lvyuanfang/Code/SingBoxConfig/src/modules/natural-language/index.ts`
|
|
93
|
+
5. `/Users/lvyuanfang/Code/SingBoxConfig/openspec/specs/rule-authoring/spec.md`
|
|
94
|
+
|
|
95
|
+
### If You Touch Runtime Or Diagnostics
|
|
96
|
+
|
|
97
|
+
1. `/Users/lvyuanfang/Code/SingBoxConfig/docs/runtime-on-macos.md`
|
|
98
|
+
2. `/Users/lvyuanfang/Code/SingBoxConfig/docs/runtime-modes.md`
|
|
99
|
+
3. `/Users/lvyuanfang/Code/SingBoxConfig/src/modules/status/index.ts`
|
|
100
|
+
4. `/Users/lvyuanfang/Code/SingBoxConfig/src/modules/desktop-runtime/index.ts`
|
|
101
|
+
5. `/Users/lvyuanfang/Code/SingBoxConfig/openspec/specs/runtime-manager/spec.md`
|
|
102
|
+
|
|
103
|
+
### If You Touch Compiler, DNS, Or Verification
|
|
104
|
+
|
|
105
|
+
1. `/Users/lvyuanfang/Code/SingBoxConfig/docs/sing-box-config-primer.md`
|
|
106
|
+
2. `/Users/lvyuanfang/Code/SingBoxConfig/src/domain/dns-plan.ts`
|
|
107
|
+
3. `/Users/lvyuanfang/Code/SingBoxConfig/src/domain/verification-plan.ts`
|
|
108
|
+
4. `/Users/lvyuanfang/Code/SingBoxConfig/src/modules/compiler/index.ts`
|
|
109
|
+
5. `/Users/lvyuanfang/Code/SingBoxConfig/src/modules/verification-plan/index.ts`
|
|
110
|
+
6. `/Users/lvyuanfang/Code/SingBoxConfig/openspec/specs/singbox-compiler/spec.md`
|
|
111
|
+
7. `/Users/lvyuanfang/Code/SingBoxConfig/openspec/specs/routing-policy/spec.md`
|
|
112
|
+
|
|
113
|
+
### If You Touch Process-Aware Routing
|
|
114
|
+
|
|
115
|
+
1. `/Users/lvyuanfang/Code/SingBoxConfig/docs/proxifier-onboarding.md`
|
|
116
|
+
2. `/Users/lvyuanfang/Code/SingBoxConfig/docs/antigravity-endpoints.md`
|
|
117
|
+
3. `/Users/lvyuanfang/Code/SingBoxConfig/src/modules/proxifier/index.ts`
|
|
118
|
+
|
|
119
|
+
## OpenSpec Discipline
|
|
120
|
+
|
|
121
|
+
- Update `openspec/specs/*` when long-lived behavior changes.
|
|
122
|
+
- Use `openspec/changes/*` for active work.
|
|
123
|
+
- Keep changes small and sequential when touching runtime behavior.
|
|
124
|
+
- Prefer adding fixtures and verification plans before widening heuristics.
|
|
125
|
+
|
|
126
|
+
## Non-Goals For The Current Phase
|
|
127
|
+
|
|
128
|
+
- do not jump straight to `TUN + FakeIP` implementation
|
|
129
|
+
- do not add more protocols just to widen support
|
|
130
|
+
- do not build a heavy GUI shell
|
|
131
|
+
- do not let natural-language authoring silently guess vague routing intent
|
|
@@ -11,6 +11,24 @@ The `author` command is the bridge between a short routing prompt and the full l
|
|
|
11
11
|
|
|
12
12
|
The output still goes through the normal compiler pipeline. Natural language does not mutate `sing-box` JSON directly.
|
|
13
13
|
|
|
14
|
+
## Layered Authoring Semantics
|
|
15
|
+
|
|
16
|
+
There are now two user-facing authoring modes:
|
|
17
|
+
|
|
18
|
+
- `use '<prompt>'`
|
|
19
|
+
Patch the current authored policy set by default. A new prompt should preserve unrelated earlier intent.
|
|
20
|
+
- `use '<prompt>' --replace`
|
|
21
|
+
Explicitly rebuild the authored policy set from this prompt.
|
|
22
|
+
- `author --prompt '<prompt>'`
|
|
23
|
+
Remains the advanced authoring entrypoint and still behaves like an explicit replacement unless a caller opts into patch mode internally.
|
|
24
|
+
|
|
25
|
+
Internally, the workflow now keeps two artifacts next to each other:
|
|
26
|
+
|
|
27
|
+
- the generated YAML DSL at `rules.userRulesFile`
|
|
28
|
+
- a sibling `*.authoring.yaml` file that stores the stable layered authored state
|
|
29
|
+
|
|
30
|
+
The compiler still consumes the merged result. The layered state exists so `use` can remain additive over time without losing earlier authoring intent.
|
|
31
|
+
|
|
14
32
|
## Provider Modes
|
|
15
33
|
|
|
16
34
|
The authoring layer supports four provider modes:
|
|
@@ -53,6 +71,21 @@ Generate rules and build a staging config:
|
|
|
53
71
|
--prompt "开发者网站走香港,视频网站走新加坡"
|
|
54
72
|
```
|
|
55
73
|
|
|
74
|
+
Patch the existing authored policy with one sentence:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
./node_modules/.bin/tsx src/cli/index.ts use \
|
|
78
|
+
'Gemini 走新加坡'
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Force a full replacement instead of patching:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
./node_modules/.bin/tsx src/cli/index.ts use \
|
|
85
|
+
'Google 服务和 GitHub 都走新加坡' \
|
|
86
|
+
--replace
|
|
87
|
+
```
|
|
88
|
+
|
|
56
89
|
Preview what would change without writing files:
|
|
57
90
|
|
|
58
91
|
```bash
|
|
@@ -112,6 +145,8 @@ It works best for:
|
|
|
112
145
|
- process-aware reminders like `IDE 走 proxifier`
|
|
113
146
|
- site classes like `视频网站走美国`
|
|
114
147
|
- named products like `Google Stitch 走美国`
|
|
148
|
+
- named site bundles like `NotebookLM 走美国`
|
|
149
|
+
- named process bundles like `Cursor 走独立入口` or `Codex 走独立入口`
|
|
115
150
|
- short regional intents like `OpenRouter 走香港`
|
|
116
151
|
- schedule phrases like `每45分钟自动更新`
|
|
117
152
|
- one-sentence developer routing like `GitHub 这类开发类走香港,Antigravity 进程级走美国,Gemini 走新加坡`
|
|
@@ -124,7 +159,7 @@ The `author` command does not require the user to think in DSL terms.
|
|
|
124
159
|
For common developer sentences, it now compiles intent across three layers:
|
|
125
160
|
|
|
126
161
|
1. specific site overrides
|
|
127
|
-
Example: `Gemini 走新加坡` becomes
|
|
162
|
+
Example: `Gemini 走新加坡` becomes a site rule before built-ins, preferably via an active official `ruleSet` tag and otherwise via curated fallback domains.
|
|
128
163
|
2. selector default changes
|
|
129
164
|
Example: `开发类都走香港` updates `Dev-Common-Out` to default to `HK`.
|
|
130
165
|
3. verification expectation alignment
|
|
@@ -148,6 +183,72 @@ Common category-style examples:
|
|
|
148
183
|
- `Amazon Prime 和 Apple TV 走新加坡`
|
|
149
184
|
- `视频网站走美国`
|
|
150
185
|
|
|
186
|
+
## Built-In Bundle Discovery
|
|
187
|
+
|
|
188
|
+
The built-in registry is now the primary discovery layer for common products.
|
|
189
|
+
|
|
190
|
+
Examples:
|
|
191
|
+
|
|
192
|
+
- site bundles
|
|
193
|
+
- `NotebookLM`
|
|
194
|
+
- `Gemini`
|
|
195
|
+
- `ChatGPT`
|
|
196
|
+
- `OpenRouter`
|
|
197
|
+
- `Google Stitch`
|
|
198
|
+
- process bundles
|
|
199
|
+
- `Antigravity`
|
|
200
|
+
- `Cursor`
|
|
201
|
+
- `VS Code`
|
|
202
|
+
- `Claude Code`
|
|
203
|
+
- `Gemini CLI`
|
|
204
|
+
- `Codex`
|
|
205
|
+
- `Copilot CLI`
|
|
206
|
+
|
|
207
|
+
When a prompt mentions one of these products, the authoring layer resolves it through the maintained bundle registry before falling back to ad-hoc explicit domains.
|
|
208
|
+
|
|
209
|
+
For site bundles, the resolution path is now:
|
|
210
|
+
|
|
211
|
+
1. prefer active official `sing-geosite` tags already enabled in the current builder config
|
|
212
|
+
2. fall back to curated exact domains and domain suffixes when upstream tags are missing or not enabled locally
|
|
213
|
+
|
|
214
|
+
Examples of official tag-backed bundles:
|
|
215
|
+
|
|
216
|
+
- `ChatGPT` / `OpenAI` -> prefer `geosite-openai`
|
|
217
|
+
- `Perplexity` -> prefer `geosite-perplexity`
|
|
218
|
+
- `YouTube` -> prefer `geosite-youtube`
|
|
219
|
+
- `Netflix` -> prefer `geosite-netflix`
|
|
220
|
+
- `Apple TV` -> prefer `geosite-apple-tvplus`
|
|
221
|
+
|
|
222
|
+
Examples of fallback-first bundles:
|
|
223
|
+
|
|
224
|
+
- `NotebookLM`
|
|
225
|
+
- `OpenRouter`
|
|
226
|
+
- `Google Stitch`
|
|
227
|
+
- `MGTV`
|
|
228
|
+
- `LeetCode`
|
|
229
|
+
- `TradingView`
|
|
230
|
+
- `TypingMind`
|
|
231
|
+
- `Roam Research`
|
|
232
|
+
- `Todoist`
|
|
233
|
+
|
|
234
|
+
Examples:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
./node_modules/.bin/tsx src/cli/index.ts use \
|
|
238
|
+
'NotebookLM 走美国'
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
./node_modules/.bin/tsx src/cli/index.ts use \
|
|
243
|
+
'Antigravity 进程级走美国,GitHub 走香港'
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Inspect current configured and official upstream rule-set coverage:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
./node_modules/.bin/tsx src/cli/index.ts rulesets list --filter openai
|
|
250
|
+
```
|
|
251
|
+
|
|
151
252
|
Supported schedule phrases include:
|
|
152
253
|
|
|
153
254
|
- `每30分钟`
|
|
@@ -166,6 +267,8 @@ Natural language produces three things:
|
|
|
166
267
|
- optional selector default changes
|
|
167
268
|
- optional verification expectation overrides
|
|
168
269
|
|
|
270
|
+
When layered authoring is active, those prompt outputs are merged with the current authored base before the DSL and builder config are rewritten.
|
|
271
|
+
|
|
169
272
|
The command then updates:
|
|
170
273
|
|
|
171
274
|
- `rules.userRulesFile`
|
|
@@ -174,6 +277,8 @@ The command then updates:
|
|
|
174
277
|
- selector defaults such as `AI-Out`, `Dev-Common-Out`, or `Process-Proxy`
|
|
175
278
|
- verification scenario expectations when an existing scenario’s target intent changed
|
|
176
279
|
|
|
280
|
+
and, when using natural-language authoring, also persists a sibling `*.authoring.yaml` state file so future `use` calls can patch instead of replacing the whole authored policy set.
|
|
281
|
+
|
|
177
282
|
and writes a new staging config.
|
|
178
283
|
|
|
179
284
|
With `--preview`, the command does not write anything. Instead it prints:
|
|
@@ -24,12 +24,12 @@ Typical files:
|
|
|
24
24
|
|
|
25
25
|
## Fast Path
|
|
26
26
|
|
|
27
|
-
If your first-run prompt mentions `Proxifier`, `进程级`, `Antigravity`, `Cursor`, or similar process-aware intent, both `
|
|
27
|
+
If your first-run prompt mentions `Proxifier`, `进程级`, `Antigravity`, `Cursor`, or similar process-aware intent, both `go` and `setup --ready` will generate the helper directory automatically.
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
singbox-iac
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
singbox-iac go \
|
|
31
|
+
'<url>' \
|
|
32
|
+
'Antigravity 进程级走美国,GitHub 走香港,国内直连'
|
|
33
33
|
```
|
|
34
34
|
|
|
35
35
|
## Manual Regeneration
|
|
@@ -46,6 +46,17 @@ To see the supported bundle presets:
|
|
|
46
46
|
singbox-iac proxifier bundles
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
The bundle list is now backed by a maintained process bundle registry rather than a docs-only preset list. That registry includes prompt aliases, process matchers, and bundle metadata for tools such as:
|
|
50
|
+
|
|
51
|
+
- `Antigravity`
|
|
52
|
+
- `Cursor`
|
|
53
|
+
- `VS Code`
|
|
54
|
+
- `Claude Code`
|
|
55
|
+
- `Gemini CLI`
|
|
56
|
+
- `Codex`
|
|
57
|
+
- `Copilot CLI`
|
|
58
|
+
- `Developer AI CLI`
|
|
59
|
+
|
|
49
60
|
To inspect one declarative bundle:
|
|
50
61
|
|
|
51
62
|
```bash
|
package/docs/rule-templates.md
CHANGED
|
@@ -9,6 +9,8 @@ Built-in rule templates are intended to cover the repetitive cases that most dev
|
|
|
9
9
|
|
|
10
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
11
|
|
|
12
|
+
They also do not replace built-in site bundles. Templates are coarse category shortcuts; site bundles are product-level discovery objects that now prefer official `ruleSet` tags when possible and fall back to curated domains when necessary.
|
|
13
|
+
|
|
12
14
|
## Current Templates
|
|
13
15
|
|
|
14
16
|
### Developer
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Runtime Modes
|
|
2
|
+
|
|
3
|
+
This document explains the internal runtime planning model used by `singbox-iac`.
|
|
4
|
+
|
|
5
|
+
Users do not need to choose these modes manually in the current phase. The CLI infers them from the onboarding path and prompt shape.
|
|
6
|
+
|
|
7
|
+
## Why Runtime Modes Exist
|
|
8
|
+
|
|
9
|
+
The project already supports several operational shapes:
|
|
10
|
+
|
|
11
|
+
- browser-oriented proxy usage
|
|
12
|
+
- process-aware proxy usage with Proxifier
|
|
13
|
+
- headless recurring update/publish flows
|
|
14
|
+
- an early desktop `tun` profile
|
|
15
|
+
|
|
16
|
+
Without an explicit planning layer, defaults become hard to reason about. `RuntimeMode` keeps those defaults consistent.
|
|
17
|
+
|
|
18
|
+
## Current Runtime Modes
|
|
19
|
+
|
|
20
|
+
### `browser-proxy`
|
|
21
|
+
|
|
22
|
+
Use this when the main path is browser or normal system-proxy traffic.
|
|
23
|
+
|
|
24
|
+
Typical defaults:
|
|
25
|
+
|
|
26
|
+
- desktop runtime profile: `system-proxy`
|
|
27
|
+
- visible verification: browser-oriented sites
|
|
28
|
+
- listener focus: `in-mixed`
|
|
29
|
+
|
|
30
|
+
### `process-proxy`
|
|
31
|
+
|
|
32
|
+
Use this when process-aware routing is a first-class requirement.
|
|
33
|
+
|
|
34
|
+
Typical defaults:
|
|
35
|
+
|
|
36
|
+
- desktop runtime profile: `system-proxy`
|
|
37
|
+
- visible verification: `in-proxifier` plus browser sanity checks
|
|
38
|
+
- listener focus: `in-proxifier` and `in-mixed`
|
|
39
|
+
- Proxifier bundle hints are surfaced
|
|
40
|
+
|
|
41
|
+
This is the current daily-driver path for:
|
|
42
|
+
|
|
43
|
+
- Antigravity
|
|
44
|
+
- developer AI CLIs
|
|
45
|
+
- desktop apps that do not reliably honor macOS system proxy settings
|
|
46
|
+
|
|
47
|
+
### `headless-daemon`
|
|
48
|
+
|
|
49
|
+
Use this when the main need is unattended update / verify / publish behavior.
|
|
50
|
+
|
|
51
|
+
Typical defaults:
|
|
52
|
+
|
|
53
|
+
- no user-facing runtime launch is required
|
|
54
|
+
- schedule and status matter more than browser-driven validation
|
|
55
|
+
|
|
56
|
+
## Desktop Runtime Profiles
|
|
57
|
+
|
|
58
|
+
`RuntimeMode` and desktop runtime profile are related but not identical.
|
|
59
|
+
|
|
60
|
+
### `system-proxy`
|
|
61
|
+
|
|
62
|
+
The CLI emits a `mixed` inbound and lets `sing-box` set and clean macOS system proxy automatically.
|
|
63
|
+
|
|
64
|
+
This is the current default desktop profile because it is simpler to debug and is good enough for the current stabilization phase.
|
|
65
|
+
|
|
66
|
+
### `tun`
|
|
67
|
+
|
|
68
|
+
The CLI can also emit a `tun` inbound with `auto_route`.
|
|
69
|
+
|
|
70
|
+
This is not the current default. It exists as an explicit profile because it is part of the long-term plan, but the project is still prioritizing stability in the current `system-proxy + process-proxy + real-ip` path before making `tun + fake-ip` a primary workflow.
|
|
71
|
+
|
|
72
|
+
## Current Product Direction
|
|
73
|
+
|
|
74
|
+
Short term:
|
|
75
|
+
|
|
76
|
+
- stabilize `system-proxy`
|
|
77
|
+
- improve status, diagnostics, and recovery
|
|
78
|
+
- improve authoring semantics and bundle intelligence
|
|
79
|
+
|
|
80
|
+
Next major phase:
|
|
81
|
+
|
|
82
|
+
- add first-class `tun + fake-ip`
|
|
83
|
+
- validate process-aware routing under TUN
|
|
84
|
+
- reduce dependence on Proxifier for advanced developer workflows
|
package/docs/runtime-on-macos.md
CHANGED
|
@@ -31,13 +31,12 @@ singbox-iac status
|
|
|
31
31
|
Advanced commands remain available for debugging or fine-grained control:
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
singbox-iac
|
|
35
|
-
singbox-iac
|
|
36
|
-
singbox-iac author
|
|
34
|
+
singbox-iac setup --ready
|
|
35
|
+
singbox-iac author --prompt '<一句话需求>' --update
|
|
37
36
|
singbox-iac build
|
|
38
37
|
singbox-iac verify
|
|
38
|
+
singbox-iac proxifier scaffold
|
|
39
39
|
singbox-iac schedule install
|
|
40
|
-
singbox-iac restart
|
|
41
40
|
```
|
|
42
41
|
|
|
43
42
|
## Desktop Runtime Profiles
|
|
@@ -63,12 +62,62 @@ singbox-iac start
|
|
|
63
62
|
singbox-iac stop
|
|
64
63
|
singbox-iac restart
|
|
65
64
|
singbox-iac status
|
|
65
|
+
singbox-iac diagnose
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
- `start` writes or refreshes a dedicated runtime LaunchAgent and boots it
|
|
69
69
|
- `stop` unloads and removes that runtime LaunchAgent
|
|
70
70
|
- `restart` replaces the runtime LaunchAgent
|
|
71
71
|
- `status` reports `sing-box` binary resolution, live config presence, desktop runtime state, system proxy/TUN hints, scheduler state, and recent transactions
|
|
72
|
+
- `diagnose` adds a higher-level local-network and DNS evidence pass on top of `status`
|
|
73
|
+
|
|
74
|
+
Use the commands this way:
|
|
75
|
+
|
|
76
|
+
- `doctor`: first-run or packaging readiness, such as missing binaries, unwritable LaunchAgents, or missing rule-set files
|
|
77
|
+
- `status`: current runtime snapshot, including process state, listeners, system proxy/TUN state, scheduler state, and recent publish history
|
|
78
|
+
- `diagnose`: failure triage when `status` is not enough, because it combines runtime state with best-effort default-route, system DNS, and representative domain resolution evidence
|
|
79
|
+
|
|
80
|
+
For the default `system-proxy` desktop profile, `status` now compares the expected `in-mixed` endpoint against the current macOS proxy state and makes drift explicit.
|
|
81
|
+
|
|
82
|
+
At minimum it distinguishes:
|
|
83
|
+
|
|
84
|
+
- runtime stopped
|
|
85
|
+
- runtime running with proxy active
|
|
86
|
+
- runtime running with proxy drift because the proxy is inactive
|
|
87
|
+
- runtime running with proxy drift because the proxy endpoint no longer matches
|
|
88
|
+
- runtime running with proxy drift because `in-mixed` is no longer accepting connections
|
|
89
|
+
|
|
90
|
+
When drift is present, `status` prints:
|
|
91
|
+
|
|
92
|
+
- the expected `in-mixed` host and port
|
|
93
|
+
- the currently enabled macOS proxy endpoint state
|
|
94
|
+
- a short next-action hint such as restarting the desktop runtime
|
|
95
|
+
|
|
96
|
+
## Runtime Watchdog
|
|
97
|
+
|
|
98
|
+
For the current `system-proxy` desktop profile, `start` also installs a lightweight runtime watchdog LaunchAgent by default.
|
|
99
|
+
|
|
100
|
+
The watchdog currently:
|
|
101
|
+
|
|
102
|
+
- wakes up on a fixed 60-second interval by default
|
|
103
|
+
- checks whether the `sing-box` process is still alive
|
|
104
|
+
- checks whether `in-mixed` is still accepting connections
|
|
105
|
+
- checks whether macOS system proxy state still points to the configured `in-mixed` endpoint
|
|
106
|
+
- reasserts the proxy endpoint when drift is detected but the runtime process is otherwise healthy
|
|
107
|
+
- escalates to a runtime LaunchAgent restart when the runtime is already unhealthy or reassert does not recover the runtime
|
|
108
|
+
|
|
109
|
+
Current limits:
|
|
110
|
+
|
|
111
|
+
- only `system-proxy` desktop mode is covered
|
|
112
|
+
- the watchdog records state changes for `status`, including the last successful reassert time when one exists
|
|
113
|
+
- identical repeated poll results do not rewrite the watchdog state file
|
|
114
|
+
- proxy reassert relies on the normal macOS network service tooling, so failures remain visible in watchdog status and logs instead of being silently ignored
|
|
115
|
+
|
|
116
|
+
Sleep/wake and network-change recovery in the current phase is symptom-driven, not event-hook driven:
|
|
117
|
+
|
|
118
|
+
- there is no second always-on LaunchAgent that subscribes to native macOS wake or network notifications
|
|
119
|
+
- the normal watchdog tick detects the common aftermath within the next polling window
|
|
120
|
+
- runtime restart escalation is guarded by a fixed 5-minute cooldown so repeated failures do not cause a restart every 60 seconds
|
|
72
121
|
|
|
73
122
|
## Launchd Notes
|
|
74
123
|
|
|
@@ -46,6 +46,14 @@ ruleSets:
|
|
|
46
46
|
format: "binary"
|
|
47
47
|
type: "local"
|
|
48
48
|
path: "~/.config/sing-box/rule-set/geoip-cn.srs"
|
|
49
|
+
- tag: "geosite-openai"
|
|
50
|
+
format: "binary"
|
|
51
|
+
type: "local"
|
|
52
|
+
path: "~/.config/sing-box/rule-set/geosite-openai.srs"
|
|
53
|
+
- tag: "geosite-perplexity"
|
|
54
|
+
format: "binary"
|
|
55
|
+
type: "local"
|
|
56
|
+
path: "~/.config/sing-box/rule-set/geosite-perplexity.srs"
|
|
49
57
|
- tag: "geosite-google"
|
|
50
58
|
format: "binary"
|
|
51
59
|
type: "local"
|
|
@@ -78,6 +86,58 @@ ruleSets:
|
|
|
78
86
|
format: "binary"
|
|
79
87
|
type: "local"
|
|
80
88
|
path: "~/.config/sing-box/rule-set/geosite-figma.srs"
|
|
89
|
+
- tag: "geosite-apple"
|
|
90
|
+
format: "binary"
|
|
91
|
+
type: "local"
|
|
92
|
+
path: "~/.config/sing-box/rule-set/geosite-apple.srs"
|
|
93
|
+
- tag: "geosite-apple-tvplus"
|
|
94
|
+
format: "binary"
|
|
95
|
+
type: "local"
|
|
96
|
+
path: "~/.config/sing-box/rule-set/geosite-apple-tvplus.srs"
|
|
97
|
+
- tag: "geosite-youtube"
|
|
98
|
+
format: "binary"
|
|
99
|
+
type: "local"
|
|
100
|
+
path: "~/.config/sing-box/rule-set/geosite-youtube.srs"
|
|
101
|
+
- tag: "geosite-netflix"
|
|
102
|
+
format: "binary"
|
|
103
|
+
type: "local"
|
|
104
|
+
path: "~/.config/sing-box/rule-set/geosite-netflix.srs"
|
|
105
|
+
- tag: "geosite-primevideo"
|
|
106
|
+
format: "binary"
|
|
107
|
+
type: "local"
|
|
108
|
+
path: "~/.config/sing-box/rule-set/geosite-primevideo.srs"
|
|
109
|
+
- tag: "geosite-disney"
|
|
110
|
+
format: "binary"
|
|
111
|
+
type: "local"
|
|
112
|
+
path: "~/.config/sing-box/rule-set/geosite-disney.srs"
|
|
113
|
+
- tag: "geosite-bilibili"
|
|
114
|
+
format: "binary"
|
|
115
|
+
type: "local"
|
|
116
|
+
path: "~/.config/sing-box/rule-set/geosite-bilibili.srs"
|
|
117
|
+
- tag: "geosite-iqiyi"
|
|
118
|
+
format: "binary"
|
|
119
|
+
type: "local"
|
|
120
|
+
path: "~/.config/sing-box/rule-set/geosite-iqiyi.srs"
|
|
121
|
+
- tag: "geosite-youku"
|
|
122
|
+
format: "binary"
|
|
123
|
+
type: "local"
|
|
124
|
+
path: "~/.config/sing-box/rule-set/geosite-youku.srs"
|
|
125
|
+
- tag: "geosite-line"
|
|
126
|
+
format: "binary"
|
|
127
|
+
type: "local"
|
|
128
|
+
path: "~/.config/sing-box/rule-set/geosite-line.srs"
|
|
129
|
+
- tag: "geosite-bbc"
|
|
130
|
+
format: "binary"
|
|
131
|
+
type: "local"
|
|
132
|
+
path: "~/.config/sing-box/rule-set/geosite-bbc.srs"
|
|
133
|
+
- tag: "geosite-microsoft"
|
|
134
|
+
format: "binary"
|
|
135
|
+
type: "local"
|
|
136
|
+
path: "~/.config/sing-box/rule-set/geosite-microsoft.srs"
|
|
137
|
+
- tag: "geosite-xai"
|
|
138
|
+
format: "binary"
|
|
139
|
+
type: "local"
|
|
140
|
+
path: "~/.config/sing-box/rule-set/geosite-xai.srs"
|
|
81
141
|
|
|
82
142
|
groups:
|
|
83
143
|
processProxy:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@singbox-iac/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "Policy-first subscription compiler for sing-box on macOS.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
},
|
|
41
41
|
"keywords": ["sing-box", "proxy", "subscription", "macos", "cli", "proxifier"],
|
|
42
42
|
"scripts": {
|
|
43
|
-
"
|
|
43
|
+
"clean:dist": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
|
|
44
|
+
"build": "npm run clean:dist && tsc -p tsconfig.json",
|
|
44
45
|
"dev": "tsx src/cli/index.ts",
|
|
45
46
|
"prepare": "npm run build",
|
|
46
47
|
"prepack": "npm run build",
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { getDefaultConfigPath, getDefaultRulesPath } from "../command-helpers.js";
|
|
2
|
-
import { runSetupFlow } from "./setup.js";
|
|
3
|
-
export function registerQuickstartCommand(program) {
|
|
4
|
-
program
|
|
5
|
-
.command("quickstart")
|
|
6
|
-
.description("Fast first-run flow: provide a subscription URL and one routing sentence, then prepare, verify, publish, schedule, and optionally run.")
|
|
7
|
-
.requiredOption("--subscription-url <url>", "subscription URL")
|
|
8
|
-
.requiredOption("-p, --prompt <text>", "one-sentence routing intent")
|
|
9
|
-
.option("-c, --config <path>", "path to builder config YAML", getDefaultConfigPath())
|
|
10
|
-
.option("--rules-out <path>", "path to generated custom-rules file", getDefaultRulesPath())
|
|
11
|
-
.option("--provider <provider>", "authoring provider: deterministic, auto, claude, exec")
|
|
12
|
-
.option("--author-timeout-ms <ms>", "timeout for local AI CLI authoring")
|
|
13
|
-
.option("--exec-command <command>", "command for the exec authoring provider")
|
|
14
|
-
.option("--exec-arg <arg>", "append one argument for the exec authoring provider", collectOption, [])
|
|
15
|
-
.option("--sing-box-bin <path>", "path to sing-box binary")
|
|
16
|
-
.option("--chrome-bin <path>", "path to Chrome binary")
|
|
17
|
-
.option("--label <label>", "LaunchAgent label", "org.singbox-iac.update")
|
|
18
|
-
.option("--launch-agents-dir <path>", "override LaunchAgents directory")
|
|
19
|
-
.option("--logs-dir <path>", "override launchd log directory")
|
|
20
|
-
.option("-f, --force", "overwrite generated files during first-time setup")
|
|
21
|
-
.option("--no-run", "prepare and publish, but do not keep sing-box in the foreground")
|
|
22
|
-
.option("--no-browser", "skip opening isolated browser windows during the foreground run")
|
|
23
|
-
.option("--no-load", "write the LaunchAgent without calling launchctl bootstrap")
|
|
24
|
-
.action(async (options) => {
|
|
25
|
-
await runSetupFlow({
|
|
26
|
-
config: options.config,
|
|
27
|
-
rulesOut: options.rulesOut,
|
|
28
|
-
subscriptionUrl: options.subscriptionUrl,
|
|
29
|
-
prompt: options.prompt,
|
|
30
|
-
...(options.provider ? { provider: options.provider } : {}),
|
|
31
|
-
...(options.authorTimeoutMs ? { authorTimeoutMs: options.authorTimeoutMs } : {}),
|
|
32
|
-
...(options.execCommand ? { execCommand: options.execCommand } : {}),
|
|
33
|
-
...(options.execArg.length > 0 ? { execArg: options.execArg } : { execArg: [] }),
|
|
34
|
-
...(options.singBoxBin ? { singBoxBin: options.singBoxBin } : {}),
|
|
35
|
-
...(options.chromeBin ? { chromeBin: options.chromeBin } : {}),
|
|
36
|
-
label: options.label,
|
|
37
|
-
...(options.launchAgentsDir ? { launchAgentsDir: options.launchAgentsDir } : {}),
|
|
38
|
-
...(options.logsDir ? { logsDir: options.logsDir } : {}),
|
|
39
|
-
...(options.force ? { force: options.force } : {}),
|
|
40
|
-
...(options.load !== undefined ? { load: options.load } : {}),
|
|
41
|
-
doctor: true,
|
|
42
|
-
verify: true,
|
|
43
|
-
apply: true,
|
|
44
|
-
ready: true,
|
|
45
|
-
installSchedule: true,
|
|
46
|
-
run: options.run !== false,
|
|
47
|
-
openBrowser: options.browser !== false,
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
function collectOption(value, previous) {
|
|
52
|
-
return [...previous, value];
|
|
53
|
-
}
|
|
54
|
-
//# sourceMappingURL=quickstart.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"quickstart.js","sourceRoot":"","sources":["../../../src/cli/commands/quickstart.ts"],"names":[],"mappings":"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"}
|