0xray 3.0.14 → 3.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 (296) hide show
  1. package/.gitignore.default +59 -0
  2. package/.mcp.json +35 -0
  3. package/.opencode/codex.codex +1 -1
  4. package/.opencode/commands/dependency-audit.md +3 -3
  5. package/.opencode/commands/summary-logger.md +4 -4
  6. package/.opencode/enforcer-config.json +2 -2
  7. package/.opencode/hooks/post-commit +1 -1
  8. package/.opencode/init.sh +10 -4
  9. package/.plugin/plugin.json +11 -0
  10. package/AGENTS-consumer.md +46 -0
  11. package/AGENTS.md +10 -10
  12. package/LICENSE +1 -1
  13. package/README.md +8 -8
  14. package/SKILLS.md +140 -0
  15. package/dist/.gitignore.default +59 -0
  16. package/dist/AGENTS.md +10 -10
  17. package/dist/CHANGELOG.md +34 -0
  18. package/dist/LICENSE +1 -1
  19. package/dist/README.md +8 -8
  20. package/dist/SKILLS.md +140 -0
  21. package/dist/agents/index.js +3 -1
  22. package/dist/agents/registry.js +13 -0
  23. package/dist/analytics/routing-refiner.js +1 -1
  24. package/dist/architect/architectural-integrity.js +3 -3
  25. package/dist/benchmark/performance-benchmark.js +4 -3
  26. package/dist/cli/commands/antigravity-status.js +23 -23
  27. package/dist/cli/commands/credible-init.js +1 -1
  28. package/dist/cli/commands/hermes-install.js +12 -4
  29. package/dist/cli/commands/mcp-install.js +1 -1
  30. package/dist/cli/commands/openclaw-install.js +10 -1
  31. package/dist/cli/commands/opencode-install.js +22 -0
  32. package/dist/cli/commands/plugin-commands.js +2 -2
  33. package/dist/cli/commands/publish-agent.js +5 -5
  34. package/dist/cli/commands/skill-install.js +39 -2
  35. package/dist/cli/commands/status.js +8 -3
  36. package/dist/cli/commands/storyteller.js +2 -2
  37. package/dist/cli/index.js +17 -11
  38. package/dist/cli/server.js +4 -4
  39. package/dist/core/activity-logger.js +4 -4
  40. package/dist/core/agent-spawn-gate.js +1 -1
  41. package/dist/core/boot-orchestrator.js +30 -31
  42. package/dist/core/bridge.mjs +26 -26
  43. package/dist/core/codex-formatter.js +2 -3
  44. package/dist/core/codex-injector.js +7 -7
  45. package/dist/core/config-loader.js +3 -2
  46. package/dist/core/config-paths.js +38 -31
  47. package/dist/core/context-loader.js +5 -5
  48. package/dist/core/features-config.js +1 -1
  49. package/dist/core/index.js +2 -2
  50. package/dist/core/logging-config.js +7 -7
  51. package/dist/core/orchestrator.js +2 -2
  52. package/dist/core/system-prompt-generator.js +2 -2
  53. package/dist/core/xray-activation.js +42 -41
  54. package/dist/delegation/agent-delegator.js +3 -3
  55. package/dist/enforcement/enforcer-tools.js +4 -4
  56. package/dist/enforcement/loaders/codex-loader.js +2 -2
  57. package/dist/execution/opencode-cli-invoker.js +1 -1
  58. package/dist/governance/governance-service.js +1 -1
  59. package/dist/governance/llm-governance-provider.js +223 -0
  60. package/dist/index.js +6 -6
  61. package/dist/inference/deploy-verifier.js +1 -1
  62. package/dist/inference/inference-cycle.js +16 -16
  63. package/dist/integrations/base/README.md +1 -1
  64. package/dist/integrations/enforcement-gate.js +2 -2
  65. package/dist/integrations/governance/index.js +1 -1
  66. package/dist/integrations/grok/grok-cli.js +20 -6
  67. package/dist/integrations/grok/hooks/pre-tool-use.js +3 -3
  68. package/dist/integrations/grok/plugin/0xray/.mcp.json +16 -4
  69. package/dist/integrations/grok/plugin/0xray/hooks/hooks.json +2 -2
  70. package/dist/integrations/hermes-agent/__init__.py +90 -79
  71. package/dist/integrations/hermes-agent/after-install.md +14 -14
  72. package/dist/integrations/hermes-agent/bridge.mjs +60 -25
  73. package/dist/integrations/hermes-agent/plugin.yaml +5 -5
  74. package/dist/integrations/hermes-agent/schemas.py +61 -12
  75. package/dist/integrations/hermes-agent/test_plugin.py +124 -124
  76. package/dist/integrations/hermes-agent/tools.py +129 -25
  77. package/dist/integrations/openclaw/README.md +6 -6
  78. package/dist/integrations/openclaw/config.js +1 -1
  79. package/dist/integrations/openclaw/index.js +2 -2
  80. package/dist/integrations/openclaw/types.js +3 -3
  81. package/dist/integrations/plugins/plugin-integration.js +1 -1
  82. package/dist/integrations/plugins/plugin-registry.js +3 -3
  83. package/dist/mcps/architect-tools.server.js +3 -2
  84. package/dist/mcps/auto-format.server.js +2 -2
  85. package/dist/mcps/boot-orchestrator.server.js +2 -2
  86. package/dist/mcps/config/config-loader.js +40 -9
  87. package/dist/mcps/config/server-config-registry.js +10 -10
  88. package/dist/mcps/connection/mcp-connection.js +1 -1
  89. package/dist/mcps/enforcer-tools.server.js +2 -2
  90. package/dist/mcps/estimation.server.js +3 -2
  91. package/dist/mcps/framework-compliance-audit.server.js +2 -2
  92. package/dist/mcps/framework-help.server.js +9 -8
  93. package/dist/mcps/governance.server.js +8 -4
  94. package/dist/mcps/knowledge-skills/api-design.server.js +3 -2
  95. package/dist/mcps/knowledge-skills/architecture-patterns.server.js +3 -2
  96. package/dist/mcps/knowledge-skills/bug-triage-specialist.server.js +3 -3
  97. package/dist/mcps/knowledge-skills/code-analyzer.server.js +2 -2
  98. package/dist/mcps/knowledge-skills/code-review.server.js +14 -39
  99. package/dist/mcps/knowledge-skills/content-creator.server.js +3 -3
  100. package/dist/mcps/knowledge-skills/database-design.server.js +2 -2
  101. package/dist/mcps/knowledge-skills/devops-deployment.server.js +3 -2
  102. package/dist/mcps/knowledge-skills/git-workflow.server.js +3 -2
  103. package/dist/mcps/knowledge-skills/growth-strategist.server.js +3 -3
  104. package/dist/mcps/knowledge-skills/log-monitor.server.js +3 -3
  105. package/dist/mcps/knowledge-skills/mobile-development.server.js +3 -3
  106. package/dist/mcps/knowledge-skills/multimodal-looker.server.js +3 -3
  107. package/dist/mcps/knowledge-skills/performance-optimization.server.js +2 -2
  108. package/dist/mcps/knowledge-skills/project-analysis.server.js +2 -2
  109. package/dist/mcps/knowledge-skills/refactoring-strategies.server.js +3 -2
  110. package/dist/mcps/knowledge-skills/security-audit.server.js +14 -44
  111. package/dist/mcps/knowledge-skills/seo-consultant.server.js +3 -2
  112. package/dist/mcps/knowledge-skills/session-management.server.js +3 -2
  113. package/dist/mcps/knowledge-skills/skill-invocation.server.js +105 -3
  114. package/dist/mcps/knowledge-skills/strategist.server.js +3 -3
  115. package/dist/mcps/knowledge-skills/tech-writer.server.js +3 -3
  116. package/dist/mcps/knowledge-skills/testing-best-practices.server.js +3 -2
  117. package/dist/mcps/knowledge-skills/testing-strategy.server.js +2 -2
  118. package/dist/mcps/knowledge-skills/ui-ux-design.server.js +5 -4
  119. package/dist/mcps/lint.server.js +4 -4
  120. package/dist/mcps/mcp-client.js +5 -5
  121. package/dist/mcps/model-health-check.server.js +3 -2
  122. package/dist/mcps/orchestrator/server.js +4 -3
  123. package/dist/mcps/orchestrator.server.js +2 -1
  124. package/dist/mcps/performance-analysis.server.js +2 -2
  125. package/dist/mcps/processor-pipeline.server.js +3 -2
  126. package/dist/mcps/registry.json +1 -1
  127. package/dist/mcps/researcher.server.js +14 -39
  128. package/dist/mcps/security-scan.server.js +2 -2
  129. package/dist/mcps/simulation/server-simulations.js +3 -3
  130. package/dist/mcps/state-manager.server.js +5 -5
  131. package/dist/metrics/agent-metrics.js +1 -1
  132. package/dist/orchestrator/enhanced-multi-agent-orchestrator.js +4 -4
  133. package/dist/orchestrator/intelligent-commit-batcher.js +2 -3
  134. package/dist/orchestrator/multi-agent-orchestration-coordinator.js +9 -9
  135. package/dist/orchestrator/orchestrator.js +9 -8
  136. package/dist/orchestrator/universal-registry-bridge.js +4 -4
  137. package/dist/postprocessor/PostProcessor.js +9 -9
  138. package/dist/postprocessor/services/RegressionAnalysisService.js +4 -4
  139. package/dist/postprocessor/triggers/GitHookTrigger.js +18 -18
  140. package/dist/processors/implementations/agents-md-validation-processor.js +2 -2
  141. package/dist/processors/implementations/inference-improvement-processor.js +1 -2
  142. package/dist/processors/implementations/log-protection-processor.js +2 -2
  143. package/dist/processors/implementations/publish-preflight-processor.js +2 -3
  144. package/dist/processors/implementations/regression-testing-processor.js +2 -2
  145. package/dist/processors/implementations/session-summary-processor.js +2 -2
  146. package/dist/processors/implementations/storytelling-trigger-processor.js +1 -2
  147. package/dist/public/about.html +6 -6
  148. package/dist/public/enterprise.html +1 -1
  149. package/dist/public/features.html +2 -2
  150. package/dist/public/index.html +4 -4
  151. package/dist/reporting/report-formatter.js +1 -1
  152. package/dist/scripts/activate-kernel-pipeline.js +4 -4
  153. package/dist/scripts/pre-command +1 -1
  154. package/dist/services/inference-tuner.js +2 -2
  155. package/dist/skills/api-design/SKILL.md +1 -1
  156. package/dist/skills/architect-tools/SKILL.md +1 -1
  157. package/dist/skills/architecture-patterns/SKILL.md +1 -1
  158. package/dist/skills/auto-format/SKILL.md +1 -1
  159. package/dist/skills/boot-orchestrator/SKILL.md +1 -1
  160. package/dist/skills/bug-triage/SKILL.md +1 -1
  161. package/dist/skills/code-analyzer/SKILL.md +1 -1
  162. package/dist/skills/code-review/SKILL.md +1 -1
  163. package/dist/skills/enforcer/SKILL.md +1 -1
  164. package/dist/skills/framework-compliance-audit/SKILL.md +1 -1
  165. package/dist/skills/git-workflow/SKILL.md +1 -1
  166. package/dist/skills/hermes-agent/SKILL.md +42 -42
  167. package/dist/skills/inference-improve/SKILL.md +1 -1
  168. package/dist/skills/lint/SKILL.md +1 -1
  169. package/dist/skills/log-monitor/SKILL.md +1 -1
  170. package/dist/skills/model-health-check/SKILL.md +1 -1
  171. package/dist/skills/multimodal-looker/SKILL.md +1 -1
  172. package/dist/skills/orchestrator/SKILL.md +1 -1
  173. package/dist/skills/performance-analysis/SKILL.md +1 -1
  174. package/dist/skills/performance-optimization/SKILL.md +1 -1
  175. package/dist/skills/processor-pipeline/SKILL.md +1 -1
  176. package/dist/skills/project-analysis/SKILL.md +1 -1
  177. package/dist/skills/refactoring-strategies/SKILL.md +1 -1
  178. package/dist/skills/registry.json +1 -1
  179. package/dist/skills/researcher/SKILL.md +1 -1
  180. package/dist/skills/security-audit/SKILL.md +1 -1
  181. package/dist/skills/security-scan/SKILL.md +1 -1
  182. package/dist/skills/session-management/SKILL.md +1 -1
  183. package/dist/skills/state-manager/SKILL.md +1 -1
  184. package/dist/skills/storyteller/SKILL.md +1 -1
  185. package/dist/skills/testing-best-practices/SKILL.md +1 -1
  186. package/dist/skills/testing-strategy/SKILL.md +1 -1
  187. package/dist/skills/ui-ux-design/SKILL.md +1 -1
  188. package/dist/state/index.js +1 -1
  189. package/dist/state/state-manager.js +3 -4
  190. package/dist/utils/import-resolver.js +1 -1
  191. package/dist/utils/path-resolver.js +2 -2
  192. package/dist/utils/token-manager.js +1 -1
  193. package/dist/validation/estimation-validator.js +1 -1
  194. package/package.json +10 -3
  195. package/scripts/hooks/pre-command +1 -1
  196. package/scripts/hooks/run-hook.js +2 -2
  197. package/scripts/node/auto-reflection-generator.mjs +30 -36
  198. package/scripts/node/govern-reflection.mjs +1 -1
  199. package/scripts/node/postinstall.cjs +37 -2
  200. package/scripts/node/pre-publish-guard.js +13 -9
  201. package/scripts/node/setup-xai-oauth.mjs +244 -0
  202. package/scripts/node/universal-version-manager.js +8 -8
  203. package/scripts/node/version-manager.mjs +1 -1
  204. package/src/integrations/grok/plugin/0xray/.mcp.json +16 -4
  205. package/src/integrations/grok/plugin/0xray/hooks/hooks.json +2 -2
  206. package/src/mcps/architect-tools.server.ts +2 -2
  207. package/src/mcps/auto-format.server.ts +2 -2
  208. package/src/mcps/boot-orchestrator.server.ts +2 -2
  209. package/src/mcps/config/__tests__/config-loader.test.ts +29 -33
  210. package/src/mcps/config/__tests__/server-config-registry.test.ts +12 -12
  211. package/src/mcps/config/config-loader.ts +50 -11
  212. package/src/mcps/config/server-config-registry.ts +10 -10
  213. package/src/mcps/connection/mcp-connection.ts +1 -1
  214. package/src/mcps/enforcer-tools.server.ts +2 -2
  215. package/src/mcps/estimation.server.ts +3 -2
  216. package/src/mcps/framework-compliance-audit.server.ts +2 -2
  217. package/src/mcps/framework-help.server.ts +9 -8
  218. package/src/mcps/governance.server.ts +8 -3
  219. package/src/mcps/knowledge-skills/api-design.server.ts +3 -2
  220. package/src/mcps/knowledge-skills/architecture-patterns.server.ts +2 -2
  221. package/src/mcps/knowledge-skills/bug-triage-specialist.server.ts +2 -2
  222. package/src/mcps/knowledge-skills/code-analyzer.server.ts +2 -2
  223. package/src/mcps/knowledge-skills/code-review.server.ts +21 -36
  224. package/src/mcps/knowledge-skills/content-creator.server.ts +3 -3
  225. package/src/mcps/knowledge-skills/database-design.server.ts +2 -2
  226. package/src/mcps/knowledge-skills/devops-deployment.server.ts +3 -2
  227. package/src/mcps/knowledge-skills/git-workflow.server.ts +3 -2
  228. package/src/mcps/knowledge-skills/growth-strategist.server.ts +3 -3
  229. package/src/mcps/knowledge-skills/log-monitor.server.ts +3 -3
  230. package/src/mcps/knowledge-skills/mobile-development.server.ts +3 -3
  231. package/src/mcps/knowledge-skills/multimodal-looker.server.ts +3 -3
  232. package/src/mcps/knowledge-skills/performance-optimization.server.ts +2 -2
  233. package/src/mcps/knowledge-skills/project-analysis.server.ts +2 -2
  234. package/src/mcps/knowledge-skills/refactoring-strategies.server.ts +3 -2
  235. package/src/mcps/knowledge-skills/security-audit.server.ts +21 -40
  236. package/src/mcps/knowledge-skills/seo-consultant.server.ts +3 -2
  237. package/src/mcps/knowledge-skills/session-management.server.ts +3 -2
  238. package/src/mcps/knowledge-skills/skill-invocation.server.ts +113 -3
  239. package/src/mcps/knowledge-skills/strategist.server.ts +3 -3
  240. package/src/mcps/knowledge-skills/tech-writer.server.ts +3 -3
  241. package/src/mcps/knowledge-skills/testing-best-practices.server.ts +3 -2
  242. package/src/mcps/knowledge-skills/testing-strategy.server.ts +2 -2
  243. package/src/mcps/knowledge-skills/ui-ux-design.server.ts +5 -4
  244. package/src/mcps/lint.server.ts +4 -4
  245. package/src/mcps/mcp-client.ts +5 -5
  246. package/src/mcps/model-health-check.server.ts +2 -2
  247. package/src/mcps/orchestrator/server.ts +4 -3
  248. package/src/mcps/orchestrator.server.ts +2 -1
  249. package/src/mcps/performance-analysis.server.ts +2 -2
  250. package/src/mcps/processor-pipeline.server.ts +3 -2
  251. package/src/mcps/registry.json +1 -1
  252. package/src/mcps/researcher.server.ts +21 -36
  253. package/src/mcps/security-scan.server.ts +2 -2
  254. package/src/mcps/simulation/server-simulations.ts +3 -3
  255. package/src/mcps/state-manager.server.ts +5 -5
  256. package/src/opencode/codex.codex +1 -1
  257. package/src/opencode/commands/dependency-audit.md +3 -3
  258. package/src/opencode/commands/summary-logger.md +4 -4
  259. package/src/opencode/enforcer-config.json +2 -2
  260. package/src/skills/api-design/SKILL.md +1 -1
  261. package/src/skills/architect-tools/SKILL.md +1 -1
  262. package/src/skills/architecture-patterns/SKILL.md +1 -1
  263. package/src/skills/auto-format/SKILL.md +1 -1
  264. package/src/skills/boot-orchestrator/SKILL.md +1 -1
  265. package/src/skills/bug-triage/SKILL.md +1 -1
  266. package/src/skills/code-analyzer/SKILL.md +1 -1
  267. package/src/skills/code-review/SKILL.md +1 -1
  268. package/src/skills/enforcer/SKILL.md +1 -1
  269. package/src/skills/framework-compliance-audit/SKILL.md +1 -1
  270. package/src/skills/git-workflow/SKILL.md +1 -1
  271. package/src/skills/hermes-agent/SKILL.md +42 -42
  272. package/src/skills/inference-improve/SKILL.md +1 -1
  273. package/src/skills/lint/SKILL.md +1 -1
  274. package/src/skills/log-monitor/SKILL.md +1 -1
  275. package/src/skills/model-health-check/SKILL.md +1 -1
  276. package/src/skills/multimodal-looker/SKILL.md +1 -1
  277. package/src/skills/orchestrator/SKILL.md +1 -1
  278. package/src/skills/performance-analysis/SKILL.md +1 -1
  279. package/src/skills/performance-optimization/SKILL.md +1 -1
  280. package/src/skills/processor-pipeline/SKILL.md +1 -1
  281. package/src/skills/project-analysis/SKILL.md +1 -1
  282. package/src/skills/refactoring-strategies/SKILL.md +1 -1
  283. package/src/skills/registry.json +1 -1
  284. package/src/skills/researcher/SKILL.md +1 -1
  285. package/src/skills/security-audit/SKILL.md +1 -1
  286. package/src/skills/security-scan/SKILL.md +1 -1
  287. package/src/skills/session-management/SKILL.md +1 -1
  288. package/src/skills/state-manager/SKILL.md +1 -1
  289. package/src/skills/storyteller/SKILL.md +1 -1
  290. package/src/skills/testing-best-practices/SKILL.md +1 -1
  291. package/src/skills/testing-strategy/SKILL.md +1 -1
  292. package/src/skills/ui-ux-design/SKILL.md +1 -1
  293. package/xray/agents_template.md +46 -0
  294. package/xray/codex.json +598 -0
  295. package/dist/plugin/xray-codex-injection.js +0 -857
  296. /package/dist/integrations/openclaw/hooks/{strray-hooks.js → xray-hooks.js} +0 -0
