@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.
Files changed (133) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +265 -0
  3. package/dist/cli/command-helpers.d.ts +6 -0
  4. package/dist/cli/command-helpers.js +34 -0
  5. package/dist/cli/command-helpers.js.map +1 -0
  6. package/dist/cli/commands/apply.d.ts +2 -0
  7. package/dist/cli/commands/apply.js +32 -0
  8. package/dist/cli/commands/apply.js.map +1 -0
  9. package/dist/cli/commands/author.d.ts +2 -0
  10. package/dist/cli/commands/author.js +194 -0
  11. package/dist/cli/commands/author.js.map +1 -0
  12. package/dist/cli/commands/build.d.ts +2 -0
  13. package/dist/cli/commands/build.js +198 -0
  14. package/dist/cli/commands/build.js.map +1 -0
  15. package/dist/cli/commands/check.d.ts +2 -0
  16. package/dist/cli/commands/check.js +23 -0
  17. package/dist/cli/commands/check.js.map +1 -0
  18. package/dist/cli/commands/doctor.d.ts +2 -0
  19. package/dist/cli/commands/doctor.js +35 -0
  20. package/dist/cli/commands/doctor.js.map +1 -0
  21. package/dist/cli/commands/init.d.ts +2 -0
  22. package/dist/cli/commands/init.js +23 -0
  23. package/dist/cli/commands/init.js.map +1 -0
  24. package/dist/cli/commands/reload.d.ts +2 -0
  25. package/dist/cli/commands/reload.js +21 -0
  26. package/dist/cli/commands/reload.js.map +1 -0
  27. package/dist/cli/commands/run.d.ts +2 -0
  28. package/dist/cli/commands/run.js +25 -0
  29. package/dist/cli/commands/run.js.map +1 -0
  30. package/dist/cli/commands/schedule.d.ts +2 -0
  31. package/dist/cli/commands/schedule.js +77 -0
  32. package/dist/cli/commands/schedule.js.map +1 -0
  33. package/dist/cli/commands/templates.d.ts +2 -0
  34. package/dist/cli/commands/templates.js +34 -0
  35. package/dist/cli/commands/templates.js.map +1 -0
  36. package/dist/cli/commands/update.d.ts +2 -0
  37. package/dist/cli/commands/update.js +52 -0
  38. package/dist/cli/commands/update.js.map +1 -0
  39. package/dist/cli/commands/verify.d.ts +2 -0
  40. package/dist/cli/commands/verify.js +49 -0
  41. package/dist/cli/commands/verify.js.map +1 -0
  42. package/dist/cli/index.d.ts +5 -0
  43. package/dist/cli/index.js +55 -0
  44. package/dist/cli/index.js.map +1 -0
  45. package/dist/config/load-config.d.ts +2 -0
  46. package/dist/config/load-config.js +29 -0
  47. package/dist/config/load-config.js.map +1 -0
  48. package/dist/config/schema.d.ts +548 -0
  49. package/dist/config/schema.js +92 -0
  50. package/dist/config/schema.js.map +1 -0
  51. package/dist/domain/config.d.ts +8 -0
  52. package/dist/domain/config.js +2 -0
  53. package/dist/domain/config.js.map +1 -0
  54. package/dist/domain/node.d.ts +11 -0
  55. package/dist/domain/node.js +2 -0
  56. package/dist/domain/node.js.map +1 -0
  57. package/dist/domain/outbound.d.ts +15 -0
  58. package/dist/domain/outbound.js +2 -0
  59. package/dist/domain/outbound.js.map +1 -0
  60. package/dist/domain/subscription.d.ts +6 -0
  61. package/dist/domain/subscription.js +2 -0
  62. package/dist/domain/subscription.js.map +1 -0
  63. package/dist/index.d.ts +1 -0
  64. package/dist/index.js +2 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/modules/authoring/index.d.ts +41 -0
  67. package/dist/modules/authoring/index.js +596 -0
  68. package/dist/modules/authoring/index.js.map +1 -0
  69. package/dist/modules/build/index.d.ts +13 -0
  70. package/dist/modules/build/index.js +39 -0
  71. package/dist/modules/build/index.js.map +1 -0
  72. package/dist/modules/compiler/index.d.ts +10 -0
  73. package/dist/modules/compiler/index.js +305 -0
  74. package/dist/modules/compiler/index.js.map +1 -0
  75. package/dist/modules/doctor/index.d.ts +17 -0
  76. package/dist/modules/doctor/index.js +89 -0
  77. package/dist/modules/doctor/index.js.map +1 -0
  78. package/dist/modules/fetcher/index.d.ts +4 -0
  79. package/dist/modules/fetcher/index.js +42 -0
  80. package/dist/modules/fetcher/index.js.map +1 -0
  81. package/dist/modules/init/index.d.ts +12 -0
  82. package/dist/modules/init/index.js +41 -0
  83. package/dist/modules/init/index.js.map +1 -0
  84. package/dist/modules/manager/index.d.ts +29 -0
  85. package/dist/modules/manager/index.js +133 -0
  86. package/dist/modules/manager/index.js.map +1 -0
  87. package/dist/modules/natural-language/index.d.ts +54 -0
  88. package/dist/modules/natural-language/index.js +458 -0
  89. package/dist/modules/natural-language/index.js.map +1 -0
  90. package/dist/modules/parser/index.d.ts +10 -0
  91. package/dist/modules/parser/index.js +113 -0
  92. package/dist/modules/parser/index.js.map +1 -0
  93. package/dist/modules/preview/index.d.ts +22 -0
  94. package/dist/modules/preview/index.js +141 -0
  95. package/dist/modules/preview/index.js.map +1 -0
  96. package/dist/modules/rule-templates/index.d.ts +15 -0
  97. package/dist/modules/rule-templates/index.js +200 -0
  98. package/dist/modules/rule-templates/index.js.map +1 -0
  99. package/dist/modules/schedule/index.d.ts +32 -0
  100. package/dist/modules/schedule/index.js +155 -0
  101. package/dist/modules/schedule/index.js.map +1 -0
  102. package/dist/modules/update/index.d.ts +22 -0
  103. package/dist/modules/update/index.js +38 -0
  104. package/dist/modules/update/index.js.map +1 -0
  105. package/dist/modules/user-rules/index.d.ts +18 -0
  106. package/dist/modules/user-rules/index.js +98 -0
  107. package/dist/modules/user-rules/index.js.map +1 -0
  108. package/dist/modules/verification/index.d.ts +49 -0
  109. package/dist/modules/verification/index.js +432 -0
  110. package/dist/modules/verification/index.js.map +1 -0
  111. package/dist/shared/errors.d.ts +3 -0
  112. package/dist/shared/errors.js +7 -0
  113. package/dist/shared/errors.js.map +1 -0
  114. package/dist/shared/logger.d.ts +2 -0
  115. package/dist/shared/logger.js +5 -0
  116. package/dist/shared/logger.js.map +1 -0
  117. package/dist/shared/result.d.ts +11 -0
  118. package/dist/shared/result.js +7 -0
  119. package/dist/shared/result.js.map +1 -0
  120. package/docs/antigravity-endpoints.md +77 -0
  121. package/docs/competitive-landscape.md +45 -0
  122. package/docs/development-workflow.md +80 -0
  123. package/docs/natural-language-authoring.md +376 -0
  124. package/docs/positioning.md +42 -0
  125. package/docs/releasing.md +72 -0
  126. package/docs/rule-templates.md +122 -0
  127. package/docs/rules-dsl.md +107 -0
  128. package/docs/runtime-on-macos.md +42 -0
  129. package/docs/sing-box-config-primer.md +39 -0
  130. package/docs/subscription-format.md +38 -0
  131. package/examples/builder.config.yaml +220 -0
  132. package/examples/custom.rules.yaml +18 -0
  133. package/package.json +51 -0
