@namewta/speculo 2.0.6 → 2.1.1

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 (273) hide show
  1. package/README.md +3 -0
  2. package/THIRD-PARTY-NOTICES.md +4 -0
  3. package/dist/src/agent-skills.d.ts +5 -0
  4. package/dist/src/agent-skills.js +10 -7
  5. package/dist/src/agent-skills.js.map +1 -1
  6. package/dist/src/cli.js +25 -36
  7. package/dist/src/cli.js.map +1 -1
  8. package/dist/src/coordination.d.ts +3 -3
  9. package/dist/src/coordination.js +21 -4
  10. package/dist/src/coordination.js.map +1 -1
  11. package/dist/src/doctor.js +8 -1
  12. package/dist/src/doctor.js.map +1 -1
  13. package/dist/src/external-files.d.ts +4 -2
  14. package/dist/src/external-files.js +4 -4
  15. package/dist/src/external-files.js.map +1 -1
  16. package/dist/src/hub-catalog.d.ts +11 -0
  17. package/dist/src/hub-catalog.js +91 -0
  18. package/dist/src/hub-catalog.js.map +1 -0
  19. package/dist/src/hub-resources.json +1 -0
  20. package/dist/src/hub-skills.d.ts +53 -0
  21. package/dist/src/hub-skills.js +157 -0
  22. package/dist/src/hub-skills.js.map +1 -0
  23. package/dist/src/index.d.ts +6 -0
  24. package/dist/src/index.js +48 -47
  25. package/dist/src/index.js.map +1 -1
  26. package/dist/src/install-ui.d.ts +16 -7
  27. package/dist/src/install-ui.js +143 -92
  28. package/dist/src/install-ui.js.map +1 -1
  29. package/dist/src/manifest.d.ts +2 -0
  30. package/dist/src/manifest.js +2 -0
  31. package/dist/src/manifest.js.map +1 -1
  32. package/dist/src/refresh.d.ts +1 -0
  33. package/dist/src/refresh.js +13 -10
  34. package/dist/src/refresh.js.map +1 -1
  35. package/dist/src/retained-workflows.d.ts +10 -0
  36. package/dist/src/retained-workflows.js +25 -0
  37. package/dist/src/retained-workflows.js.map +1 -0
  38. package/dist/src/runtime-entry.d.ts +1 -0
  39. package/dist/src/runtime-entry.js +1 -0
  40. package/dist/src/runtime-entry.js.map +1 -1
  41. package/dist/src/skill-trees.d.ts +27 -0
  42. package/dist/src/skill-trees.js +118 -0
  43. package/dist/src/skill-trees.js.map +1 -0
  44. package/dist/src/terminal-ui.d.ts +30 -0
  45. package/dist/src/terminal-ui.js +148 -0
  46. package/dist/src/terminal-ui.js.map +1 -0
  47. package/dist/src/transaction.d.ts +3 -14
  48. package/dist/src/transaction.js +20 -36
  49. package/dist/src/transaction.js.map +1 -1
  50. package/dist/src/workflow-install.d.ts +15 -0
  51. package/dist/src/workflow-install.js +104 -0
  52. package/dist/src/workflow-install.js.map +1 -0
  53. package/dist/src/workflows.js +1 -1
  54. package/dist/src/workflows.js.map +1 -1
  55. package/package.json +6 -2
  56. package/skills-hub/automation/grok-bot-team-steward/CHEATSHEET.md +17 -0
  57. package/skills-hub/automation/grok-bot-team-steward/INSTALL.md +23 -0
  58. package/skills-hub/automation/grok-bot-team-steward/LICENSE +21 -0
  59. package/skills-hub/automation/grok-bot-team-steward/README.md +9 -0
  60. package/skills-hub/automation/grok-bot-team-steward/SKILL.md +52 -0
  61. package/skills-hub/automation/grok-bot-team-steward/agents/openai.yaml +4 -0
  62. package/skills-hub/automation/grok-bot-team-steward/references/00-hard-rules.md +50 -0
  63. package/skills-hub/automation/grok-bot-team-steward/references/01-snapshot-schema.md +84 -0
  64. package/skills-hub/automation/grok-bot-team-steward/references/02-export-protocol.md +57 -0
  65. package/skills-hub/automation/grok-bot-team-steward/references/03-restore-protocol.md +64 -0
  66. package/skills-hub/automation/grok-bot-team-steward/references/04-inventory.md +37 -0
  67. package/skills-hub/automation/grok-bot-team-steward/references/05-conversations.md +71 -0
  68. package/skills-hub/automation/grok-bot-team-steward/references/06-sanitizer.md +39 -0
  69. package/skills-hub/automation/grok-bot-team-steward/references/07-prompts.md +87 -0
  70. package/skills-hub/automation/grok-bot-team-steward/references/08-verification.md +30 -0
  71. package/skills-hub/automation/grok-bot-team-steward/references/09-sources.md +31 -0
  72. package/skills-hub/automation/grok-bot-team-steward/scripts/scrub.sh +17 -0
  73. package/skills-hub/automation/grok-bot-team-steward/scripts/snapshot-name.sh +18 -0
  74. package/skills-hub/automation/grok-bot-team-steward/scripts/validate-snapshot.sh +62 -0
  75. package/skills-hub/automation/grok-bot-team-steward/steward/ACTIVATE.md +58 -0
  76. package/skills-hub/automation/grok-bot-team-steward/steward/SETUP-INSTRUCTIONS.md +33 -0
  77. package/skills-hub/automation/grok-bot-team-steward/steward/STEWARD-PROFILE.md +28 -0
  78. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/CHANGELOG.md +3 -0
  79. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/CHARTER.md +27 -0
  80. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/DROP-LIST.md +10 -0
  81. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/GAPS.md +6 -0
  82. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/INIT.md +14 -0
  83. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/MANIFEST.md +30 -0
  84. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/MANIFEST.yaml +20 -0
  85. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/ORG.md +15 -0
  86. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/README.md +8 -0
  87. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/RESTORE.md +13 -0
  88. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/ROSTER.md +11 -0
  89. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/bots/_SLUG/GAPS.md +7 -0
  90. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/bots/_SLUG/MEMORY.md +9 -0
  91. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/bots/_SLUG/PROFILE.md +27 -0
  92. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/bots/_SLUG/agent-spec.md +9 -0
  93. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/bots/_SLUG/conversations/INDEX.md +5 -0
  94. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/bots/_SLUG/conversations/main.md +9 -0
  95. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/bots/_SLUG/routines.md +5 -0
  96. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/bots/_SLUG/skills.md +5 -0
  97. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/connectors.md +7 -0
  98. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/meta/COMPLETED.md +6 -0
  99. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/meta/CREATED.md +6 -0
  100. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/meta/RESTORE-NOTES.md +13 -0
  101. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/meta/SANITIZER.md +7 -0
  102. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/meta/SOURCE.md +8 -0
  103. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/rooms/_ROOM.md +8 -0
  104. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/routines/_ROUTINE.md +12 -0
  105. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/shared/shared-memory.md +5 -0
  106. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/shared/workspace-map.md +5 -0
  107. package/skills-hub/automation/grok-bot-team-steward/templates/snapshot/skills/_SKILL/SKILL.md +18 -0
  108. package/skills-hub/automation/herdr/SKILL.md +246 -0
  109. package/skills-hub/automation/orca/SKILL.md +328 -0
  110. package/skills-hub/coding/gitea-repo/LICENSE +21 -0
  111. package/skills-hub/coding/gitea-repo/SKILL.md +50 -0
  112. package/skills-hub/coding/gitea-repo/agents/openai.yaml +4 -0
  113. package/skills-hub/coding/gitea-repo/references/auth-and-scopes.md +58 -0
  114. package/skills-hub/coding/gitea-repo/references/endpoint-map.md +80 -0
  115. package/skills-hub/coding/gitea-repo/references/pagination-and-errors.md +34 -0
  116. package/skills-hub/coding/gitea-repo/scripts/gitea_api.py +814 -0
  117. package/skills-hub/coding/github-repo-steward/LICENSE +21 -0
  118. package/skills-hub/coding/github-repo-steward/SKILL.md +48 -0
  119. package/skills-hub/coding/github-repo-steward/agents/openai.yaml +4 -0
  120. package/skills-hub/coding/github-repo-steward/references/00-auth-and-tokens.md +73 -0
  121. package/skills-hub/coding/github-repo-steward/references/01-inventory.md +55 -0
  122. package/skills-hub/coding/github-repo-steward/references/02-lifecycle.md +57 -0
  123. package/skills-hub/coding/github-repo-steward/references/03-stars.md +42 -0
  124. package/skills-hub/coding/github-repo-steward/references/04-hygiene.md +40 -0
  125. package/skills-hub/coding/github-repo-steward/references/05-sources.md +42 -0
  126. package/skills-hub/coding/github-repo-steward/scripts/inventory.sh +64 -0
  127. package/skills-hub/coding/vscode-fullstack/LICENSE +21 -0
  128. package/skills-hub/coding/vscode-fullstack/SKILL.md +47 -0
  129. package/skills-hub/coding/vscode-fullstack/agents/openai.yaml +4 -0
  130. package/skills-hub/coding/vscode-fullstack/references/extensions-and-settings.md +181 -0
  131. package/skills-hub/coding/vscode-fullstack/references/profiles-and-validation.md +62 -0
  132. package/skills-hub/coding/vscode-fullstack/references/runtime-reuse.md +52 -0
  133. package/skills-hub/design/photo-retouch/LICENSE +21 -0
  134. package/skills-hub/design/photo-retouch/SKILL.md +50 -0
  135. package/skills-hub/design/photo-retouch/agents/openai.yaml +4 -0
  136. package/skills-hub/design/photo-retouch/references/basic-retouch.md +58 -0
  137. package/skills-hub/design/photo-retouch/references/formal-portrait.md +57 -0
  138. package/skills-hub/design/photo-retouch/references/object-and-canvas.md +82 -0
  139. package/skills-hub/design/photo-retouch/references/product-photo.md +41 -0
  140. package/skills-hub/design/photo-retouch/references/repair-and-look.md +61 -0
  141. package/skills-hub/design/photo-retouch/references/social-effects.md +55 -0
  142. package/skills-hub/design/photo-retouch/references/travel-creative.md +79 -0
  143. package/skills-hub/system/clash-client-profile/LICENSE +21 -0
  144. package/skills-hub/system/clash-client-profile/SKILL.md +79 -0
  145. package/skills-hub/system/clash-client-profile/agents/openai.yaml +4 -0
  146. package/skills-hub/system/clash-client-profile/references/acceptance.md +81 -0
  147. package/skills-hub/system/clash-client-profile/references/browser-privacy.md +35 -0
  148. package/skills-hub/system/clash-client-profile/references/clash-verge.md +40 -0
  149. package/skills-hub/system/clash-client-profile/references/dns-workflow.md +147 -0
  150. package/skills-hub/system/clash-client-profile/references/flclash.md +24 -0
  151. package/skills-hub/system/clash-client-profile/references/network-performance.md +25 -0
  152. package/skills-hub/system/clash-client-profile/references/platform-dns.md +109 -0
  153. package/skills-hub/system/clash-client-profile/references/sources.md +46 -0
  154. package/skills-hub/system/clash-client-profile/references/troubleshooting.md +82 -0
  155. package/skills-hub/system/clash-client-profile/scripts/dns_guard.py +650 -0
  156. package/skills-hub/system/clash-client-profile/scripts/proxy_doctor.py +213 -0
  157. package/skills-hub/system/clash-client-profile/scripts/render_rules.py +34 -0
  158. package/skills-hub/system/clash-client-profile/templates/ai-rules.yaml +18 -0
  159. package/skills-hub/system/clash-client-profile/templates/dns-request.example.json +9 -0
  160. package/skills-hub/system/clash-client-profile/templates/dns.yaml +8 -0
  161. package/skills-hub/system/linux-dev-disk-cleanup/LICENSE +21 -0
  162. package/skills-hub/system/linux-dev-disk-cleanup/SKILL.md +42 -0
  163. package/skills-hub/system/linux-dev-disk-cleanup/agents/openai.yaml +4 -0
  164. package/skills-hub/system/linux-dev-disk-cleanup/references/linux-cleanup-workflow.md +145 -0
  165. package/skills-hub/system/optimize-codex-config/LICENSE +21 -0
  166. package/skills-hub/system/optimize-codex-config/SKILL.md +101 -0
  167. package/skills-hub/system/optimize-codex-config/agents/openai.yaml +4 -0
  168. package/skills-hub/system/optimize-codex-config/assets/capabilities.example.json +22 -0
  169. package/skills-hub/system/optimize-codex-config/references/cli.md +35 -0
  170. package/skills-hub/system/optimize-codex-config/references/configuration-contract.md +33 -0
  171. package/skills-hub/system/optimize-codex-config/references/optimization-method.md +38 -0
  172. package/skills-hub/system/optimize-codex-config/references/privacy.md +41 -0
  173. package/skills-hub/system/optimize-codex-config/references/sources.md +24 -0
  174. package/skills-hub/system/optimize-codex-config/references/statusline.md +31 -0
  175. package/skills-hub/system/optimize-codex-config/references/transactions.md +32 -0
  176. package/skills-hub/system/optimize-codex-config/references/troubleshooting.md +95 -0
  177. package/skills-hub/system/optimize-codex-config/scripts/adapters/claude.mjs +24 -0
  178. package/skills-hub/system/optimize-codex-config/scripts/adapters/codex.mjs +10 -0
  179. package/skills-hub/system/optimize-codex-config/scripts/ai-cli-config.mjs +67 -0
  180. package/skills-hub/system/optimize-codex-config/scripts/audit-codex-config.mjs +762 -0
  181. package/skills-hub/system/optimize-codex-config/scripts/lib/document.mjs +166 -0
  182. package/skills-hub/system/optimize-codex-config/scripts/lib/inspect.mjs +211 -0
  183. package/skills-hub/system/optimize-codex-config/scripts/lib/io.mjs +104 -0
  184. package/skills-hub/system/optimize-codex-config/scripts/lib/plan.mjs +79 -0
  185. package/skills-hub/system/optimize-codex-config/scripts/lib/transaction.mjs +205 -0
  186. package/skills-hub/system/optimize-codex-config/scripts/lib/writers.mjs +46 -0
  187. package/skills-hub/system/optimize-codex-config/scripts/statusline/claude-statusline.mjs +94 -0
  188. package/skills-hub/system/optimize-codex-config/scripts/vendor/THIRD-PARTY-NOTICES.txt +250 -0
  189. package/skills-hub/system/optimize-codex-config/scripts/vendor/build-package-lock.json +488 -0
  190. package/skills-hub/system/optimize-codex-config/scripts/vendor/manifest.json +14 -0
  191. package/skills-hub/system/optimize-codex-config/scripts/vendor/parsers.mjs +16 -0
  192. package/skills-hub/system/proxy-region-locale/LICENSE +21 -0
  193. package/skills-hub/system/proxy-region-locale/SKILL.md +42 -0
  194. package/skills-hub/system/proxy-region-locale/agents/openai.yaml +4 -0
  195. package/skills-hub/system/proxy-region-locale/references/linux.md +35 -0
  196. package/skills-hub/system/proxy-region-locale/references/macos.md +31 -0
  197. package/skills-hub/system/proxy-region-locale/references/windows.md +45 -0
  198. package/skills-hub/system/system-health-audit/LICENSE +21 -0
  199. package/skills-hub/system/system-health-audit/SKILL.md +41 -0
  200. package/skills-hub/system/system-health-audit/agents/openai.yaml +4 -0
  201. package/skills-hub/system/system-health-audit/references/platforms.md +37 -0
  202. package/skills-hub/system/system-health-audit/scripts/system_audit.py +41 -0
  203. package/skills-hub/system/windows-dev-disk-cleanup/LICENSE +21 -0
  204. package/skills-hub/system/windows-dev-disk-cleanup/SKILL.md +40 -0
  205. package/skills-hub/system/windows-dev-disk-cleanup/agents/openai.yaml +4 -0
  206. package/skills-hub/system/windows-dev-disk-cleanup/references/windows-cleanup-workflow.md +121 -0
  207. package/skills-hub/writing/.gitkeep +0 -0
  208. package/skills-hub/writing/job-application/LICENSE +21 -0
  209. package/skills-hub/writing/job-application/SKILL.md +160 -0
  210. package/skills-hub/writing/job-application/agents/openai.yaml +4 -0
  211. package/skills-hub/writing/job-application/assets/resume.css +10 -0
  212. package/skills-hub/writing/job-application/config.example.json +9 -0
  213. package/skills-hub/writing/job-application/references/company-research.md +7 -0
  214. package/skills-hub/writing/job-application/references/corpus-schema.md +33 -0
  215. package/skills-hub/writing/job-application/references/honesty-gate.md +29 -0
  216. package/skills-hub/writing/job-application/references/improvement-plan.md +15 -0
  217. package/skills-hub/writing/job-application/references/ingest-protocol.md +18 -0
  218. package/skills-hub/writing/job-application/references/interview-speech.md +16 -0
  219. package/skills-hub/writing/job-application/references/jd-parse.md +18 -0
  220. package/skills-hub/writing/job-application/references/persist-paths.md +34 -0
  221. package/skills-hub/writing/job-application/references/question-bank.md +19 -0
  222. package/skills-hub/writing/job-application/references/rendering.md +9 -0
  223. package/skills-hub/writing/job-application/references/resume-playbook.md +30 -0
  224. package/skills-hub/writing/job-application/scripts/README.md +12 -0
  225. package/skills-hub/writing/job-application/scripts/ingest_kb.py +188 -0
  226. package/skills-hub/writing/job-application/scripts/render_resume.py +144 -0
  227. package/skills-hub/writing/job-application/scripts/validate_claims.py +52 -0
  228. package/skills-hub/writing/job-application/scripts/write_config.py +72 -0
  229. package/skills-hub/writing/job-application/templates/application-index.md +10 -0
  230. package/skills-hub/writing/job-application/templates/brief.md +16 -0
  231. package/skills-hub/writing/job-application/templates/changelog.md +6 -0
  232. package/skills-hub/writing/job-application/templates/company-research.md +15 -0
  233. package/skills-hub/writing/job-application/templates/corpus.md +11 -0
  234. package/skills-hub/writing/job-application/templates/evidence-map.md +5 -0
  235. package/skills-hub/writing/job-application/templates/framings.md +6 -0
  236. package/skills-hub/writing/job-application/templates/improvement-plan.md +16 -0
  237. package/skills-hub/writing/job-application/templates/ingest-log.md +4 -0
  238. package/skills-hub/writing/job-application/templates/known-gaps.md +4 -0
  239. package/skills-hub/writing/job-application/templates/match-report.md +21 -0
  240. package/skills-hub/writing/job-application/templates/methodology-cache.md +10 -0
  241. package/skills-hub/writing/job-application/templates/persist-index.md +11 -0
  242. package/skills-hub/writing/job-application/templates/profile.md +21 -0
  243. package/skills-hub/writing/job-application/templates/questions.md +22 -0
  244. package/skills-hub/writing/job-application/templates/resume-original.md +10 -0
  245. package/skills-hub/writing/job-application/templates/resume-tailored.md +21 -0
  246. package/skills-hub/writing/job-application/templates/sources-index.md +6 -0
  247. package/skills-hub/writing/job-application/templates/speech.md +19 -0
  248. package/skills-hub/writing/job-application/templates/stories.md +9 -0
  249. package/skills-hub/writing/job-application/templates/story-bank.md +11 -0
  250. package/skills-hub/writing/job-application/templates/strengths.md +4 -0
  251. package/skills-hub/writing/job-application/templates/style-memory.md +7 -0
  252. package/skills-hub/writing/ste-zh/LICENSE +21 -0
  253. package/skills-hub/writing/ste-zh/NOTICE.md +9 -0
  254. package/skills-hub/writing/ste-zh/SKILL.md +130 -0
  255. package/skills-hub/writing/ste-zh/agents/openai.yaml +6 -0
  256. package/skills-hub/writing/ste-zh/examples/zh-report.md +23 -0
  257. package/skills-hub/writing/ste-zh/references/english-modes.md +13 -0
  258. package/skills-hub/writing/ste-zh/references/terminology.md +13 -0
  259. package/skills-hub/writing/ste-zh/references/zh-rules.md +29 -0
  260. package/template/.speculo/refresh-contract.json +2 -0
  261. package/template/canonical/canonical-specdev-goal-plan.md +33 -25
  262. package/template/canonical/canonical-specdev-grill-with-docs.md +214 -206
  263. package/template/canonical/canonical-specdev-spec.md +214 -206
  264. package/template/canonical/canonical-specdev-tickets.md +214 -206
  265. package/template/canonical/canonical-specdev-wayfinder.md +214 -206
  266. package/template/lib/speculo-runtime.mjs +183 -8
  267. package/template/references/coordination/coordination-contract.md +11 -3
  268. package/template/references/coordination/modes/cli.md +2 -2
  269. package/template/references/coordination/modes/herdr.md +9 -9
  270. package/template/references/coordination/modes/orca.md +11 -11
  271. package/template/references/coordination/project-facts.schema.json +1 -0
  272. package/template/workflows/specdev/specdev-i-init-setup/SKILL.md +7 -6
  273. package/template/workflows/specdev/specdev-i-init-setup/references/first-setup.md +30 -1