@@ -1,4 +1,4 @@
1
- """StringRay Hermes Plugin — full framework pipeline integration.
1
+ """Xray Hermes Plugin — full framework pipeline integration.
2
2
 
3
3
  Mirrors the OpenCode xray-codex-injection.ts behavior:
4
4
  1. Captures ALL tool calls and logs to disk
@@ -29,32 +29,31 @@ except ImportError:
29
29
  schemas = importlib.import_module("schemas")
30
30
  tools = importlib.import_module("tools")
31
31
 
32
- logger = logging.getLogger("strray-hermes")
32
+ logger = logging.getLogger("xray-hermes")
33
33
 
34
34
  # ── Paths ─────────────────────────────────────────────────────
35
35
 
36
36
  PLUGIN_DIR = Path(__file__).resolve().parent
37
37
  BRIDGE_PATH = PLUGIN_DIR / "bridge.mjs"
38
38
 
39
- # Project root: find the StringRay project directory
40
- # The plugin lives at ~/.hermes/plugins/ which is NOT inside any project tree,
41
- # so walking up from PLUGIN_DIR will never find the project. Instead:
42
- # 1. Check STRRAY_PROJECT_ROOT env var (explicit override)
43
- # 2. Walk up from cwd looking for node_modules/0xray or strray-ai (consumer install)
44
- ...
45
- # node_modules/0xray — consumer install marker
46
- if (d / "node_modules" / "0xray" / "package.json").exists() or (d / "node_modules" / "strray-ai" / "package.json").exists():
39
+ def _find_project_root() -> Path:
40
+ """Walk up from cwd to find project root."""
41
+ cwd = Path.cwd()
42
+ home = Path.home()
43
+ override = os.environ.get("XRAY_PROJECT_ROOT")
44
+ if override:
45
+ return Path(override).resolve()
46
+ d = cwd
47
+ while True:
48
+ if (d / "node_modules" / "0xray" / "package.json").exists():
47
49
  return d