@@ -0,0 +1,7 @@
1
+ export function ok(value) {
2
+ return { ok: true, value };
3
+ }
4
+ export function err(error) {
5
+ return { ok: false, error };
6
+ }
7
+ //# sourceMappingURL=result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/shared/result.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,EAAE,CAAI,KAAQ;IAC5B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,GAAG,CAAI,KAAQ;IAC7B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,77 @@
1
+ # Antigravity Endpoint Notes
2
+
3
+ These notes were derived from the installed macOS app bundle at `/Applications/Antigravity.app` and local logs under `/Users/lvyuanfang/Library/Application Support/Antigravity/logs`.
4
+
5
+ ## App Identity
6
+
7
+ - Bundle identifier: `com.google.antigravity`
8
+ - Product links in `product.json`:
9
+ - `https://antigravity.google/docs`
10
+ - `https://antigravity.google/docs/rules`
11
+ - `https://antigravity.google/docs/mcp`
12
+ - `https://antigravity.google/support`
13
+
14
+ ## Observed Or Referenced Google Endpoints
15
+
16
+ The installed app and local logs reference these Google-hosted domains that are relevant for routing verification:
17
+
18
+ - `antigravity.google`
19
+ - `accounts.google.com`
20
+ - `oauth2.googleapis.com`
21
+ - `clients2.google.com`
22
+ - `android.clients.google.com`
23
+ - `apis.google.com`
24
+ - `aiplatform.googleapis.com`
25
+ - `cloud.google.com`
26
+ - `daily-cloudcode-pa.googleapis.com`
27
+ - `firebase.googleapis.com`
28
+ - `fonts.googleapis.com`
29
+ - `fonts.gstatic.com`
30
+ - `lh3.googleusercontent.com`
31
+ - `play.googleapis.com`
32
+ - `antigravity-unleash.goog`
33
+ - `www.googleapis.com`
34
+ - `www.gstatic.com`
35
+
36
+ ## Why These Matter
37
+
38
+ - `accounts.google.com` is a good auth-path verification target for `in-proxifier`.
39
+ - `oauth2.googleapis.com` is a good OAuth metadata verification target for `in-proxifier`.
40
+ - `antigravity.google` is a good product-surface verification target for `in-proxifier`.
41
+ - `www.googleapis.com` is a stable Google API surface that appeared in real runtime logs and is suitable for verification.
42
+ - `daily-cloudcode-pa.googleapis.com` appears during real model streaming, but it is less stable as a browser verification target and is better tracked as an observed runtime dependency.
43
+ - `play.googleapis.com`, `antigravity-unleash.goog`, `lh3.googleusercontent.com`, `clients2.google.com`, `android.clients.google.com`, `fonts.googleapis.com`, and `www.gstatic.com` regularly appear as supporting traffic during a real Antigravity session.
44
+
45
+ ## User Journey Buckets
46
+
47
+ ### Product Surfaces
48
+
49
+ - `https://antigravity.google/docs`
50
+ - `https://antigravity.google/docs/rules`
51
+ - `https://antigravity.google/docs/mcp`
52
+
53
+ ### Auth And Session Bootstrap
54
+
55
+ - `https://accounts.google.com/favicon.ico`
56
+ - `https://oauth2.googleapis.com/.well-known/openid-configuration`
57
+
58
+ ### Control And API Surfaces
59
+
60
+ - `https://www.googleapis.com/discovery/v1/apis`
61
+ - Observed at runtime, but not used as fixed browser probes:
62
+ - `daily-cloudcode-pa.googleapis.com`
63
+ - `play.googleapis.com`
64
+ - `antigravity-unleash.goog`
65
+
66
+ ## Current Verification Usage
67
+
68
+ The current verification harness uses:
69
+
70
+ - `https://accounts.google.com/favicon.ico`
71
+ - `https://oauth2.googleapis.com/.well-known/openid-configuration`
72
+ - `https://antigravity.google/docs`
73
+ - `https://antigravity.google/docs/rules`
74
+ - `https://antigravity.google/docs/mcp`
75
+ - `https://www.googleapis.com/discovery/v1/apis`
76
+
77
+ All of these are routed through `in-proxifier` and must land on the fixed US `OnlyAI` node.
@@ -0,0 +1,45 @@
1
+ # Competitive Landscape
2
+
3
+ ## Existing Categories
4
+
5
+ ### Generic subscription converters
6
+
7
+ These tools convert provider subscriptions into one or more target client formats. They are useful, but their center of gravity is format conversion, not runtime-safe policy compilation.
8
+
9
+ Typical limitations:
10
+
11
+ - route precedence is often inherited from templates
12
+ - process-aware routing is not a first-class use case
13
+ - runtime validation and staged publish are usually outside scope
14
+
15
+ ### GUI clients and launchers
16
+
17
+ These tools optimize for usability and visual management. They are convenient but tend to hide merge order, effective config structure, and runtime rollout details.
18
+
19
+ Typical limitations:
20
+
21
+ - higher idle resource usage
22
+ - config merge logic is harder to audit
23
+ - process routing and custom listeners become brittle over time
24
+
25
+ ### Library-style generators
26
+
27
+ These projects expose config generation as an SDK or library. They can be useful implementation references but are not the final product shape targeted here.
28
+
29
+ Typical limitations:
30
+
31
+ - not macOS workflow-oriented
32
+ - no opinionated CLI lifecycle
33
+ - no declarative policy authoring model
34
+
35
+ ## Planned Differentiators
36
+
37
+ `Sing-box IaC Builder` should differentiate on:
38
+
39
+ - policy-first compilation
40
+ - macOS headless operation
41
+ - explicit staged rollout
42
+ - route ordering invariants
43
+ - user-facing rule DSL
44
+ - future natural-language rule authoring with DSL confirmation
45
+
@@ -0,0 +1,80 @@
1
+ # Development Workflow
2
+
3
+ ## Goal
4
+
5
+ Use OpenSpec for specification control and Superpowers for execution discipline.
6
+
7
+ ## Working Model
8
+
9
+ - OpenSpec answers: what behavior should exist.
10
+ - Superpowers answers: how this change will be executed safely.
11
+
12
+ ## Standard Flow for Each Phase
13
+
14
+ 1. Clarify scope and non-goals.
15
+ 2. Create or update `openspec/changes/<change-id>/proposal.md`.
16
+ 3. Write `design.md` only for the important decisions.
17
+ 4. Write `tasks.md` with small, executable tasks.
18
+ 5. Update the relevant capability specs under `openspec/specs/`.
19
+ 6. Write fixtures or tests before implementation where behavior is concrete.
20
+ 7. Implement in small batches.
21
+ 8. Run validation.
22
+ 9. Fold approved behavior back into the long-lived specs.
23
+
24
+ ## MVP Path
25
+
26
+ For self-hosting and early dogfooding, prefer a vertical slice when the full roadmap would delay first use too much.
27
+
28
+ Recommended first slice:
29
+
30
+ 1. parse Trojan subscriptions
31
+ 2. compile a minimal usable `sing-box` config
32
+ 3. expose a `build` command
33
+ 4. test locally with manual `sing-box check`
34
+
35
+ This keeps OpenSpec lightweight:
36
+
37
+ - use one MVP-oriented change proposal
38
+ - keep specs focused on acceptance criteria and invariants
39
+ - avoid writing extra design documents unless a decision is genuinely hard to reverse
40
+
41
+ ## Phase Guidance
42
+
43
+ ### Phase 0
44
+
45
+ Use OpenSpec to define project constraints, architecture, and capability boundaries. Use Superpowers to enforce small setup tasks and avoid jumping into parser or compiler code too early.
46
+
47
+ ### Phase 1
48
+
49
+ Use OpenSpec to lock parser input, output, and failure semantics. Use Superpowers to drive fixture-first implementation and edge-case coverage.
50
+
51
+ If the immediate goal is self-use, combine the parser with a minimal compiler and `build` command under a vertical MVP change before returning to the broader phase roadmap.
52
+
53
+ ### Phase 2
54
+
55
+ Use OpenSpec to define compiler invariants and route priority. Use Superpowers to break the compiler into template assembly, grouping, and route generation tasks.
56
+
57
+ ### Phase 3
58
+
59
+ Use OpenSpec to define CLI contracts and fetch behavior. Use Superpowers to implement command-by-command instead of building the whole pipeline as one opaque step.
60
+
61
+ ### Phase 4
62
+
63
+ Use OpenSpec to define runtime state transitions and safety rules. Use Superpowers to implement validation, publish, reload, and rollback in explicit steps.
64
+
65
+ ### Future Rule Authoring
66
+
67
+ Use OpenSpec to define the DSL grammar and compiler guarantees. Use Superpowers to keep natural-language support behind a preview-and-confirm flow.
68
+
69
+ ## Review Focus
70
+
71
+ Before closing a change, verify:
72
+
73
+ - specs still match implementation
74
+ - error handling is defensive
75
+ - route ordering invariants are protected
76
+ - user-configurable layers cannot bypass system invariants silently
77
+
78
+ ## Current Recommendation
79
+
80
+ The next implementation step for this repository is `parse-and-build-first-config`. It is the shortest path from specification baseline to a locally usable config generator.
@@ -0,0 +1,376 @@
1
+ # Natural-Language Authoring
2
+
3
+ The `author` command is the bridge between a short routing prompt and the full local workflow:
4
+
5
+ 1. turn a prompt into the YAML rules DSL
6
+ 2. write the generated rules file
7
+ 3. update the builder config to point at that rules file
8
+ 4. build a new `sing-box` config
9
+ 5. optionally install a `launchd` schedule that runs `update`
10
+ 6. optionally run `update` immediately from the same command
11
+
12
+ The output still goes through the normal compiler pipeline. Natural language does not mutate `sing-box` JSON directly.
13
+
14
+ ## Provider Modes
15
+
16
+ The authoring layer supports four provider modes:
17
+
18
+ - `deterministic`
19
+ The built-in keyword/template parser. This is the default because it is fast, testable, and does not depend on any external model.
20
+
21
+ - `auto`
22
+ Try a supported local AI CLI first, then fall back to the deterministic parser if the local CLI is unavailable, times out, or returns invalid output.
23
+
24
+ - `claude`
25
+ Use the local `claude` CLI directly for structured JSON plan generation.
26
+
27
+ - `exec`
28
+ Use any local command that can print a JSON authoring plan to stdout or write one to a file.
29
+
30
+ Recommended default:
31
+
32
+ ```yaml
33
+ authoring:
34
+ provider: "deterministic"
35
+ timeoutMs: 4000
36
+ ```
37
+
38
+ Opt in to local AI CLI probing:
39
+
40
+ ```yaml
41
+ authoring:
42
+ provider: "auto"
43
+ timeoutMs: 1000
44
+ ```
45
+
46
+ ## One-Line Examples
47
+
48
+ Generate rules and build a staging config:
49
+
50
+ ```bash
51
+ ./node_modules/.bin/tsx src/cli/index.ts author \
52
+ --config ./builder.config.local.yaml \
53
+ --prompt "开发者网站走香港,视频网站走新加坡"
54
+ ```
55
+
56
+ Preview what would change without writing files:
57
+
58
+ ```bash
59
+ ./node_modules/.bin/tsx src/cli/index.ts author \
60
+ --config ./builder.config.local.yaml \
61
+ --provider deterministic \
62
+ --prompt "OpenRouter 走香港,YouTube Netflix 走美国,每60分钟自动更新" \
63
+ --preview
64
+ ```
65
+
66
+ Generate rules, build a config, and install a schedule:
67
+
68
+ ```bash
69
+ ./node_modules/.bin/tsx src/cli/index.ts author \
70
+ --config ./builder.config.local.yaml \
71
+ --prompt "OpenRouter 和 Perplexity 走香港,YouTube Netflix 走美国,每45分钟自动更新" \
72
+ --install-schedule
73
+ ```
74
+
75
+ Generate rules and immediately run `build -> verify -> publish`:
76
+
77
+ ```bash
78
+ ./node_modules/.bin/tsx src/cli/index.ts author \
79
+ --config ./builder.config.local.yaml \
80
+ --provider deterministic \
81
+ --prompt "Google 服务和 GitHub 这类开发类都走香港,Gemini 走新加坡,Antigravity 进程级走美国,每30分钟自动更新" \
82
+ --update
83
+ ```
84
+
85
+ Force a local AI CLI attempt first, then fall back safely if needed:
86
+
87
+ ```bash
88
+ ./node_modules/.bin/tsx src/cli/index.ts author \
89
+ --config ./builder.config.local.yaml \
90
+ --provider auto \
91
+ --author-timeout-ms 1000 \
92
+ --prompt "开发者网站走香港,AI 工具走香港,视频网站走新加坡,每45分钟自动更新"
93
+ ```
94
+
95
+ Use a local subscription fixture instead of fetching remotely:
96
+
97
+ ```bash
98
+ ./node_modules/.bin/tsx src/cli/index.ts author \
99
+ --config ./builder.config.local.yaml \
100
+ --prompt "国内视频网站直连,AI 工具走香港,每2小时自动更新" \
101
+ --subscription-file ./tests/fixtures/subscriptions/trojan-sample.b64 \
102
+ --install-schedule \
103
+ --no-load
104
+ ```
105
+
106
+ ## What the Prompt Can Express
107
+
108
+ This layer intentionally aims at simple intent, not full policy programming.
109
+
110
+ It works best for:
111
+
112
+ - process-aware reminders like `IDE 走 proxifier`
113
+ - site classes like `视频网站走美国`
114
+ - named products like `Google Stitch 走美国`
115
+ - short regional intents like `OpenRouter 走香港`
116
+ - schedule phrases like `每45分钟自动更新`
117
+ - one-sentence developer routing like `GitHub 这类开发类走香港,Antigravity 进程级走美国,Gemini 走新加坡`
118
+ - mainstream subscription vocabulary like `Google 服务`, `Apple 服务`, `Amazon Prime`, `Apple TV`
119
+
120
+ ## Intent-First Behavior
121
+
122
+ The `author` command does not require the user to think in DSL terms.
123
+
124
+ For common developer sentences, it now compiles intent across three layers:
125
+
126
+ 1. specific site overrides
127
+ Example: `Gemini 走新加坡` becomes an explicit rule before built-ins.
128
+ 2. selector default changes
129
+ Example: `开发类都走香港` updates `Dev-Common-Out` to default to `HK`.
130
+ 3. verification expectation alignment
131
+ Example: if the configured verification URL for Gemini previously expected `AI-Out -> HK`, it will be updated so runtime verification now expects `SG`.
132
+
133
+ That keeps `author -> build -> verify` truthful even after intent-driven changes.
134
+
135
+ Example:
136
+
137
+ ```bash
138
+ ./node_modules/.bin/tsx src/cli/index.ts author \
139
+ --config ./builder.config.local.yaml \
140
+ --provider deterministic \
141
+ --prompt "GitHub 这类开发类都走香港出口,Antigravity 进程级都走独立的入口并路由到美国节点,Gemini 都出口到新加坡,每30分钟自动更新"
142
+ ```
143
+
144
+ Common category-style examples:
145
+
146
+ - `Google 服务和 GitHub 这类开发类都走香港`
147
+ - `Apple 服务走香港`
148
+ - `Amazon Prime 和 Apple TV 走新加坡`
149
+ - `视频网站走美国`
150
+
151
+ Supported schedule phrases include:
152
+
153
+ - `每30分钟`
154
+ - `每45分钟`
155
+ - `每2小时`
156
+ - `schedule`
157
+ - `launchd`
158
+
159
+ ## Output Model
160
+
161
+ Natural language produces three things:
162
+
163
+ - generated user rules
164
+ - optional inferred templates
165
+ - optional schedule interval
166
+ - optional selector default changes
167
+ - optional verification expectation overrides
168
+
169
+ The command then updates:
170
+
171
+ - `rules.userRulesFile`
172
+ - `schedule.enabled`
173
+ - `schedule.intervalMinutes`
174
+ - selector defaults such as `AI-Out`, `Dev-Common-Out`, or `Process-Proxy`
175
+ - verification scenario expectations when an existing scenario’s target intent changed
176
+
177
+ and writes a new staging config.
178
+
179
+ With `--preview`, the command does not write anything. Instead it prints:
180
+
181
+ - rules diff
182
+ - builder config diff
183
+ - staging config diff
184
+
185
+ This is the safest way to inspect what a prompt or local AI CLI would change before touching your local files.
186
+
187
+ ## Exec Provider
188
+
189
+ The `exec` provider is the escape hatch for developer machines that already have local AI tooling.
190
+ This is the recommended way to integrate most AI CLIs beyond the built-in `claude` adapter.
191
+
192
+ The command receives:
193
+
194
+ - `SINGBOX_IAC_AUTHOR_PROMPT`
195
+ - `SINGBOX_IAC_AUTHOR_SCHEMA`
196
+ - `SINGBOX_IAC_AUTHOR_CONTEXT`
197
+
198
+ Arguments may use placeholders:
199
+
200
+ - `{{prompt}}`
201
+ - `{{schema}}`
202
+ - `{{context_json}}`
203
+ - `{{full_prompt}}`
204
+ - `{{schema_file}}`
205
+ - `{{output_file}}`
206
+
207
+ Environment variables are also injected for wrapper scripts:
208
+
209
+ - `SINGBOX_IAC_AUTHOR_PROMPT`
210
+ - `SINGBOX_IAC_AUTHOR_SCHEMA`
211
+ - `SINGBOX_IAC_AUTHOR_CONTEXT`
212
+ - `SINGBOX_IAC_AUTHOR_FULL_PROMPT`
213
+ - `SINGBOX_IAC_AUTHOR_SCHEMA_FILE`
214
+ - `SINGBOX_IAC_AUTHOR_OUTPUT_FILE`
215
+
216
+ The command must print a JSON object that matches the internal plan schema:
217
+
218
+ ```json
219
+ {
220
+ "templateIds": ["developer-ai-sites", "video-sg"],
221
+ "beforeBuiltins": [],
222
+ "afterBuiltins": [],
223
+ "notes": [],
224
+ "scheduleIntervalMinutes": 45
225
+ }
226
+ ```
227
+
228
+ If the CLI is noisy, the provider will also accept:
229
+
230
+ - a fenced ````json` block that contains the plan
231
+ - a longer text response with one balanced JSON object inside it
232
+ - an output file path populated through `{{output_file}}`
233
+
234
+ ## Common Local AI CLI Integrations
235
+
236
+ The goal is not to hard-code every AI CLI on the market. The goal is to make almost all of them usable through one bounded adapter.
237
+
238
+ Recommended support model:
239
+
240
+ - stable built-ins:
241
+ - `claude`
242
+ - generic `exec` integrations:
243
+ - `gemini`
244
+ - `codebuddy`
245
+ - `codex`
246
+ - `opencode`
247
+ - `qodercli` / `qoder`
248
+ - tooling-only or editor launchers:
249
+ - `trae`
250
+
251
+ ### Gemini CLI
252
+
253
+ Best when Gemini is already logged in locally and you want a lightweight prompt-only integration.
254
+
255
+ ```yaml
256
+ authoring:
257
+ provider: "exec"
258
+ timeoutMs: 4000
259
+ exec:
260
+ command: "gemini"
261
+ args:
262
+ - "-p"
263
+ - "{{full_prompt}}"
264
+ ```
265
+
266
+ ### CodeBuddy CLI
267
+
268
+ `codebuddy` and `cbc` expose `--print` and `--output-format json`, which makes them strong `exec` candidates.
269
+
270
+ ```yaml
271
+ authoring:
272
+ provider: "exec"
273
+ timeoutMs: 4000
274
+ exec:
275
+ command: "codebuddy"
276
+ args:
277
+ - "--print"
278
+ - "--output-format"
279
+ - "json"
280
+ - "{{full_prompt}}"
281
+ ```
282
+
283
+ ### Codex CLI
284
+
285
+ Codex already supports schema files and writing the final response to a file. That maps well onto `{{schema_file}}` and `{{output_file}}`.
286
+
287
+ ```yaml
288
+ authoring:
289
+ provider: "exec"
290
+ timeoutMs: 8000
291
+ exec:
292
+ command: "codex"
293
+ args:
294
+ - "exec"
295
+ - "--skip-git-repo-check"
296
+ - "--output-schema"
297
+ - "{{schema_file}}"
298
+ - "--output-last-message"
299
+ - "{{output_file}}"
300
+ - "{{full_prompt}}"
301
+ ```
302
+
303
+ ### OpenCode
304
+
305
+ `opencode run` supports a non-interactive message flow and a JSON event mode. Use a small wrapper if the raw JSON event stream is too noisy.
306
+
307
+ ```yaml
308
+ authoring:
309
+ provider: "exec"
310
+ timeoutMs: 8000
311
+ exec:
312
+ command: "opencode"
313
+ args:
314
+ - "run"
315
+ - "--format"
316
+ - "json"
317
+ - "{{full_prompt}}"
318
+ ```
319
+
320
+ ### Qoder CLI
321
+
322
+ If Qoder is installed locally, prefer a wrapper script or a direct print/json mode if your local version exposes one.
323
+
324
+ ```yaml
325
+ authoring:
326
+ provider: "exec"
327
+ timeoutMs: 8000
328
+ exec:
329
+ command: "qodercli"
330
+ args:
331
+ - "--print"
332
+ - "--output-format"
333
+ - "json"
334
+ - "{{full_prompt}}"
335
+ ```
336
+
337
+ ### Wrapper Pattern
338
+
339
+ Some CLIs will not print the exact JSON plan directly. In that case, use a tiny local wrapper script.
340
+
341
+ ```yaml
342
+ authoring:
343
+ provider: "exec"
344
+ timeoutMs: 8000
345
+ exec:
346
+ command: "/Users/you/bin/singbox-author-wrapper"
347
+ args:
348
+ - "{{prompt}}"
349
+ - "{{output_file}}"
350
+ - "{{schema_file}}"
351
+ ```
352
+
353
+ That wrapper can:
354
+
355
+ 1. call the local AI CLI you prefer
356
+ 2. instruct it to output only one JSON plan
357
+ 3. write the final JSON object to `{{output_file}}`
358
+
359
+ This keeps the project neutral and avoids shipping hard-coded adapters for every vendor.
360
+
361
+ ## Guardrails
362
+
363
+ - Built-in protected system rules still stay first.
364
+ - Generated rules still pass through the DSL validator.
365
+ - Schedule installation is explicit through `--install-schedule`.
366
+ - If a clause maps better to the built-in proxifier flow, the generator emits a note rather than trying to fake process matching inside the DSL.
367
+ - `auto` may fall back to deterministic if a local AI CLI is installed but not usable in the current environment.
368
+
369
+ ## Recommended Usage
370
+
371
+ For developer-oriented setups, use this workflow:
372
+
373
+ 1. keep `Process-Proxy` reserved for Proxifier-driven IDE and app traffic
374
+ 2. use built-in service rules for Stitch, OpenAI, Gemini, Anthropic, GitHub, and Google
375
+ 3. use templates or natural language for third-party AI sites and video sites
376
+ 4. use the DSL only for small exceptions
@@ -0,0 +1,42 @@
1
+ # Positioning
2
+
3
+ ## One-Line Summary
4
+
5
+ `Sing-box IaC Builder` is a policy-first CLI that compiles subscriptions into safe, headless `sing-box` infrastructure for macOS.
6
+
7
+ ## Problem Statement
8
+
9
+ Existing workflows usually optimize for importing subscriptions into a GUI client. They do not optimize for:
10
+
11
+ - deterministic route priority
12
+ - process-aware routing via `Proxifier`
13
+ - multiple listeners with stable semantics
14
+ - headless runtime management
15
+ - low resource usage
16
+ - safe rollout and validation
17
+
18
+ ## Strategic Difference
19
+
20
+ This project separates three concerns that are often mixed together:
21
+
22
+ 1. provider input
23
+ 2. local policy
24
+ 3. runtime application
25
+
26
+ Provider subscriptions are treated as untrusted upstream data. Local policy is declared separately and compiled with stable precedence. Runtime application is validated before live deployment.
27
+
28
+ ## Open Source Position
29
+
30
+ This project should be published as:
31
+
32
+ - a `sing-box` compiler, not a generic converter
33
+ - a macOS-first headless runtime tool, not a GUI replacement
34
+ - a policy authoring system, not only a template pack
35
+
36
+ ## Target Users
37
+
38
+ - advanced macOS users who already run `sing-box`
39
+ - users migrating away from Clash Verge or similar GUI clients
40
+ - users relying on `Proxifier`, AI applications, or mixed app-specific routing
41
+ - users who want a low-overhead headless runtime
42
+
@@ -0,0 +1,72 @@
1
+ # Releasing
2
+
3
+ This repository is prepared for npm-style distribution. The default package name is now:
4
+
5
+ ```json
6
+ "name": "@singbox-iac/cli"
7
+ ```
8
+
9
+ The repository still intentionally remains `"private": true` until the first real publish.
10
+
11
+ ## Current Release Safety Commands
12
+
13
+ Use these two commands before any real publish:
14
+
15
+ ```bash
16
+ npm run release:check
17
+ npm run release:dry-run
18
+ ```
19
+
20
+ `release:check` verifies:
21
+
22
+ - typecheck
23
+ - lint
24
+ - tests
25
+ - build
26
+ - `npm pack`
27
+ - clean-directory install
28
+ - installed `singbox-iac --help`
29
+
30
+ `release:dry-run` first runs `release:check`, then stages a publishable package copy with:
31
+
32
+ - `private: false`
33
+ - a publish name
34
+ - compiled `dist`
35
+ - docs/examples/README/LICENSE
36
+
37
+ and finally runs:
38
+
39
+ ```bash
40
+ npm publish --dry-run
41
+ ```
42
+
43
+ ## Package Name
44
+ The chosen default publish target is:
45
+
46
+ - `@singbox-iac/cli`
47
+
48
+ The installed command remains:
49
+
50
+ - `singbox-iac`
51
+
52
+ ## Dry-Run with a Candidate Name
53
+
54
+ You can still test an alternate future publish name without changing the repository package metadata:
55
+
56
+ ```bash
57
+ SINGBOX_IAC_PACKAGE_NAME=@singbox-iac/experimental-cli npm run release:dry-run
58
+ ```
59
+
60
+ ## Real Publish Checklist
61
+
62
+ 1. confirm the license choice
63
+ 2. remove `"private": true` in `package.json`
64
+ 3. ensure you are logged into npm with access to the `singbox-iac` organization
65
+ 4. run `npm run release:check`
66
+ 5. run `npm run release:dry-run`
67
+ 6. publish from a clean working tree with `npm publish --access public`
68
+
69
+ ## Notes
70
+
71
+ - `release:dry-run` keeps its staging directory on failure for debugging.
72
+ - `release:check` and `release:dry-run` both avoid mutating the live repository package metadata.