@@ -0,0 +1,213 @@
1
+ #!/usr/bin/env python3
2
+ """Read-only proxy diagnostics. Offline by default; Python 3.10+, optional curl.
3
+
4
+ This tool does not change proxies, DNS, routes, firewall rules, or accounts.
5
+ A successful echo probe is NOT proof that another application's traffic is proxied.
6
+ """
7
+ from __future__ import annotations
8
+ import argparse
9
+ import ipaddress
10
+ import json
11
+ import os
12
+ from pathlib import Path
13
+ import platform
14
+ import shutil
15
+ import subprocess
16
+ import sys
17
+ import urllib.error
18
+ import urllib.request
19
+ from urllib.parse import urlsplit
20
+
21
+ PROXY_KEYS = ("http_proxy", "https_proxy", "all_proxy", "no_proxy",
22
+ "HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "NO_PROXY")
23
+ TARGETS = ("anthropic.com", "claude.ai", "claude.com")
24
+ ECHO = {4: "https://api4.ipify.org", 6: "https://api6.ipify.org"}
25
+ LIMIT = 1024 * 1024
26
+
27
+
28
+ def local_endpoint(value: str, controller: bool = False) -> str:
29
+ """Require an explicit numeric loopback and port; never forward credentials."""
30
+ try:
31
+ u = urlsplit(value)
32
+ schemes = ("http", "https") if controller else ("http", "https", "socks5h")
33
+ if u.scheme not in schemes or u.username is not None or u.password is not None:
34
+ raise ValueError
35
+ if not u.hostname or not ipaddress.ip_address(u.hostname).is_loopback:
36
+ raise ValueError
37
+ if u.port is None or not 1 <= u.port <= 65535:
38
+ raise ValueError
39
+ if u.path or u.query or u.fragment or any(c.isspace() for c in value):
40
+ raise ValueError
41
+ except (ValueError, TypeError):
42
+ raise ValueError("Use scheme://numeric-loopback:port without credentials, path or query; SOCKS requires socks5h") from None
43
+ return value
44
+
45
+
46
+ def environment_summary(env: dict[str, str]) -> dict:
47
+ result = {}
48
+ for key in PROXY_KEYS:
49
+ value = env.get(key)
50
+ if value is None:
51
+ continue
52
+ if key.lower() == "no_proxy":
53
+ result[key] = {"set": bool(value), "wildcard": any(part.strip() == "*" for part in value.split(",")),
54
+ "note": "Inspect locally for target-domain bypass; value redacted"}
55
+ else:
56
+ try:
57
+ u = urlsplit(value)
58
+ scheme = u.scheme if u.scheme in ("http", "https", "socks5", "socks5h") else "unknown"
59
+ result[key] = {"set": bool(value), "scheme": scheme,
60
+ "credentials_present": u.username is not None or u.password is not None}
61
+ except ValueError:
62
+ result[key] = {"set": bool(value), "scheme": "invalid"}
63
+ return result
64
+
65
+
66
+ def target_host(host: object, targets: tuple[str, ...] = TARGETS) -> bool:
67
+ if not isinstance(host, str):
68
+ return False
69
+ host = host.lower().rstrip(".")
70
+ return any(host == t or host.endswith("." + t) for t in targets)
71
+
72
+
73
+ def analyze_connections(data: object, targets: tuple[str, ...] = TARGETS) -> dict:
74
+ if not isinstance(data, dict) or not isinstance(data.get("connections"), list):
75
+ return {"status": "UNVERIFIED", "reason": "Missing connections array", "observations": []}
76
+ observations = []
77
+ for item in data["connections"]:
78
+ if not isinstance(item, dict):
79
+ continue
80
+ metadata = item.get("metadata")
81
+ if not isinstance(metadata, dict) or not target_host(metadata.get("host"), targets):
82
+ continue
83
+ chains = item.get("chains")
84
+ valid = isinstance(chains, list) and bool(chains) and all(isinstance(c, str) for c in chains)
85
+ direct = valid and any(c.upper() == "DIRECT" for c in chains)
86
+ blocked = valid and any(c.upper() in ("REJECT", "REJECT-DROP") for c in chains)
87
+ status = "FAIL" if direct else "BLOCKED" if blocked else "OBSERVED" if valid else "UNVERIFIED"
88
+ observations.append({"status": status, "direct": bool(direct), "blocked": bool(blocked),
89
+ "chain_length": len(chains) if valid else 0,
90
+ "rule_present": isinstance(item.get("rule"), str) and bool(item["rule"]),
91
+ "note": "Host, process, destination IP and node names redacted"})
92
+ return {"status": "FAIL" if any(o["status"] == "FAIL" for o in observations) else "UNVERIFIED",
93
+ "reason": "A snapshot cannot prove all application traffic, DNS, IPv6 or crash isolation",
94
+ "matched_connections": len(observations), "observations": observations}
95
+
96
+
97
+ def curl_command(executable: str, proxy: str, family: int) -> list[str]:
98
+ # -q must be first: ignore .curlrc (which may contain proxy, insecure, or output options).
99
+ # Do NOT add -6: with an IPv4 loopback HTTP proxy it constrains the proxy connection,
100
+ # not the exit's address family. Instead use a family-specific remote endpoint.
101
+ local_endpoint(proxy)
102
+ return [executable, "-q", "--silent", "--show-error", "--fail",
103
+ "--connect-timeout", "4", "--max-time", "10", "--max-filesize", "128",
104
+ "--proto", "=https", "--proxy", proxy, "--noproxy", "", ECHO[family]]
105
+
106
+
107
+ def probe(proxy: str, family: int, show_ip: bool = False) -> dict:
108
+ executable = shutil.which("curl.exe" if os.name == "nt" else "curl")
109
+ if not executable:
110
+ return {"status": "UNVERIFIED", "reason": "curl unavailable", "family": family}
111
+ env = {k: v for k, v in os.environ.items() if k.lower() not in
112
+ {"http_proxy", "https_proxy", "all_proxy", "no_proxy", "sslkeylogfile"}}
113
+ try:
114
+ result = subprocess.run(curl_command(executable, proxy, family), env=env,
115
+ capture_output=True, timeout=12, check=False)
116
+ if result.returncode:
117
+ return {"status": "UNVERIFIED", "curl_exit": result.returncode, "family": family,
118
+ "reason": "Probe failed; no direct retry; this alone does not prove a leak"}
119
+ ip = ipaddress.ip_address(result.stdout.decode("ascii").strip())
120
+ if ip.version != family:
121
+ return {"status": "UNVERIFIED", "reason": "Unexpected echo address family", "family": family}
122
+ return {"status": "OBSERVED", "family": family, "ip": str(ip) if show_ip else "<redacted>",
123
+ "note": "Only this explicit-proxy echo request was observed; country and application route unverified"}
124
+ except (OSError, subprocess.TimeoutExpired, UnicodeError, ValueError):
125
+ return {"status": "UNVERIFIED", "reason": "Probe unavailable or invalid response", "family": family}
126
+
127
+
128
+ class NoRedirect(urllib.request.HTTPRedirectHandler):
129
+ def redirect_request(self, req, fp, code, msg, headers, newurl):
130
+ raise urllib.error.HTTPError(req.full_url, code, "Redirect refused", headers, fp)
131
+
132
+
133
+ def read_controller(base: str, secret: str | None) -> dict:
134
+ local_endpoint(base, controller=True)
135
+ if secret and any(c in secret for c in "\r\n"):
136
+ raise ValueError("Invalid controller credential")
137
+ headers = {"Authorization": "Bearer " + secret} if secret else {}
138
+ opener = urllib.request.build_opener(urllib.request.ProxyHandler({}), NoRedirect())
139
+ request = urllib.request.Request(base + "/connections", headers=headers, method="GET")
140
+ with opener.open(request, timeout=5) as response:
141
+ payload = response.read(LIMIT + 1)
142
+ if len(payload) > LIMIT:
143
+ raise ValueError("Controller response too large")
144
+ return json.loads(payload)
145
+
146
+
147
+ def domain(value: str) -> str:
148
+ value = value.lower().rstrip(".")
149
+ labels = value.split(".")
150
+ if len(labels) < 2 or len(value) > 253 or not all(
151
+ label and len(label) <= 63 and label[0].isalnum() and label[-1].isalnum()
152
+ and all(c.isascii() and (c.isalnum() or c == "-") for c in label) for label in labels
153
+ ):
154
+ raise argparse.ArgumentTypeError("Use a DNS hostname, not a URL, wildcard or IP")
155
+ try:
156
+ ipaddress.ip_address(value)
157
+ except ValueError:
158
+ return value
159
+ raise argparse.ArgumentTypeError("Use a DNS hostname, not an IP")
160
+
161
+
162
+ def main(argv: list[str] | None = None) -> int:
163
+ parser = argparse.ArgumentParser(description=__doc__)
164
+ parser.add_argument("--network", action="store_true", help="Allow explicitly requested network probes; echo services see the exit IP")
165
+ parser.add_argument("--proxy", help="Actual local HTTP/HTTPS or socks5h endpoint; no assumed port")
166
+ parser.add_argument("--controller", help="Existing loopback controller; never enables or reconfigures it")
167
+ parser.add_argument("--connections", type=Path, help="Offline /connections JSON snapshot; keep raw file private")
168
+ parser.add_argument("--target", action="append", type=domain, help="Replace default target domain set; repeat as needed")
169
+ parser.add_argument("--show-ip", action="store_true", help="Include observed public echo IPs in stdout")
170
+ parser.add_argument("--strict", action="store_true", help="Exit 3 for inconclusive evidence; default exits 0 unless DIRECT observed")
171
+ args = parser.parse_args(argv)
172
+ if args.proxy or args.controller:
173
+ if not args.network:
174
+ parser.error("--proxy/--controller require --network; offline inspection makes no requests")
175
+ try:
176
+ if args.proxy:
177
+ local_endpoint(args.proxy)
178
+ if args.controller:
179
+ local_endpoint(args.controller, controller=True)
180
+ except ValueError as exc:
181
+ parser.error(str(exc))
182
+ elif args.network:
183
+ parser.error("--network requires --proxy and/or --controller")
184
+ if args.connections and args.controller:
185
+ parser.error("Choose either an offline snapshot or a live controller")
186
+ report = {"schema_version": 1, "platform": platform.system(), "network_requested": args.network,
187
+ "environment": environment_summary(dict(os.environ)), "verdict": "UNVERIFIED",
188
+ "limitations": ["No OS settings changed", "No direct baseline or fallback",
189
+ "No DNS/IPv6/crash-isolation or service-region guarantee"]}
190
+ targets = tuple(args.target or TARGETS)
191
+ if args.connections or args.controller:
192
+ try:
193
+ if args.connections:
194
+ with args.connections.open("rb") as handle:
195
+ payload = handle.read(LIMIT + 1)
196
+ if len(payload) > LIMIT:
197
+ raise ValueError("Snapshot too large")
198
+ data = json.loads(payload)
199
+ else:
200
+ data = read_controller(args.controller, os.environ.get("MIHOMO_SECRET"))
201
+ report["connections"] = analyze_connections(data, targets)
202
+ if report["connections"]["status"] == "FAIL":
203
+ report["verdict"] = "FAIL"
204
+ except (OSError, ValueError, urllib.error.URLError):
205
+ report["connections"] = {"status": "UNVERIFIED", "reason": "Snapshot/controller unavailable or invalid; raw error withheld"}
206
+ if args.proxy:
207
+ report["echo_probes"] = [probe(args.proxy, family, args.show_ip) for family in (4, 6)]
208
+ print(json.dumps(report, ensure_ascii=False, indent=2))
209
+ return 1 if report["verdict"] == "FAIL" else 3 if args.strict else 0
210
+
211
+
212
+ if __name__ == "__main__":
213
+ sys.exit(main())
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env python3
2
+ """Render a minimal Mihomo rules-extension fragment to stdout; never edits a profile."""
3
+ from __future__ import annotations
4
+ import argparse
5
+ import json
6
+ import sys
7
+
8
+ DOMAINS = ("anthropic.com", "claude.ai", "claude.com", "openai.com", "chatgpt.com",
9
+ "oaistatic.com", "oaiusercontent.com", "cursor.com", "cursor.sh", "x.ai", "grok.com")
10
+
11
+
12
+ def render(group: str) -> str:
13
+ if not group.strip() or group != group.strip() or any(c in group for c in ",\r\n\x00"):
14
+ raise ValueError("Group must be a nonempty exact name without comma or control characters")
15
+ if any(ord(c) < 32 for c in group) or group.upper() in ("DIRECT", "REJECT", "REJECT-DROP", "PASS", "COMPATIBLE"):
16
+ raise ValueError("Choose a real proxy policy group, not a direct/reject/reserved target")
17
+ rules = [json.dumps("DOMAIN-SUFFIX," + d + "," + group, ensure_ascii=False) for d in DOMAINS]
18
+ return "# Minimal domain baseline, not an exhaustive service allowlist.\nprepend:\n" + "".join(" - " + r + "\n" for r in rules) + "append: []\ndelete: []\n"
19
+
20
+
21
+ def main() -> None:
22
+ p = argparse.ArgumentParser(description=__doc__)
23
+ p.add_argument("--group", required=True, help="Exact existing group name; verify its currently selected leaf is not DIRECT")
24
+ args = p.parse_args()
25
+ try:
26
+ text = render(args.group)
27
+ except ValueError as exc:
28
+ p.error(str(exc))
29
+ # Keep redirected output UTF-8 even on Windows legacy code pages.
30
+ sys.stdout.buffer.write(text.encode("utf-8"))
31
+
32
+
33
+ if __name__ == "__main__":
34
+ main()
@@ -0,0 +1,18 @@
1
+ # Minimal domain baseline, not an exhaustive service allowlist.
2
+ prepend:
3
+ - "DOMAIN-SUFFIX,anthropic.com,🔰 节点选择"
4
+ - "DOMAIN-SUFFIX,claude.ai,🔰 节点选择"
5
+ - "DOMAIN-SUFFIX,claude.com,🔰 节点选择"
6
+ - "DOMAIN-SUFFIX,openai.com,🔰 节点选择"
7
+ - "DOMAIN-SUFFIX,chatgpt.com,🔰 节点选择"
8
+ - "DOMAIN-SUFFIX,oaistatic.com,🔰 节点选择"
9
+ - "DOMAIN-SUFFIX,oaiusercontent.com,🔰 节点选择"
10
+ - "DOMAIN-SUFFIX,cursor.com,🔰 节点选择"
11
+ - "DOMAIN-SUFFIX,cursor.sh,🔰 节点选择"
12
+ - "DOMAIN-SUFFIX,x.ai,🔰 节点选择"
13
+ - "DOMAIN-SUFFIX,grok.com,🔰 节点选择"
14
+ - "DOMAIN-SUFFIX,gemini.google.com,🔰 节点选择"
15
+ - "DOMAIN-SUFFIX,aistudio.google.com,🔰 节点选择"
16
+ - "DOMAIN-SUFFIX,generativelanguage.googleapis.com,🔰 节点选择"
17
+ append: []
18
+ delete: []
@@ -0,0 +1,9 @@
1
+ {
2
+ "schema_version": 1,
3
+ "group": "🔰 节点选择",
4
+ "resolvers": ["https://1.1.1.1/dns-query"],
5
+ "bootstrap": {"mode": "deny"},
6
+ "ipv6": "tunnel",
7
+ "targets": ["anthropic.com", "claude.ai", "claude.com"],
8
+ "replace_existing_dns_policies": false
9
+ }
@@ -0,0 +1,8 @@
1
+ # Backward-compatible discovery fragment, NOT a privacy or deployment profile.
2
+ # Do not apply this by itself: use scripts/dns_guard.py plan with a real effective
3
+ # configuration and templates/dns-request.example.json customized by the user.
4
+ # The generated plan pins nameserver/default/direct DNS to the approved group,
5
+ # explicitly models node bootstrap, and requires map REPLACEMENT for stale policies.
6
+ # No resolver, port-53 listener, OS DNS or IPv6 block is inferred here.
7
+ dns:
8
+ enable: true
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ting'an Wang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: linux-dev-disk-cleanup
3
+ description: 审计 Linux 开发机磁盘,并在具名授权后清理 APT、journal、snap 旧修订、Docker 未使用数据和可重建缓存。用于根分区空间、缓存体积和 /linux-dev-disk-cleanup;不处理 Windows、仅查 CPU、区域、代理或 Clash。
4
+ license: MIT
5
+ compatibility: Requires systemd Linux on the actual target, commonly Ubuntu or Debian. Root is required only for authorized steps that need it.
6
+ metadata:
7
+ author: NAMEWTA
8
+ wta-format-reviewed: '2026-10-08'
9
+ ---
10
+ # Linux 开发机磁盘清理
11
+
12
+ ## 输入与输出契约
13
+
14
+ 确认目标是 systemd Linux 主机,而不是 WSL 里看到的 Windows 盘、容器内部或远程跳板。取得根分区基线和当前清理清单;每项具有确切路径、容器名、volume ID、snap 修订或官方缓存命令,以及所有者、估计大小、决定和状态。扫描发现候选不自动新增删除授权。
15
+
16
+ 清单逐项写估计占用、批准动作、执行/停止/保留状态、`df` 实测变化,以及运行中容器、业务数据目录、当前内核和回退内核的核对。目录 `du` 之和不能冒充释放量。
17
+
18
+ 示例:“仅审计这台 Ubuntu 的根分区,列出可清理项目让我确认。”应进入本技能;“清理 Windows 的 C 盘缓存。”或“只看哪个进程占 CPU。”不应由本技能接管。
19
+
20
+ Docker、snap 或 APT 不存在时跳过对应项。需要 root 的步骤先确认权限,审计不自动提权。测量和命令见 [清理工作流](references/linux-cleanup-workflow.md)。本入口的授权与停止条件优先于参考中的示例命令。
21
+
22
+ 在用户工作区的 `清理清单.md` 或指定文件记录稳定编号和历史;不能因重新扫描覆盖已有决定。
23
+
24
+ ## 审计与授权
25
+
26
+ 只读或规划请求不删除、不清缓存、不 prune、不卸载、不改 journald。已有具名批准可执行,新候选继续待确认。“磁盘优化一下”不授权破坏性操作。
27
+
28
+ 开始前重测 `df -h /` 与 `df -ih /`。overlay 和 loop 与根分区是同一块盘,不相加。`du` 使用 `-x`,不跟随其他挂载。
29
+
30
+ ## 执行
31
+
32
+ 操作前重读路径、所有权和清单。先处理清单点名的过期临时目录,再处理 Docker。Docker 顺序固定:点名且非 running 的容器、`docker volume prune`、`docker image prune -a`、`docker builder prune`。不运行 `docker system prune -a --volumes`,不把 `docker volume prune` 放进定时任务。
33
+
34
+ 语言和构建缓存只用该工具的官方清理命令。`node_modules`、工具链、会话目录和业务 bind mount 各自独立决定。不从家目录或仓库根递归删除 `dist`、`build`、`node_modules`、`.next`。
35
+
36
+ 留下当前内核和至少一个已安装的回退内核。`apt autoremove` 先 dry-run;列表含回退内核、桌面或运行时则不执行。snap 只删除带 disabled 标记的修订,并且必须带 `--revision`。journal 上限和 vacuum 只有清单写明才改。
37
+
38
+ 父目录里还有未点名内容、在用 volume 会消失、dry-run 与保留项冲突,或现场与清单矛盾时,停止受影响项。不删除 `/tmp`、`/var/tmp` 本身,也不删除 `systemd-private-*`。
39
+
40
+ ## 验收
41
+
42
+ 按阶段读回根分区可用空间。核对运行中容器的名单与健康、点名数据目录大小、`uname -r` 与回退内核、源码仍在且生成目录已空。成功、失败、保留和硬停写入清单。只清理本轮自行创建且不再需要的临时文件,保留清单与证据。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Linux 磁盘清理"
3
+ short_description: "审计 Linux 磁盘并具名清理,保护内核、业务数据和活动容器"
4
+ default_prompt: "请使用 $linux-dev-disk-cleanup:仅审计根分区空间,列出可清理项目让我确认。"
@@ -0,0 +1,145 @@
1
+ # Linux 开发机清理工作流
2
+
3
+ 用于大范围审计、交互式清理规划,或已授权执行。按这台机器裁剪清单。某个工具或路径不存在是结果,不是错误。
4
+
5
+ 基线写到清单,并另存一份不覆盖的记录,例如 `/tmp/cleanup-YYYYMMDD-manifest.txt`。
6
+
7
+ ## 只读发现
8
+
9
+ 提出方案之前先抓初始快照:
10
+
11
+ - `df -h /` 与 `df -ih /`。只报根分区。overlay 行和同一文件系统上的 loop 是同一块盘的另一种视图,不相加。光盘或 ISO 挂载(例如 `/dev/sr0`)不占根分区。
12
+ - `du -xh --max-depth=1` 从 `/`、`/var`、`/var/lib`、`/var/tmp`、`/home`、`/root` 和大型项目根开始。跳过 overlay 挂载点。inode 紧张时再查文件数量。
13
+ - `docker system df`,以及 `docker ps` 的名字、状态、健康。数据根用 `docker info -f '{{.DockerRootDir}}'`。
14
+ - `journalctl --disk-usage`,`du -sh /var/cache/apt/archives /var/log`。
15
+ - `snap list --all` 里的 disabled 修订。`uname -r` 和已安装的 `linux-image-*`。
16
+ - 各用户的语言缓存:`go env GOCACHE GOMODCACHE`、`npm config get cache`、Cargo registry、Gradle caches、Maven repository、pnpm store。把缓存目录和工具链目录分开。
17
+
18
+ 体积扫描可能很贵。从已知的大目录往下钻,不要对同一 overlay 再走一遍。
19
+
20
+ ## 给候选分类
21
+
22
+ | 类别 | 通常怎么处理 | 主要风险 |
23
+ | --- | --- | --- |
24
+ | 过期临时目录 | 无进程、mtime 已旧、清单点名后按确切路径删除 | 父目录里还有别的工作 |
25
+ | 可重建构建缓存 | 官方命令:`cargo clean`、`go clean -cache` | 下次编译变慢,源码必须留下 |
26
+ | 可重新下载的依赖缓存 | 第二波:module、registry、Gradle caches、Maven repository | 离线时无法马上重建 |
27
+ | Docker 未使用数据 | 先看挂载,再按下面的顺序 prune | 匿名 volume 里可能有已停止栈的数据 |
28
+ | 包缓存与旧 snap 修订 | `apt-get clean`;只删 disabled 修订 | 误卸当前 snap 或回退内核 |
29
+ | 日志 | `journalctl --vacuum-size=`,需要时再写上限 | 丢掉旧日志 |
30
+ | 业务数据 | 除非被点名,否则保留 | bind mount 上的数据库、对象存储、索引 |
31
+ | 工具链与会话 | 保留,除非单独点名 | 拆掉正在用的运行时或会话 |
32
+
33
+ 目录大不等于可以删除。写清谁拥有它、能不能重建、支撑哪条工作流、必须留下什么。
34
+
35
+ 运行中的数据库、对象存储和搜索服务经常把数据 bind 到宿主机目录,而不是 Docker volume。匿名 volume 显示为 dangling 时,先 `docker inspect` 确认没有容器引用,再 prune。
36
+
37
+ ## 清单合同
38
+
39
+ ```markdown
40
+ # Linux 磁盘清理清单
41
+
42
+ > 更新时间:YYYY-MM-DD
43
+ > 当前状态:只读排查 / 决策中 / 已授权执行 / 已完成
44
+
45
+ ## 基线
46
+ | 文件系统 | 总空间 | 已用 | 可用 | 使用率 | inode 使用率 |
47
+
48
+ ## 已批准清理
49
+ | 编号 | 项目 | 决定 | 已知大小 | 精确边界 | 状态 |
50
+
51
+ ## 明确保留
52
+ | 编号 | 项目 | 保留边界 |
53
+
54
+ ## 待确认
55
+ | 编号 | 项目 | 风险/收益 | 问题 |
56
+
57
+ ## 执行记录
58
+ | 时间 | 项目 | 方法 | 结果 | df 变化 |
59
+ ```
60
+
61
+ 候选编号跨批次保持稳定。用户收窄边界后,后续项都按新边界做。已经删掉的内容如实记录。
62
+
63
+ ## 执行阶段
64
+
65
+ 路径互不重叠的已批准项可以并行。编排者先写基线,最后统一验收。并行不能改变下面的 Docker 顺序。
66
+
67
+ ### 1. 点名的过期临时目录
68
+
69
+ - 删除前确认路径是目录、清单写了完整路径、没有进程占用。
70
+ - 一次删除一个确切路径。不删除 `/var/tmp` 或 `/tmp` 本身,不删除 `systemd-private-*`。
71
+ - 父目录里还有未点名的子树时,停止并报告,不删父目录。
72
+
73
+ ### 2. Docker
74
+
75
+ 先记录每个运行中容器的 Mounts,以及因此必须留下的 volume ID。
76
+
77
+ 1. `docker rm` 只针对清单点名、且当前不是 running 的容器。正在运行的不删。
78
+ 2. `docker volume prune -f`。prune 之后,清理前记下的 volume ID 必须还在。
79
+ 3. `docker image prune -a -f`。仍被任何容器(含未删除的已退出容器)引用的镜像会留下。
80
+ 4. `docker builder prune -f`。随后看 `docker system df`。Build Cache 的 RECLAIMABLE 仍高于清单里的阈值(默认可按 1G)时,再执行一次 `docker builder prune -af`。
81
+
82
+ 不运行 `docker system prune -a --volumes`。不把 `docker volume prune` 放进 cron。
83
+
84
+ ### 3. 构建缓存
85
+
86
+ 优先用官方命令,并且只作用于清单点名的树或用户:
87
+
88
+ - 在点名的 Cargo 项目里执行 `cargo clean`。失败时只删除该项目的 `target/`。
89
+ - `go clean -cache`。`sudo -u` 找不到 `go` 时改用绝对路径。
90
+ - `npm cache clean --force`。它不清 `_npx`;`_npx` 未单独批准就留下。
91
+
92
+ 不从家目录或仓库根递归删除 `dist`、`build`、`node_modules`、`.next`。
93
+
94
+ ### 4. 包、snap、journal
95
+
96
+ - `apt-get clean` 只清 `/var/cache/apt/archives`。
97
+ - `apt-get autoremove --purge --dry-run`。待删除列表含回退内核、桌面元包、docker、containerd 或其他运行时则不执行。列表只有明确的孤儿包时才真正 autoremove。
98
+ - 对 `snap list --all` 里带 disabled 的行执行 `snap remove <name> --revision=<rev>`。不带 `--revision` 就不删。不卸载 snapd。
99
+ - 清单写明时:`journalctl --vacuum-size=200M`。需要持久上限时写入 `/etc/systemd/journald.conf.d/size-cap.conf`:
100
+
101
+ ```
102
+ [Journal]
103
+ SystemMaxUse=200M
104
+ ```
105
+
106
+ 然后 `systemctl restart systemd-journald`。重启失败就报告,不反复重试。
107
+
108
+ 回收站和 `/var/crash` 只在清单点名时清空内容,目录本身留下。
109
+
110
+ ### 5. 第二波:需要重新下载的依赖缓存
111
+
112
+ 第一波验收通过,且清单单独批准之后才做:
113
+
114
+ - `go clean -modcache`
115
+ - 删除 Cargo 的 `registry` 目录,保留 `bin`
116
+ - 删除 Gradle 的 `caches`,保留 `wrapper`
117
+ - 删除 Maven 的 `repository`,保留 `~/.m2/settings.xml`
118
+ - `pnpm store prune`。仍被项目引用的包会留下,这是预期结果
119
+ - 浏览器只清 Cache 与 Code Cache 子目录,不删 `~/.config` 里的配置
120
+
121
+ ## 硬停
122
+
123
+ 出现下列任一情况,停止受影响的项并报告证据:
124
+
125
+ - 要保留的容器不再 Up,或点名的数据目录大小变了。
126
+ - prune 之后,清理前还被容器挂载的 volume 不见了。
127
+ - 删除范围从点名路径扩到父目录,或父目录里有未识别内容。
128
+ - dry-run 要移除回退内核、桌面或运行时。
129
+ - 当前内核被列进待删除包。
130
+ - 缺少执行该项所需的权限。
131
+
132
+ ## 最终验收
133
+
134
+ - `df -h /` 的可用空间,以及相对基线的实际增量。目录 `du` 之和不必等于 `df` 的变化。
135
+ - `docker ps` 的名字、状态、健康与清理前的运行集合一致,除非清单批准过停掉其中某一个。
136
+ - 点名的业务数据目录大小未变。
137
+ - `uname -r` 不变,回退内核仍是 `ii`。
138
+ - 点名项目的源码还在,生成目录(例如 `target/`)已空。
139
+ - 清单写明保留的工具链和会话目录还在。
140
+
141
+ ## 一次实测里学到的边界
142
+
143
+ 2026-10-05,一台 Ubuntu 开发机根分区 196G,从 94%(剩余 12G)降到 38%(剩余 117G)。最大的几项是:三个已无进程的 `/var/tmp` 工作目录、84 个无引用匿名 volume、一个 Tauri 项目的 `target/`、Go build cache、未使用镜像和 build cache。19 个业务容器使用 bind mount,清理后仍全部健康;两个正在使用的 Kafka volume 被 prune 留下。
144
+
145
+ 同一台机器上,一个 828M 的项目 `temp/` 因为里面还有未点名的子树而整目录保留。pnpm store 在 prune 之后几乎没变,因为包仍被项目引用。这些是分类规则的例子,不是可以在别的机器上照路径重放的删除列表。
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ting'an Wang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: optimize-codex-config
3
+ description: 初始化、只读体检或修复 Codex CLI / Claude Code 配置,设置五小时、周额度与上下文状态栏,关闭遥测和外部检测,诊断 config.toml、settings.json、413 或 compaction。修改前展示脱敏 diff 并取得本次明确确认;不接管 CC Switch、账号额度、远端 API 或反向代理。
4
+ license: MIT
5
+ compatibility: Node.js >=22.16.0. Self-contained offline scripts; no runtime npm install. Linux/macOS guarded apply; native Windows doctor/plan/verify only. No credential-content reads or automatic CLI/network probes.
6
+ metadata:
7
+ author: NAMEWTA
8
+ wta-format-reviewed: '2026-10-10'
9
+ ---
10
+
11
+ # AI CLI Config
12
+
13
+ 稳定调用名仍是 `$optimize-codex-config`;覆盖 **Codex CLI 和 Claude Code**,不创建依赖兄弟技能的别名。以本机事实驱动:**发现 → 体检 → 计划 → 本次确认 → 最小写入 → 验证/恢复备份**。
14
+
15
+ 默认 `local-private`:遥测、反馈、外部域名预检、远程目录刷新、自动更新均提出关闭;只显示宿主已经提供的额度,不读取账号凭据查询额度。普通模型调用、云端数据政策与本机遥测开关不是同一件事。
16
+
17
+ ## 1. 确认环境和范围
18
+
19
+ 区分初始化、故障修复、隐私收敛和只设置状态栏。明确客户端、用户级/项目级,以及实际主机:当前容器、WSL、远程机器不是用户电脑。路径按显式参数 → `CODEX_HOME` / `CLAUDE_CONFIG_DIR` → 用户默认目录解析;项目根目录必须明确,worktree/旧版 Claude 本地设置位置不能猜测。
20
+
21
+ 读取 [配置层级与版本契约](references/configuration-contract.md)。原目录不存在是正常初始化状态,不是损坏。已有目录/文件或祖先为符号链接、junction、非普通文件时停止自动写入;不得换工具绕过权限拒绝。
22
+
23
+ 从本 SKILL.md 所在目录运行;先看 `--help`:
24
+
25
+ ```bash
26
+ node scripts/ai-cli-config.mjs doctor --client all --scope user --json
27
+ ```
28
+
29
+ 自定义目录使用 `--codex-home <absolute-directory>`、`--claude-home <absolute-directory>`;项目上下文使用 `--project <absolute-project-root>`。`--client claude` / `codex` 限定单个客户端。此命令不启动 CLI、MCP、hooks、插件或 helper,不扫描会话正文;认证仅检查文件元数据。
30
+
31
+ **完成标准:** 主机、路径、作用域、缺失/损坏文件、配置来源、继承环境冲突和未知能力均被如实记录。报告不能包含配置原文、密钥、provider URL、命令秘密参数或认证内容。
32
+
33
+ ## 2. 选择最小方案
34
+
35
+ 读取 [优化方法](references/optimization-method.md) 和 [隐私策略](references/privacy.md)。不要把最高推理、最大上下文、更多 Agent、关闭沙箱或安装更多插件当作默认优化。模型、供应商、审批、沙箱、MCP、hooks、历史和用户未知键默认保留;相关问题单独形成确认包。
36
+
37
+ 内置确定性写入限于经过版本核验的隐私控制和状态栏:
38
+
39
+ | 模式 | 用途 |
40
+ |---|---|
41
+ | `local-private` | 隐私控制+原生额度状态栏;默认 |
42
+ | `privacy-only` | 只收敛非必要外部流量,不换已有状态栏 |
43
+ | `statusline-only` | 只设置状态栏;不宣称其他隐私项已关闭 |
44
+
45
+ Codex 用原生 `tui.status_line`;Claude 用 [stdin-only renderer](scripts/statusline/claude-statusline.mjs)。读取 [状态栏数据契约](references/statusline.md):Codex 原生限额是剩余,Claude 输入百分比是已用;缺失不能变成 0% 或伪造余额。不得抓 cookie、读 OAuth、调用非公开接口或设置后台额度轮询。
46
+
47
+ 项目模式不会暗改 HOME。Claude 个人项目配置写 `.claude/settings.local.json`;确认真实宿主加载位置,并单独检查本地设置与运行资源不会被提交进 Git。Codex 机器级 telemetry/provider 不能靠项目配置覆盖:`requires_user_scope` 是阻断,不是放宽作用域的授权。
48
+
49
+ **完成标准:** 每个目标值有理由和适用范围;未知集成保留并标记“未验证”;不把外部预检关闭描述成安全性全面提高。
50
+
51
+ ## 3. 核验能力并生成脱敏计划
52
+
53
+ 官方网页是配置契约,不证明用户安装的版本支持该键。按 [CLI 使用与能力证据](references/cli.md) 填写本地能力记录,模板是 [capabilities.example.json](assets/capabilities.example.json)。只记录已核验的版本、键、状态项目、作用域及更高优先级来源;不能为了让计划通过而批量填“已验证”。未知、过期、托管限制或无法核验的能力阻止写入,但不阻止只读报告。
54
+
55
+ 不自动执行可能联网的客户端 doctor、登录或模型探测。已有本地版本信息、已授权且确认无外部副作用的本地帮助和当前官方契约可用于核验;不得读取认证内容补证据。外部检测仍保持关闭。
56
+
57
+ ```bash
58
+ node scripts/ai-cli-config.mjs plan --client all --scope user \
59
+ --mode local-private --evidence <absolute-capabilities.json> \
60
+ --out <absolute-review.plan.json> --json
61
+ ```
62
+
63
+ `plan` 本身不改配置;`--out` 只明确授权创建一个新的私有计划文件,父目录需已存在。计划列出逐文件目标、指纹、语义脱敏 diff、保留项、blocker、备份位置、原子替换方法和未验证项。它不保存完整原配置。已有 Claude 回调只有在用户选择替换后才加 `--replace-statusline` 并重新生成计划。
64
+
65
+ **完成标准:** 用户已看到全部目标与代价;`ready` 只是静态计划可供确认,不等于当前 writer、宿主加载或真实额度已验证。
66
+
67
+ ## 4. 本次确认后应用
68
+
69
+ 用户必须在看到计划后给出本次明确确认;计划 ID 是完整性标识,不是授权来源。关闭或暂停相关配置管理器及会触发 ConfigChange 的会话,再由用户确认处于静止状态。不能自动杀进程、关闭安全 hooks 或伪造 `--quiescent`。
70
+
71
+ ```bash
72
+ node scripts/ai-cli-config.mjs apply --plan <absolute-review.plan.json> \
73
+ --confirm <exact-plan-id> --quiescent --json
74
+ ```
75
+
76
+ 读取 [事务与平台边界](references/transactions.md)。脚本取得自身排他锁,重新核验全部观察项,检查目标可写句柄,将 `*.pre-optimize.bak` 保存在私有事务目录,先暂存再逐文件原子提交。缺失文件使用不覆盖创建;Claude 运行脚本复制到内容寻址的稳定目录,不依赖 npm 缓存或技能安装位置。
77
+
78
+ Linux/macOS writer 观测 unknown 或 busy 时阻断。原生 Windows 的句柄与 ACL 支持尚未达到自动写入门槛,**仅提供 doctor/plan/verify**;不能改用 WSL 或直接写文件绕过这个边界。多文件不是瞬时原子事务,也不承诺断电自动恢复。
79
+
80
+ **完成标准:** 只写本次确认集合;无强制覆盖、无全局 shell 环境修改、无认证内容操作。异常时尝试安全恢复备份,后续用户编辑存在则停止回滚并保留现场。
81
+
82
+ ## 5. 验证和故障处理
83
+
84
+ ```bash
85
+ node scripts/ai-cli-config.mjs verify --plan <absolute-review.plan.json> --json
86
+ node scripts/ai-cli-config.mjs rollback --plan <absolute-review.plan.json> \
87
+ --confirm <exact-plan-id> --quiescent --json
88
+ ```
89
+
90
+ 离线验证覆盖本机 hash、完整语法、已观察的策略与依赖指纹;不代表真实宿主已经加载、账号额度可用、远端政策或既有集成零出网。重新打开宿主后由用户检查原生状态栏、配置来源和保留功能;不为验收额度而额外发起模型或账号请求。
91
+
92
+ 出现 401/403/404/413/429、SSE、超时或 compaction 故障,按 [故障诊断](references/troubleshooting.md) 分离本机、认证、供应商与代理证据。旧脚本保留用于用户明确选择的 Codex 会话诊断,默认不再执行 CLI 探针:
93
+
94
+ ```bash
95
+ node scripts/audit-codex-config.mjs --codex-home <absolute-directory> \
96
+ --no-command-probes --since-days 7 --json
97
+ ```
98
+
99
+ 不通过提高上下文窗口、无限重试、关闭 TLS 校验或放宽权限修复稳定错误。不接管 CC Switch 数据库、反向代理或远端 API;外部问题只交接。
100
+
101
+ **交付固定为:** 已改变、已保留、已验证、未验证、阻断和回滚结果。真实设备、账号测试、跨平台 CI、离线 fixtures 和模型选择评估分别报告,未执行的项目不能标记通过。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "AI CLI 配置维护"
3
+ short_description: "体检 Codex 与 Claude 配置、隐私及额度状态栏,确认后安全修改并可回滚。"
4
+ default_prompt: "请使用 $optimize-codex-config:先只读体检本机 Codex CLI 和 Claude Code,规划隐私收敛与原生额度状态栏;展示脱敏 diff,未经本次明确确认不要修改。"