48
- # .opencode/strray — dev repo marker
49
- if (d / ".opencode" / "strray" / "features.json").exists():
50
+ if (d / ".xray" / "features.json").exists():
50
51
  return d
51
- # package.json but not home dir
52
52
  if d != home and (d / "package.json").exists():
53
53
  return d
54
54
  d = d.parent
55
55
  if d == d.parent:
56
56
  break
57
-
58
57
  return cwd
59
58
 
60
59
  PROJECT_ROOT = _find_project_root()
@@ -79,20 +78,20 @@ _TOOL_AGENT_MAP = {
79
78
  "delegate_task": ("orchestrator", "delegation"),
80
79
  }
81
80
 
82
- # Tools where StringRay has a better alternative
81
+ # Tools where Xray has a better alternative
83
82
  # terminal: only nudge when the command looks lint/security/search related
84
- _BETTER_WITH_STRRAY = {
85
- "search_files": "Use mcp_strray_researcher_search_codebase for code pattern searches",
83
+ _BETTER_WITH_XRAY = {
84
+ "search_files": "Use mcp_xray_researcher_search_codebase for code pattern searches",
86
85
  }
87
86
 
88
87
  # Patterns that suggest the terminal command should use an MCP tool instead
89
88
  _TERMINAL_NUDGE_PATTERNS = {
90
- "grep": "Use mcp_strray_researcher_search_codebase instead of grep",
91
- "rg ": "Use mcp_strray_researcher_search_codebase instead of ripgrep",
92
- "eslint": "Use mcp_strray_lint_lint instead of raw eslint",
93
- "npx eslint": "Use mcp_strray_lint_lint instead of raw eslint",
94
- "npm audit": "Use mcp_strray_security_scan_security_scan instead of npm audit",
95
- "yarn audit": "Use mcp_strray_security_scan_security_scan instead of yarn audit",
89
+ "grep": "Use mcp_xray_researcher_search_codebase instead of grep",
90
+ "rg ": "Use mcp_xray_researcher_search_codebase instead of ripgrep",
91
+ "eslint": "Use mcp_xray_lint_lint instead of raw eslint",
92
+ "npx eslint": "Use mcp_xray_lint_lint instead of raw eslint",
93
+ "npm audit": "Use mcp_xray_security_scan_security_scan instead of npm audit",
94
+ "yarn audit": "Use mcp_xray_security_scan_security_scan instead of yarn audit",
96
95
  "find ": "Use search_files(target='files') instead of find",
97
96
  "sed ": "Use patch tool instead of sed",
98
97
  "awk ": "Use patch tool instead of awk",
@@ -108,7 +107,7 @@ _session_stats = {
108
107
  "session_id": None,
109
108
  "code_operations": 0,
110
109
  "total_tool_calls": 0,
111
- "strray_mcp_calls": 0,
110
+ "xray_mcp_calls": 0,
112
111
  "native_tool_calls": 0,
113
112
  "quality_gate_runs": 0,
114
113
  "quality_gate_blocks": 0,
@@ -184,8 +183,8 @@ def _call_bridge(command: dict, timeout: int = 10) -> dict:
184
183
 
185
184
  # ── Hook: pre_tool_call ───────────────────────────────────────
186
185
 
187
- def _is_strray_mcp(tool_name: str) -> bool:
188
- return tool_name.startswith("mcp_strray_")
186
+ def _is_xray_mcp(tool_name: str) -> bool:
187
+ return tool_name.startswith("mcp_xray_")
189
188
 
190
189
 
191
190
  def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
@@ -195,17 +194,17 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
195
194
  1. Track stats
196
195
  2. Log tool-start event to disk
197
196
  3. For code-producing tools: run quality gate + pre-processors via bridge
198
- 4. For non-code tools: nudge if StringRay alternative exists
197
+ 4. For non-code tools: nudge if Xray alternative exists
199
198
  """
200
199
  _session_stats["total_tool_calls"] += 1
201
200
 
202
201
  # Log start event
203
202
  _log_tool_event("start", tool_name, args)
204
203
 
205
- # StringRay MCP tools — track but don't interfere
206
- if _is_strray_mcp(tool_name):
207
- _session_stats["strray_mcp_calls"] += 1
208
- _log_to_file("activity.log", f"[quality-gate] SKIP (strray-mcp): {tool_name}")
204
+ # Xray MCP tools — track but don't interfere
205
+ if _is_xray_mcp(tool_name):
206
+ _session_stats["xray_mcp_calls"] += 1
207
+ _log_to_file("activity.log", f"[quality-gate] SKIP [xray-mcp]: {tool_name}")
209
208
  return
210
209
 
211
210
  # delegate_task: snapshot working tree so post_hook can validate changes
@@ -252,7 +251,7 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
252
251
  _log_to_file("activity.log",
253
252
  f"[quality-gate] BLOCKED: tool={tool_name} violations={violation_msg}")
254
253
  logger.warning(
255
- "[strray] Quality gate BLOCKED %s: %s",
254
+ "[xray] Quality gate BLOCKED %s: %s",
256
255
  tool_name, violation_msg,
257
256
  )
258
257
  else:
@@ -277,10 +276,10 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
277
276
  f"[bridge] ERROR in pre-process: {bridge_result.get('error', 'unknown')}")
278
277
  return
279
278
 
280
- # Non-code tools: nudge for StringRay alternatives
281
- if tool_name in _BETTER_WITH_STRRAY:
282
- tip = _BETTER_WITH_STRRAY[tool_name]
283
- logger.info("[strray] Tip: %s — %s", tool_name, tip)
279
+ # Non-code tools: nudge for Xray alternatives
280
+ if tool_name in _BETTER_WITH_XRAY:
281
+ tip = _BETTER_WITH_XRAY[tool_name]
282
+ logger.info("[xray] Tip: %s — %s", tool_name, tip)
284
283
  _log_to_file("activity.log",
285
284
  f"[nudge] {tool_name}: {tip}")
286
285
 
@@ -290,7 +289,7 @@ def _on_pre_tool_call(tool_name: str, args: dict, task_id: str, **kwargs):
290
289
  if isinstance(cmd, str):
291
290
  for pattern, tip in _TERMINAL_NUDGE_PATTERNS.items():
292
291
  if pattern in cmd:
293
- logger.info("[strray] Tip: %s — %s", tool_name, tip)
292
+ logger.info("[xray] Tip: %s — %s", tool_name, tip)
294
293
  _log_to_file("activity.log",
295
294
  f"[nudge] {tool_name}: {tip}")
296
295
  break
@@ -378,14 +377,14 @@ def _on_post_tool_call(tool_name: str, args: dict, result, task_id: str, **kwarg
378
377
  if calls - _last_tune_tool_call_count >= _INFERENCE_TUNE_INTERVAL:
379
378
  _last_tune_tool_call_count = calls
380
379
  logger.info(
381
- "[strray] Triggering inference tuning cycle (tool call #%d)", calls
380
+ "[xray] Triggering inference tuning cycle (tool call #%d)", calls
382
381
  )
383
382
  _log_to_file("activity.log",
384
383
  f"[inference-tune] auto-cycle at tool call #{calls}")
385
384
  try:
386
385
  _run_inference_tune()
387
386
  except Exception as e:
388
- logger.warning("[strray] Inference tuning failed: %s", e)
387
+ logger.warning("[xray] Inference tuning failed: %s", e)
389
388
 
390
389
 
391
390
  # ── Hook: session_start ───────────────────────────────────────
@@ -394,7 +393,7 @@ def _on_session_start(session_id: str, platform: str, **kwargs):
394
393
  """Fires when a new session starts. Resets stats, logs to disk."""
395
394
  _session_stats["started_at"] = datetime.now(timezone.utc).isoformat().replace("+00:00", "Z")
396
395
  _session_stats["session_id"] = session_id
397
- for key in ("code_operations", "total_tool_calls", "strray_mcp_calls",
396
+ for key in ("code_operations", "total_tool_calls", "xray_mcp_calls",
398
397
  "native_tool_calls", "quality_gate_runs", "quality_gate_blocks",
399
398
  "pre_processor_runs", "post_processor_runs",
400
399
  "bridge_calls", "bridge_errors",
@@ -406,23 +405,23 @@ def _on_session_start(session_id: str, platform: str, **kwargs):
406
405
  _ensure_log_dir()
407
406
  _log_to_file("activity.log",
408
407
  f"[session-start] session={session_id} platform={platform}")
409
- logger.info("[strray] Session %s started on %s", session_id, platform)
408
+ logger.info("[xray] Session %s started on %s", session_id, platform)
410
409
 
411
410
 
412
411
  # ── Slash command ─────────────────────────────────────────────
413
412
 
414
- def _strray_command(args: str) -> str:
415
- """Slash command handler: /strray [status|stats|help]"""
413
+ def _xray_command(args: str) -> str:
414
+ """Slash command handler: /xray [status|stats|help]"""
416
415
  cmd = (args or "status").strip().lower()
417
416
 
418
417
  if cmd == "stats":
419
418
  return (
420
- f"StringRay Session Stats\n"
419
+ f"Xray Session Stats\n"
421
420
  f" Session: {_session_stats['session_id'] or 'N/A'}\n"
422
421
  f" Started: {_session_stats['started_at'] or 'N/A'}\n"
423
422
  f" Tool calls: {_session_stats['total_tool_calls']}\n"
424
423
  f" Code operations: {_session_stats['code_operations']}\n"
425
- f" StringRay MCP: {_session_stats['strray_mcp_calls']}\n"
424
+ f" Xray MCP: {_session_stats['xray_mcp_calls']}\n"
426
425
  f" Native tools: {_session_stats['native_tool_calls']}\n"
427
426
  f" Quality gate runs: {_session_stats['quality_gate_runs']}\n"
428
427
  f" Quality gate blocks: {_session_stats['quality_gate_blocks']}\n"
@@ -437,19 +436,19 @@ def _strray_command(args: str) -> str:
437
436
 
438
437
  if cmd == "help":
439
438
  return (
440
- "StringRay Commands:\n"
441
- " /strray status — Plugin and framework health\n"
442
- " /strray stats — Session pipeline statistics\n"
443
- " /strray help — This message"
439
+ "Xray Commands:\n"
440
+ " /xray status — Plugin and framework health\n"
441
+ " /xray stats — Session pipeline statistics\n"
442
+ " /xray help — This message"
444
443
  )
445
444
 
446
445
  # Default: status (calls bridge health)
447
446
  bridge_result = _call_bridge({"command": "health"}, timeout=10)
448
447
  if "error" in bridge_result:
449
- return f"StringRay plugin loaded. Bridge: {bridge_result['error']}"
448
+ return f"Xray plugin loaded. Bridge: {bridge_result['error']}"
450
449
 
451
450
  return (
452
- f"StringRay Hermes Plugin Status\n"
451
+ f"Xray Hermes Plugin Status\n"
453
452
  f" Framework: {bridge_result.get('framework', 'unknown')}\n"
454
453
  f" Version: {bridge_result.get('version', 'unknown')}\n"
455
454
  f" Quality Gate: {'ready' if bridge_result.get('components', {}).get('qualityGate') else 'not loaded'}\n"
@@ -518,13 +517,13 @@ def _record_tool_outcome(tool_name: str, args: dict, success: bool):
518
517
  with open(_OUTCOMES_PATH, "w") as f:
519
518
  json.dump(outcomes, f, indent=2)
520
519
  except Exception as e:
521
- logger.debug("[strray] outcome recording failed: %s", e)
520
+ logger.debug("[xray] outcome recording failed: %s", e)
522
521
 
523
522
 
524
523
  # ── Inference tuning (auto-calibration) ────────────────────────
525
524
 
526
525
  def _run_inference_tune():
527
- """Shell out to strray-ai inference:tuner --run-once.
526
+ """Shell out to 0xray inference:tuner --run-once.
528
527
 
529
528
  Runs in a background thread so it doesn't block the tool call pipeline.
530
529
  The tuner reads routing outcomes, runs the analytics pipeline, and
@@ -560,7 +559,7 @@ def _run_inference_tune():
560
559
  # ── Registration ──────────────────────────────────────────────
561
560
 
562
561
  # ── Subagent (delegate_task) enforcement ────────────────────
563
- # Subagents bypass all StringRay hooks because they run in isolated
562
+ # Subagents bypass all Xray hooks because they run in isolated
564
563
  # contexts. We enforce by snapshotting the working tree before dispatch
565
564
  # and validating all changed files after return.
566
565
 
@@ -647,7 +646,7 @@ def _validate_subagent_changes(task_id: str, **kwargs):
647
646
  f"[subagent-validate] BLOCKED: {rel_path} "
648
647
  f"violations={'; '.join(str(v) for v in violations[:3])}")
649
648
  logger.warning(
650
- "[strray] Subagent BLOCKED %s: %s",
649
+ "[xray] Subagent BLOCKED %s: %s",
651
650
  rel_path, violations[:3],
652
651
  )
653
652
  else:
@@ -659,28 +658,40 @@ def register(ctx):
659
658
  """Wire schemas to handlers and register lifecycle hooks."""
660
659
  # ── Register tools ────────────────────────────────────────
661
660
  ctx.register_tool(
662
- name="strray_validate",
663
- toolset="strray-hermes",
664
- schema=schemas.STRRAY_VALIDATE,
665
- handler=tools.strray_validate,
661
+ name="xray_validate",
662
+ toolset="xray-hermes",
663
+ schema=schemas.XRAY_VALIDATE,
664
+ handler=tools.xray_validate,
665
+ )
666
+ ctx.register_tool(
667
+ name="xray_codex_check",
668
+ toolset="xray-hermes",
669
+ schema=schemas.XRAY_CODEX_CHECK,
670
+ handler=tools.xray_codex_check,
671
+ )
672
+ ctx.register_tool(
673
+ name="xray_health",
674
+ toolset="xray-hermes",
675
+ schema=schemas.XRAY_HEALTH,
676
+ handler=tools.xray_health,
666
677
  )
667
678
  ctx.register_tool(
668
- name="strray_codex_check",
669
- toolset="strray-hermes",
670
- schema=schemas.STRRAY_CODEX_CHECK,
671
- handler=tools.strray_codex_check,
679
+ name="xray_hooks",
680
+ toolset="xray-hermes",
681
+ schema=schemas.XRAY_HOOKS,
682
+ handler=tools.xray_hooks,
672
683
  )
673
684
  ctx.register_tool(
674
- name="strray_health",
675
- toolset="strray-hermes",
676
- schema=schemas.STRRAY_HEALTH,
677
- handler=tools.strray_health,
685
+ name="xray_skill_install",
686
+ toolset="xray-hermes",
687
+ schema=schemas.XRAY_SKILL_INSTALL,
688
+ handler=tools.xray_skill_install,
678
689
  )
679
690
  ctx.register_tool(
680
- name="strray_hooks",
681
- toolset="strray-hermes",
682
- schema=schemas.STRRAY_HOOKS,
683
- handler=tools.strray_hooks,
691
+ name="xray_skill_registry",
692
+ toolset="xray-hermes",
693
+ schema=schemas.XRAY_SKILL_REGISTRY,
694
+ handler=tools.xray_skill_registry,
684
695
  )
685
696
 
686
697
  # ── Register hooks ────────────────────────────────────────
@@ -691,28 +702,28 @@ def register(ctx):
691
702
  try:
692
703
  ctx.register_hook("on_session_start", _on_session_start)
693
704
  except (AttributeError, TypeError):
694
- logger.debug("[strray] on_session_start hook not yet available")
705
+ logger.debug("[xray] on_session_start hook not yet available")
695
706
 
696
707
  # ── Register slash command ────────────────────────────────
697
708
  try:
698
709
  ctx.register_command(
699
- name="strray",
700
- handler=_strray_command,
701
- description="StringRay status, stats, hooks, and enforcement info",
710
+ name="xray",
711
+ handler=_xray_command,
712
+ description="Xray status, stats, hooks, and enforcement info",
702
713
  args_hint="[status|stats|help]",
703
714
  aliases=("sr",),
704
715
  )
705
716
  except (AttributeError, TypeError):
706
- logger.debug("[strray] Slash command registration not yet available")
717
+ logger.debug("[xray] Slash command registration not yet available")
707
718
 
708
719
  # ── Bootstrap ─────────────────────────────────────────────
709
720
  _ensure_log_dir()
710
721
  _log_to_file("activity.log",
711
- f"[plugin-loaded] StringRay Hermes Plugin v2.2 — "
712
- f"4 tools, 2 hooks, subagent enforcement, bridge={BRIDGE_PATH.exists()}")
722
+ f"[plugin-loaded] Xray Hermes Plugin v2.2 — "
723
+ f"6 tools, 2 hooks, subagent enforcement, bridge={BRIDGE_PATH.exists()}")
713
724
 
714
725
  logger.info(
715
- "[strray] Plugin v2.2 loaded: 4 tools, 2 hooks, "
726
+ "[xray] Plugin v2.2 loaded: 6 tools, 2 hooks, "
716
727
  "subagent enforcement active, bridge=%s",
717
728
  BRIDGE_PATH.exists(),
718
729
  )
@@ -1,4 +1,4 @@
1
- # StringRay Hermes Plugin Installed
1
+ # Xray Hermes Plugin Installed
2
2
 
3
3
  **Restart your Hermes session** for the plugin to take effect.
4
4
 
@@ -6,10 +6,10 @@
6
6
 
7
7
  | Component | Description |
8
8
  |-----------|-------------|
9
- | `strray_validate` | Pre-commit validation with quality gates |
10
- | `strray_codex_check` | Code review against 60 Codex error-prevention rules |
11
- | `strray_health` | Framework health check |
12
- | `strray_hooks` | Git hooks management (install, uninstall, list, status) |
9
+ | `xray_validate` | Pre-commit validation with quality gates |
10
+ | `xray_codex_check` | Code review against 60 Codex error-prevention rules |
11
+ | `xray_health` | Framework health check |
12
+ | `xray_hooks` | Git hooks management (install, uninstall, list, status) |
13
13
  | `pre_tool_call` hook | Quality gates + nudges before every tool call |
14
14
  | `post_tool_call` hook | Post-processors after every tool call |
15
15
 
@@ -27,24 +27,24 @@ The plugin can install git hooks for automated validation:
27
27
  ### Install Hooks
28
28
 
29
29
  ```
30
- /strray hooks install
30
+ /xray hooks install
31
31
  ```
32
32
 
33
33
  Or use the tool directly:
34
34
  ```
35
- strray_hooks(action="install")
35
+ xray_hooks(action="install")
36
36
  ```
37
37
 
38
38
  ### Check Hook Status
39
39
 
40
40
  ```
41
- /strray hooks status
41
+ /xray hooks status
42
42
  ```
43
43
 
44
44
  ### Uninstall Hooks
45
45
 
46
46
  ```
47
- /strray hooks uninstall
47
+ /xray hooks uninstall
48
48
  ```
49
49
 
50
50
  ## Quick Test
@@ -52,20 +52,20 @@ strray_hooks(action="install")
52
52
  After restarting Hermes, try:
53
53
 
54
54
  ```
55
- /strray status
56
- /strray stats
55
+ /xray status
56
+ /xray stats
57
57
  ```
58
58
 
59
- Or use the tools directly — `strray_health` will confirm the bridge is connected.
59
+ Or use the tools directly — `xray_health` will confirm the bridge is connected.
60
60
 
61
61
  ## MCP Servers
62
62
 
63
- The plugin works alongside StringRay's MCP servers (if configured in your
63
+ The plugin works alongside Xray's MCP servers (if configured in your
64
64
  Hermes config). The plugin's native tools provide offline/offline-first
65
65
  validation, while MCP servers offer deeper framework integration.
66
66
 
67
67
  ## Files
68
68
 
69
- The plugin lives at `~/.hermes/plugins/strray-hermes/`. It is auto-updated
69
+ The plugin lives at `~/.hermes/plugins/xray-hermes/`. It is auto-updated
70
70
  when you run `npm install` or `npm update` in a project with `0xray`
71
71
  as a dependency.
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * StringRay Framework Bridge for Hermes Agent
4
+ * Xray Framework Bridge for Hermes Agent
5
5
  *
6
- * Provides direct access to StringRay framework components
6
+ * Provides direct access to Xray framework components
7
7
  * (ProcessorManager, QualityGate, StateManager) from Python.
8
8
  * Uses JSON stdin/stdout protocol for IPC.
9
9
  *
@@ -44,7 +44,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
44
44
 
45
45
  // ── Framework components (lazy-loaded) ───────────────────────
46
46
  let ProcessorManager = null;
47
- let StrRayStateManager = null;
47
+ let XrayStateManager = null;
48
48
  let featuresConfigLoader = null;
49
49
  let runQualityGateWithLogging = null;
50
50
  let enforcerValidators = null;
@@ -53,12 +53,12 @@ let frameworkLoadAttempted = false;
53
53
 
54
54
  // ── Project root detection ───────────────────────────────────
55
55
  function findProjectRoot() {
56
- const envHome = process.env.STRRAY_HOME;
56
+ const envHome = process.env.XRAY_HOME;
57
57
  if (envHome && existsSync(join(envHome, "package.json"))) return envHome;
58
58
 
59
59
  const candidates = [
60
60
  process.cwd(),
61
- join(homedir(), "dev", "stringray"),
61
+ join(homedir(), "dev", "xray"),
62
62
  join(dirname(__dirname), "..", "..", "..", ".."), // plugin dir -> project root
63
63
  ];
64
64
 
@@ -67,7 +67,7 @@ function findProjectRoot() {
67
67
  const pkgPath = join(dir, "package.json");
68
68
  if (existsSync(pkgPath)) {
69
69
  const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
70
- if (pkg.name === "strray-ai" || pkg.dependencies?.["strray-ai"] || pkg.name === "0xray" || pkg.dependencies?.["0xray"]) {
70
+ if (pkg.name === "0xray" || pkg.dependencies?.["0xray"] || pkg.name === "0xray" || pkg.dependencies?.["0xray"]) {
71
71
  return dir;
72
72
  }
73
73
  }
@@ -149,11 +149,11 @@ async function loadFramework(projectRoot) {
149
149
  }
150
150
  }
151
151
 
152
- if (!StrRayStateManager) {
152
+ if (!XrayStateManager) {
153
153
  const smPath = join(distDir, "state", "state-manager.js");
154
154
  if (existsSync(smPath)) {
155
155
  const sm = await import(smPath);
156
- StrRayStateManager = sm.StrRayStateManager;
156
+ XrayStateManager = sm.XrayStateManager;
157
157
  }
158
158
  }
159
159
 
@@ -230,15 +230,15 @@ async function runQualityGateCheck(context, projectRoot, logDir) {
230
230
 
231
231
  // ── Processor Pipeline ───────────────────────────────────────
232
232
  async function runProcessors(tool, args, phase, projectRoot, logDir) {
233
- if (!ProcessorManager || !StrRayStateManager) {
233
+ if (!ProcessorManager || !XrayStateManager) {
234
234
  return { ran: false, reason: "framework modules not loaded" };
235
235
  }
236
236
 
237
237
  const logger = new BridgeLogger(logDir);
238
238
 
239
239
  try {
240
- const stateDir = join(projectRoot, ".strray", "state");
241
- const stateManager = new StrRayStateManager(stateDir);
240
+ const stateDir = join(projectRoot, ".xray", "state");
241
+ const stateManager = new XrayStateManager(stateDir);
242
242
  const processorManager = new ProcessorManager(stateManager);
243
243
 
244
244
  // Register processors matching OpenCode plugin
@@ -353,7 +353,7 @@ async function handleHealth(input) {
353
353
  const components = {
354
354
  qualityGate: !!runQualityGateWithLogging,
355
355
  processorManager: !!ProcessorManager,
356
- stateManager: !!StrRayStateManager,
356
+ stateManager: !!XrayStateManager,
357
357
  featuresConfig: !!featuresConfigLoader,
358
358
  };
359
359
 
@@ -563,7 +563,7 @@ function handleHooks(input, projectRoot) {
563
563
  const { action, hooks } = input;
564
564
  const hookTypes = hooks || ["pre-commit", "post-commit", "pre-push", "post-push"];
565
565
  const gitHooksDir = join(projectRoot, ".git", "hooks");
566
- const strrayHooksDir = join(projectRoot, "hooks");
566
+ const xrayHooksDir = join(projectRoot, "hooks");
567
567
 
568
568
  if (!existsSync(gitHooksDir)) {
569
569
  return { error: "Not a git repository — no .git/hooks directory" };
@@ -575,14 +575,14 @@ function handleHooks(input, projectRoot) {
575
575
  if (action === "list" || action === "status") {
576
576
  for (const hookName of hookTypes) {
577
577
  const gitHook = join(gitHooksDir, hookName);
578
- const strrayHook = join(strrayHooksDir, hookName);
578
+ const xrayHook = join(xrayHooksDir, hookName);
579
579
 
580
580
  if (!existsSync(gitHook)) {
581
581
  result.missing.push(hookName);
582
582
  } else {
583
583
  try {
584
584
  const content = readFileSync(gitHook, "utf-8");
585
- if (content.includes("StringRay") || content.includes("strray") || content.includes("run-hook.js")) {
585
+ if (content.includes("Xray") || content.includes("xray") || false || content.includes("run-hook.js")) {
586
586
  result.managed.push(hookName);
587
587
  } else {
588
588
  result.external.push(hookName);
@@ -592,8 +592,8 @@ function handleHooks(input, projectRoot) {
592
592
  }
593
593
  }
594
594
 
595
- // Check if strray source hook exists
596
- if (!existsSync(strrayHook)) {
595
+ // Check if xray source hook exists
596
+ if (!existsSync(xrayHook)) {
597
597
  result.stale.push(hookName);
598
598
  }
599
599
  }
@@ -603,7 +603,7 @@ function handleHooks(input, projectRoot) {
603
603
  action,
604
604
  hooks: result,
605
605
  gitHooksDir,
606
- strrayHooksDir,
606
+ xrayHooksDir,
607
607
  };
608
608
  }
609
609
 
@@ -614,7 +614,7 @@ function handleHooks(input, projectRoot) {
614
614
  const errors = [];
615
615
 
616
616
  for (const hookName of hookTypes) {
617
- const src = join(strrayHooksDir, hookName);
617
+ const src = join(xrayHooksDir, hookName);
618
618
  const dst = join(gitHooksDir, hookName);
619
619
 
620
620
  if (!existsSync(src)) {
@@ -623,11 +623,11 @@ function handleHooks(input, projectRoot) {
623
623
  }
624
624
 
625
625
  try {
626
- // Backup existing non-strray hooks
626
+ // Backup existing non-xray hooks
627
627
  if (existsSync(dst)) {
628
628
  const content = readFileSync(dst, "utf-8");
629
- if (!content.includes("StringRay") && !content.includes("strray") && !content.includes("run-hook.js")) {
630
- renameSync(dst, `${dst}.strray-backup`);
629
+ if (!content.includes("Xray") && !content.includes("xray") && !false && !content.includes("run-hook.js")) {
630
+ renameSync(dst, `${dst}.xray-backup`);
631
631
  } else {
632
632
  unlinkSync(dst);
633
633
  }
@@ -659,15 +659,15 @@ function handleHooks(input, projectRoot) {
659
659
 
660
660
  for (const hookName of hookTypes) {
661
661
  const dst = join(gitHooksDir, hookName);
662
- const backup = `${dst}.strray-backup`;
662
+ const backup = `${dst}.xray-backup`;
663
663
 
664
664
  if (!existsSync(dst)) continue;
665
665
 
666
666
  try {
667
667
  const content = readFileSync(dst, "utf-8");
668
- const isStrray = content.includes("StringRay") || content.includes("strray") || content.includes("run-hook.js");
668
+ const isXray = content.includes("Xray") || content.includes("xray") || false || content.includes("run-hook.js");
669
669
 
670
- if (isStrray || lstatSync(dst).isSymbolicLink()) {
670
+ if (isXray || lstatSync(dst).isSymbolicLink()) {
671
671
  unlinkSync(dst);
672
672
 
673
673
  // Restore backup if exists
@@ -743,8 +743,37 @@ async function handleApply(input, projectRoot, logDir) {
743
743
  // ── Known commands for positional-arg mode ──────────────────
744
744
  const KNOWN_COMMANDS = new Set([
745
745
  "health", "stats", "pre-process", "post-process", "validate", "codex-check", "hooks", "govern", "apply",
746
+ "skill-install", "skill-registry",
746
747
  ]);
747
748
 
749
+ // ── Skill management ──────────────────────────────────────────
750
+
751
+ async function handleSkillInstall(command, projectRoot, logDir) {
752
+ try {
753
+ const source = command.source;
754
+ if (!source) {
755
+ return { error: "Missing 'source' — specify a source name or git URL" };
756
+ }
757
+ const { execSync } = await import("child_process");
758
+ const output = execSync(`npx 0xray skill:install "${source}"`, { cwd: projectRoot, timeout: 120000 }).toString();
759
+ return { status: "ok", output: output.trim() };
760
+ } catch (error) {
761
+ return { error: `Skill install failed: ${error.message || error}` };
762
+ }
763
+ }
764
+
765
+ async function handleSkillRegistry(command, projectRoot, logDir) {
766
+ try {
767
+ const action = command.action || "list";
768
+ const { execSync } = await import("child_process");
769
+ const args = command.source ? `"${command.source}"` : "";
770
+ const output = execSync(`npx 0xray skill:registry ${action} ${args}`, { cwd: projectRoot, timeout: 30000 }).toString();
771
+ return { status: "ok", output: output.trim() };
772
+ } catch (error) {
773
+ return { error: `Skill registry command failed: ${error.message || error}` };
774
+ }
775
+ }
776
+
748
777
  // ── Main ─────────────────────────────────────────────────────
749
778
  async function main() {
750
779
  // Parse --cwd flag and detect positional command arg
@@ -836,6 +865,12 @@ async function main() {
836
865
  case "apply":
837
866
  response = await handleApply(command, projectRoot, logDir);
838
867
  break;
868
+ case "skill-install":
869
+ response = await handleSkillInstall(command, projectRoot, logDir);
870
+ break;
871
+ case "skill-registry":
872
+ response = await handleSkillRegistry(command, projectRoot, logDir);
873
+ break;
839
874
  default:
840
875
  response = { error: `Unknown command: ${cmd}` };
841
876
  }