@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.
Files changed (80) hide show
  1. package/README.md +70 -24
  2. package/dist/cli/commands/author.d.ts +2 -0
  3. package/dist/cli/commands/author.js +49 -19
  4. package/dist/cli/commands/author.js.map +1 -1
  5. package/dist/cli/commands/build.js +25 -13
  6. package/dist/cli/commands/build.js.map +1 -1
  7. package/dist/cli/commands/diagnose.d.ts +2 -0
  8. package/dist/cli/commands/diagnose.js +120 -0
  9. package/dist/cli/commands/diagnose.js.map +1 -0
  10. package/dist/cli/commands/doctor.js +21 -1
  11. package/dist/cli/commands/doctor.js.map +1 -1
  12. package/dist/cli/commands/restart.js +42 -2
  13. package/dist/cli/commands/restart.js.map +1 -1
  14. package/dist/cli/commands/rulesets.d.ts +2 -0
  15. package/dist/cli/commands/rulesets.js +125 -0
  16. package/dist/cli/commands/rulesets.js.map +1 -0
  17. package/dist/cli/commands/runtime-watchdog.d.ts +2 -0
  18. package/dist/cli/commands/runtime-watchdog.js +45 -0
  19. package/dist/cli/commands/runtime-watchdog.js.map +1 -0
  20. package/dist/cli/commands/setup.js +190 -20
  21. package/dist/cli/commands/setup.js.map +1 -1
  22. package/dist/cli/commands/start.js +29 -1
  23. package/dist/cli/commands/start.js.map +1 -1
  24. package/dist/cli/commands/status.js +135 -28
  25. package/dist/cli/commands/status.js.map +1 -1
  26. package/dist/cli/commands/stop.js +19 -1
  27. package/dist/cli/commands/stop.js.map +1 -1
  28. package/dist/cli/commands/use.js +3 -1
  29. package/dist/cli/commands/use.js.map +1 -1
  30. package/dist/cli/index.js +12 -4
  31. package/dist/cli/index.js.map +1 -1
  32. package/dist/config/schema.d.ts +49 -6
  33. package/dist/config/schema.js +17 -0
  34. package/dist/config/schema.js.map +1 -1
  35. package/dist/modules/authoring/index.js +25 -8
  36. package/dist/modules/authoring/index.js.map +1 -1
  37. package/dist/modules/build/index.d.ts +4 -1
  38. package/dist/modules/build/index.js +17 -4
  39. package/dist/modules/build/index.js.map +1 -1
  40. package/dist/modules/bundle-registry/index.d.ts +46 -0
  41. package/dist/modules/bundle-registry/index.js +650 -0
  42. package/dist/modules/bundle-registry/index.js.map +1 -0
  43. package/dist/modules/desktop-runtime/index.d.ts +11 -0
  44. package/dist/modules/desktop-runtime/index.js +41 -0
  45. package/dist/modules/desktop-runtime/index.js.map +1 -1
  46. package/dist/modules/diagnostics/index.d.ts +28 -0
  47. package/dist/modules/diagnostics/index.js +288 -0
  48. package/dist/modules/diagnostics/index.js.map +1 -0
  49. package/dist/modules/layered-authoring/index.d.ts +45 -0
  50. package/dist/modules/layered-authoring/index.js +549 -0
  51. package/dist/modules/layered-authoring/index.js.map +1 -0
  52. package/dist/modules/natural-language/index.d.ts +6 -3
  53. package/dist/modules/natural-language/index.js +74 -69
  54. package/dist/modules/natural-language/index.js.map +1 -1
  55. package/dist/modules/proxifier/index.d.ts +1 -14
  56. package/dist/modules/proxifier/index.js +10 -139
  57. package/dist/modules/proxifier/index.js.map +1 -1
  58. package/dist/modules/rule-set-catalog/index.d.ts +25 -0
  59. package/dist/modules/rule-set-catalog/index.js +135 -0
  60. package/dist/modules/rule-set-catalog/index.js.map +1 -0
  61. package/dist/modules/runtime-watchdog/index.d.ts +73 -0
  62. package/dist/modules/runtime-watchdog/index.js +532 -0
  63. package/dist/modules/runtime-watchdog/index.js.map +1 -0
  64. package/dist/modules/status/index.d.ts +48 -0
  65. package/dist/modules/status/index.js +254 -23
  66. package/dist/modules/status/index.js.map +1 -1
  67. package/dist/modules/system-proxy/index.d.ts +31 -0
  68. package/dist/modules/system-proxy/index.js +164 -0
  69. package/dist/modules/system-proxy/index.js.map +1 -0
  70. package/docs/agent-context.md +131 -0
  71. package/docs/natural-language-authoring.md +106 -1
  72. package/docs/proxifier-onboarding.md +15 -4
  73. package/docs/rule-templates.md +2 -0
  74. package/docs/runtime-modes.md +84 -0
  75. package/docs/runtime-on-macos.md +53 -4
  76. package/examples/builder.config.yaml +60 -0
  77. package/package.json +3 -2
  78. package/dist/cli/commands/quickstart.d.ts +0 -2
  79. package/dist/cli/commands/quickstart.js +0 -54
  80. 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 an explicit rule before built-ins.
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 `quickstart` and `setup --ready` will generate the helper directory automatically.
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 quickstart \
31
- --subscription-url '<url>' \
32
- --prompt 'Antigravity 进程级走美国,GitHub 走香港,国内直连'
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
@@ -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
@@ -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 quickstart
35
- singbox-iac setup
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.15",
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
- "build": "tsc -p tsconfig.json",
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,2 +0,0 @@
1
- import type { Command } from "commander";
2
- export declare function registerQuickstartCommand(program: Command): void;
@@ -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":"AAEA,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,UAAU,yBAAyB,CAAC,OAAgB;IACxD,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CACV,wIAAwI,CACzI;SACA,cAAc,CAAC,0BAA0B,EAAE,kBAAkB,CAAC;SAC9D,cAAc,CAAC,qBAAqB,EAAE,6BAA6B,CAAC;SACpE,MAAM,CAAC,qBAAqB,EAAE,6BAA6B,EAAE,oBAAoB,EAAE,CAAC;SACpF,MAAM,CAAC,oBAAoB,EAAE,qCAAqC,EAAE,mBAAmB,EAAE,CAAC;SAC1F,MAAM,CAAC,uBAAuB,EAAE,uDAAuD,CAAC;SACxF,MAAM,CAAC,0BAA0B,EAAE,oCAAoC,CAAC;SACxE,MAAM,CAAC,0BAA0B,EAAE,yCAAyC,CAAC;SAC7E,MAAM,CACL,kBAAkB,EAClB,qDAAqD,EACrD,aAAa,EACb,EAAE,CACH;SACA,MAAM,CAAC,uBAAuB,EAAE,yBAAyB,CAAC;SAC1D,MAAM,CAAC,qBAAqB,EAAE,uBAAuB,CAAC;SACtD,MAAM,CAAC,iBAAiB,EAAE,mBAAmB,EAAE,wBAAwB,CAAC;SACxE,MAAM,CAAC,4BAA4B,EAAE,iCAAiC,CAAC;SACvE,MAAM,CAAC,mBAAmB,EAAE,gCAAgC,CAAC;SAC7D,MAAM,CAAC,aAAa,EAAE,mDAAmD,CAAC;SAC1E,MAAM,CAAC,UAAU,EAAE,iEAAiE,CAAC;SACrF,MAAM,CAAC,cAAc,EAAE,iEAAiE,CAAC;SACzF,MAAM,CAAC,WAAW,EAAE,2DAA2D,CAAC;SAChF,MAAM,CAAC,KAAK,EAAE,OAAiC,EAAE,EAAE;QAClD,MAAM,YAAY,CAAC;YACjB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChF,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;YAChF,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACjE,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChF,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACxD,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,IAAI;YACX,eAAe,EAAE,IAAI;YACrB,GAAG,EAAE,OAAO,CAAC,GAAG,KAAK,KAAK;YAC1B,WAAW,EAAE,OAAO,CAAC,OAAO,KAAK,KAAK;SACvC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC;AAsBD,SAAS,aAAa,CAAC,KAAa,EAAE,QAA2B;IAC/D,OAAO,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,CAAC;AAC9B,CAAC"}