@toolu/opencode 6.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. package/generated/GENERATED-NOTES.md +16 -0
  2. package/generated/agents/toolu--architect.md +52 -0
  3. package/generated/agents/toolu--deep-explore.md +65 -0
  4. package/generated/agents/toolu--implementer.md +50 -0
  5. package/generated/agents/toolu--quick-task.md +54 -0
  6. package/generated/agents/toolu--research-agent.md +101 -0
  7. package/generated/commands/toolu--commit.md +8 -0
  8. package/generated/commands/toolu--review-and-commit.md +8 -0
  9. package/generated/opencode.toolu.json +116 -0
  10. package/generated/skills/toolu--brainstorm/SKILL.md +57 -0
  11. package/generated/skills/toolu--brainstorm/references/design-questions.md +36 -0
  12. package/generated/skills/toolu--commit--skill/SKILL.md +11 -0
  13. package/generated/skills/toolu--debug/SKILL.md +54 -0
  14. package/generated/skills/toolu--deep-research/SKILL.md +51 -0
  15. package/generated/skills/toolu--execution/SKILL.md +77 -0
  16. package/generated/skills/toolu--orchestrator/SKILL.md +145 -0
  17. package/generated/skills/toolu--orchestrator/references/delegation-cost.md +104 -0
  18. package/generated/skills/toolu--orchestrator/references/model-routing.md +112 -0
  19. package/generated/skills/toolu--plan/SKILL.md +56 -0
  20. package/generated/skills/toolu--plan/references/ledger.md +18 -0
  21. package/generated/skills/toolu--plan-review/SKILL.md +48 -0
  22. package/generated/skills/toolu--review-and-commit--skill/SKILL.md +10 -0
  23. package/generated/skills/toolu--setup/SKILL.md +24 -0
  24. package/generated/skills/toolu--setup/scripts/setup.sh +206 -0
  25. package/generated/skills/toolu--spec/SKILL.md +67 -0
  26. package/generated/skills/toolu--spec-review/SKILL.md +50 -0
  27. package/generated/skills/toolu--test/SKILL.md +49 -0
  28. package/package.json +51 -0
  29. package/plugins/agent-browser/.claude-plugin/plugin.json +18 -0
  30. package/plugins/agent-browser/.codex-plugin/plugin.json +7 -0
  31. package/plugins/agent-browser/README.md +18 -0
  32. package/plugins/agent-browser/hooks/hooks.json +15 -0
  33. package/plugins/agent-browser/hooks/session-start.sh +42 -0
  34. package/plugins/agent-browser/skills/agent-browser/SKILL.md +77 -0
  35. package/plugins/agent-browser/skills/agent-browser/scripts/agent-browser.sh +80 -0
  36. package/plugins/ast-grep/.claude-plugin/plugin.json +18 -0
  37. package/plugins/ast-grep/.codex-plugin/plugin.json +7 -0
  38. package/plugins/ast-grep/README.md +21 -0
  39. package/plugins/ast-grep/hooks/hooks.json +15 -0
  40. package/plugins/ast-grep/hooks/post-tools.d/byte-savings.sh +67 -0
  41. package/plugins/ast-grep/hooks/pre-tools.d/search-nudge.sh +170 -0
  42. package/plugins/ast-grep/hooks/register.sh +68 -0
  43. package/plugins/ast-grep/scripts/byte-savings-report.sh +28 -0
  44. package/plugins/ast-grep/skills/ast-grep/SKILL.md +127 -0
  45. package/plugins/ast-grep/skills/ast-grep/references/ast-grep-advanced.md +44 -0
  46. package/plugins/ast-grep/skills/ast-grep/scripts/ast-grep.sh +103 -0
  47. package/plugins/context7/.claude-plugin/plugin.json +18 -0
  48. package/plugins/context7/.codex-plugin/plugin.json +7 -0
  49. package/plugins/context7/README.md +19 -0
  50. package/plugins/context7/hooks/hooks.json +15 -0
  51. package/plugins/context7/hooks/session-start.sh +42 -0
  52. package/plugins/context7/skills/context7/SKILL.md +64 -0
  53. package/plugins/context7/skills/context7/scripts/search.sh +151 -0
  54. package/plugins/exa-search/.claude-plugin/plugin.json +18 -0
  55. package/plugins/exa-search/.codex-plugin/plugin.json +7 -0
  56. package/plugins/exa-search/README.md +19 -0
  57. package/plugins/exa-search/hooks/hooks.json +15 -0
  58. package/plugins/exa-search/hooks/session-start.sh +34 -0
  59. package/plugins/exa-search/skills/exa-search/SKILL.md +91 -0
  60. package/plugins/exa-search/skills/exa-search/scripts/search.sh +221 -0
  61. package/plugins/jev/.claude-plugin/plugin.json +19 -0
  62. package/plugins/jev/.codex-plugin/plugin.json +7 -0
  63. package/plugins/jev/README.md +61 -0
  64. package/plugins/jev/hooks/hooks.json +25 -0
  65. package/plugins/jev/hooks/lib/common.sh +49 -0
  66. package/plugins/jev/hooks/session-start.sh +45 -0
  67. package/plugins/jev/hooks/user-prompt-submit.sh +41 -0
  68. package/plugins/jev/skills/jev/SKILL.md +81 -0
  69. package/plugins/jev/skills/jev/evals/README.md +98 -0
  70. package/plugins/jev/skills/jev/references/problem-solving.md +198 -0
  71. package/plugins/jev/skills/jev/scripts/jev.sh +405 -0
  72. package/plugins/jira/.claude-plugin/plugin.json +18 -0
  73. package/plugins/jira/.codex-plugin/plugin.json +7 -0
  74. package/plugins/jira/README.md +42 -0
  75. package/plugins/jira/hooks/hooks.json +15 -0
  76. package/plugins/jira/hooks/session-start.sh +34 -0
  77. package/plugins/jira/skills/jira/SKILL.md +123 -0
  78. package/plugins/jira/skills/jira/scripts/jira.sh +70 -0
  79. package/plugins/jira/skills/jira/scripts/lib/adf.sh +17 -0
  80. package/plugins/jira/skills/jira/scripts/lib/attachment.sh +94 -0
  81. package/plugins/jira/skills/jira/scripts/lib/board.sh +58 -0
  82. package/plugins/jira/skills/jira/scripts/lib/http.sh +184 -0
  83. package/plugins/jira/skills/jira/scripts/lib/issue.sh +159 -0
  84. package/plugins/jira/skills/jira/scripts/lib/paginate.sh +45 -0
  85. package/plugins/jira/skills/jira/scripts/lib/plan-parse.sh +70 -0
  86. package/plugins/jira/skills/jira/scripts/lib/plan-run.sh +115 -0
  87. package/plugins/jira/skills/jira/scripts/lib/plan-store.sh +168 -0
  88. package/plugins/jira/skills/jira/scripts/lib/plan.sh +108 -0
  89. package/plugins/jira/skills/jira/scripts/lib/project.sh +42 -0
  90. package/plugins/jira/skills/jira/scripts/lib/raw.sh +15 -0
  91. package/plugins/jira/skills/jira/scripts/lib/search.sh +41 -0
  92. package/plugins/jira/skills/jira/scripts/lib/sprint.sh +88 -0
  93. package/plugins/jira/skills/jira/scripts/lib/user.sh +45 -0
  94. package/plugins/jira/skills/jira/scripts/lib/worklog.sh +56 -0
  95. package/plugins/pr-babysit/.claude-plugin/plugin.json +25 -0
  96. package/plugins/pr-babysit/.codex-plugin/plugin.json +7 -0
  97. package/plugins/pr-babysit/README.md +38 -0
  98. package/plugins/pr-babysit/commands/babysit.md +13 -0
  99. package/plugins/pr-babysit/hooks/check-toolu.sh +20 -0
  100. package/plugins/pr-babysit/hooks/hooks.json +15 -0
  101. package/plugins/pr-babysit/scripts/babysit-tick.sh +133 -0
  102. package/plugins/pr-babysit/scripts/collect-pr.sh +224 -0
  103. package/plugins/pr-babysit/scripts/lib/common.sh +146 -0
  104. package/plugins/pr-babysit/scripts/lib/gh.sh +150 -0
  105. package/plugins/pr-babysit/scripts/lib/lock.sh +84 -0
  106. package/plugins/pr-babysit/scripts/lib/normalize.sh +98 -0
  107. package/plugins/pr-babysit/scripts/lib/state.sh +37 -0
  108. package/plugins/pr-babysit/scripts/parse-verdict.sh +171 -0
  109. package/plugins/pr-babysit/scripts/record.sh +69 -0
  110. package/plugins/pr-babysit/scripts/reduce-state.sh +245 -0
  111. package/plugins/pr-babysit/scripts/reply-thread.sh +90 -0
  112. package/plugins/pr-babysit/scripts/resolve-thread.sh +71 -0
  113. package/plugins/pr-babysit/skills/babysit/SKILL.md +31 -0
  114. package/plugins/pr-babysit/skills/babysit/references/helper.md +209 -0
  115. package/plugins/pr-babysit/workflows/babysit.md +722 -0
  116. package/plugins/python-quality/.claude-plugin/plugin.json +24 -0
  117. package/plugins/python-quality/.codex-plugin/plugin.json +6 -0
  118. package/plugins/python-quality/README.md +23 -0
  119. package/plugins/python-quality/hooks/check-toolu.sh +20 -0
  120. package/plugins/python-quality/hooks/concerns/00-preamble.sh +85 -0
  121. package/plugins/python-quality/hooks/concerns/10-size-file.sh +6 -0
  122. package/plugins/python-quality/hooks/concerns/20-tests.sh +37 -0
  123. package/plugins/python-quality/hooks/concerns/30-suppression.sh +33 -0
  124. package/plugins/python-quality/hooks/concerns/50-size-fn.sh +49 -0
  125. package/plugins/python-quality/hooks/concerns/70-no-mocks.sh +76 -0
  126. package/plugins/python-quality/hooks/concerns/90-docs.sh +52 -0
  127. package/plugins/python-quality/hooks/concerns/99-finalize.sh +36 -0
  128. package/plugins/python-quality/hooks/hooks.json +19 -0
  129. package/plugins/python-quality/hooks/register.sh +65 -0
  130. package/plugins/rust-quality/.claude-plugin/plugin.json +24 -0
  131. package/plugins/rust-quality/.codex-plugin/plugin.json +6 -0
  132. package/plugins/rust-quality/README.md +24 -0
  133. package/plugins/rust-quality/hooks/check-toolu.sh +20 -0
  134. package/plugins/rust-quality/hooks/concerns/00-preamble.sh +93 -0
  135. package/plugins/rust-quality/hooks/concerns/10-size-file.sh +10 -0
  136. package/plugins/rust-quality/hooks/concerns/20-tests.sh +84 -0
  137. package/plugins/rust-quality/hooks/concerns/30-suppression.sh +26 -0
  138. package/plugins/rust-quality/hooks/concerns/40-unsafe.sh +39 -0
  139. package/plugins/rust-quality/hooks/concerns/50-size-fn.sh +38 -0
  140. package/plugins/rust-quality/hooks/concerns/55-size-impl.sh +28 -0
  141. package/plugins/rust-quality/hooks/concerns/60-error-handling.sh +149 -0
  142. package/plugins/rust-quality/hooks/concerns/70-no-mocks.sh +139 -0
  143. package/plugins/rust-quality/hooks/concerns/90-docs.sh +32 -0
  144. package/plugins/rust-quality/hooks/concerns/99-finalize.sh +36 -0
  145. package/plugins/rust-quality/hooks/hooks.json +19 -0
  146. package/plugins/rust-quality/hooks/register.sh +65 -0
  147. package/plugins/statusline/.claude-plugin/plugin.json +19 -0
  148. package/plugins/statusline/.codex-plugin/plugin.json +7 -0
  149. package/plugins/statusline/README.md +108 -0
  150. package/plugins/statusline/commands/setup.md +30 -0
  151. package/plugins/statusline/hooks/hooks.json +15 -0
  152. package/plugins/statusline/hooks/session-start.sh +45 -0
  153. package/plugins/statusline/scripts/collect-status.sh +147 -0
  154. package/plugins/statusline/scripts/setup.sh +93 -0
  155. package/plugins/statusline/scripts/status.sh +55 -0
  156. package/plugins/statusline/skills/status/SKILL.md +13 -0
  157. package/plugins/statusline/statusline.sh +177 -0
  158. package/plugins/toolu/.claude-plugin/plugin.json +19 -0
  159. package/plugins/toolu/.codex-plugin/plugin.json +7 -0
  160. package/plugins/toolu/README.md +35 -0
  161. package/plugins/toolu/agents/.gitkeep +0 -0
  162. package/plugins/toolu/agents/architect.md +52 -0
  163. package/plugins/toolu/agents/deep-explore.md +65 -0
  164. package/plugins/toolu/agents/implementer.md +50 -0
  165. package/plugins/toolu/agents/quick-task.md +54 -0
  166. package/plugins/toolu/agents/research-agent.md +107 -0
  167. package/plugins/toolu/assets/agents/architect.toml +9 -0
  168. package/plugins/toolu/assets/agents/deep-explore.toml +9 -0
  169. package/plugins/toolu/assets/agents/implementer.toml +9 -0
  170. package/plugins/toolu/assets/agents/quick-task.toml +9 -0
  171. package/plugins/toolu/assets/agents/research-agent.toml +9 -0
  172. package/plugins/toolu/commands/.gitkeep +0 -0
  173. package/plugins/toolu/commands/commit.md +5 -0
  174. package/plugins/toolu/commands/review-and-commit.md +5 -0
  175. package/plugins/toolu/hooks/docs/gates.md +157 -0
  176. package/plugins/toolu/hooks/docs/model-routing.md +14 -0
  177. package/plugins/toolu/hooks/docs/post-compaction.md +3 -0
  178. package/plugins/toolu/hooks/docs/push-review.md +123 -0
  179. package/plugins/toolu/hooks/docs/session-start-python.md +3 -0
  180. package/plugins/toolu/hooks/docs/session-start-rust.md +4 -0
  181. package/plugins/toolu/hooks/docs/session-start-ts.md +3 -0
  182. package/plugins/toolu/hooks/docs/session-start.md +16 -0
  183. package/plugins/toolu/hooks/hooks.json +76 -0
  184. package/plugins/toolu/hooks/lib/config.sh +355 -0
  185. package/plugins/toolu/hooks/lib/detect.sh +929 -0
  186. package/plugins/toolu/hooks/lib/diff-sha.sh +32 -0
  187. package/plugins/toolu/hooks/lib/dispatch.sh +365 -0
  188. package/plugins/toolu/hooks/lib/docs-sync-config.sh +81 -0
  189. package/plugins/toolu/hooks/lib/edit-records.sh +157 -0
  190. package/plugins/toolu/hooks/lib/gate-file.sh +201 -0
  191. package/plugins/toolu/hooks/lib/gate-mode.sh +244 -0
  192. package/plugins/toolu/hooks/lib/host.sh +205 -0
  193. package/plugins/toolu/hooks/lib/permissions.sh +125 -0
  194. package/plugins/toolu/hooks/lib/plan-ledger-parse.sh +219 -0
  195. package/plugins/toolu/hooks/lib/plan-ledger-preflight.sh +137 -0
  196. package/plugins/toolu/hooks/lib/plan-ledger.sh +749 -0
  197. package/plugins/toolu/hooks/lib/push-waiver.sh +116 -0
  198. package/plugins/toolu/hooks/lib/quality-config.sh +184 -0
  199. package/plugins/toolu/hooks/lib/registry.sh +72 -0
  200. package/plugins/toolu/hooks/lib/state-sweeper.sh +194 -0
  201. package/plugins/toolu/hooks/lib/telemetry.sh +94 -0
  202. package/plugins/toolu/hooks/lib/verdict.sh +477 -0
  203. package/plugins/toolu/hooks/post-tools/mod.sh +42 -0
  204. package/plugins/toolu/hooks/post-tools/modules/gate-status.sh +140 -0
  205. package/plugins/toolu/hooks/post-tools/modules/push-waiver.sh +97 -0
  206. package/plugins/toolu/hooks/pre-compact.sh +18 -0
  207. package/plugins/toolu/hooks/pre-tools/agent-tier.sh +111 -0
  208. package/plugins/toolu/hooks/pre-tools/mod.sh +37 -0
  209. package/plugins/toolu/hooks/pre-tools/modules/bash-commands.sh +187 -0
  210. package/plugins/toolu/hooks/pre-tools/modules/code-edit-rules.sh +78 -0
  211. package/plugins/toolu/hooks/pre-tools/modules/commit-gate.sh +70 -0
  212. package/plugins/toolu/hooks/pre-tools/modules/docs-sync.sh +137 -0
  213. package/plugins/toolu/hooks/pre-tools/modules/mcp-blocker.sh +151 -0
  214. package/plugins/toolu/hooks/pre-tools/modules/plan-ledger.sh +201 -0
  215. package/plugins/toolu/hooks/pre-tools/modules/protected-files.sh +177 -0
  216. package/plugins/toolu/hooks/pre-tools/modules/push-review.sh +273 -0
  217. package/plugins/toolu/hooks/pre-tools/modules/quality-gate.sh +87 -0
  218. package/plugins/toolu/hooks/session-start.sh +379 -0
  219. package/plugins/toolu/hooks/user-prompt-submit.sh +197 -0
  220. package/plugins/toolu/scripts/context-budget.sh +111 -0
  221. package/plugins/toolu/scripts/debug-log.sh +98 -0
  222. package/plugins/toolu/scripts/debug-stack.sh +108 -0
  223. package/plugins/toolu/scripts/debug-testfail.sh +97 -0
  224. package/plugins/toolu/settings/.gitkeep +0 -0
  225. package/plugins/toolu/settings/README.md +127 -0
  226. package/plugins/toolu/settings/bash-allowlist.txt +12 -0
  227. package/plugins/toolu/settings/bash-denylist.txt +25 -0
  228. package/plugins/toolu/settings/code-edit-rules.json +67 -0
  229. package/plugins/toolu/settings/commit-prefixes.txt +12 -0
  230. package/plugins/toolu/settings/mcp-blocklist.txt +8 -0
  231. package/plugins/toolu/settings/permissions.fragment.json +36 -0
  232. package/plugins/toolu/settings/protected-files.txt +30 -0
  233. package/plugins/toolu/settings/rust-unsafe-exemptions.txt +5 -0
  234. package/plugins/toolu/settings/toolu.config.example.json +130 -0
  235. package/plugins/toolu/skills/.gitkeep +0 -0
  236. package/plugins/toolu/skills/brainstorm/SKILL.md +57 -0
  237. package/plugins/toolu/skills/brainstorm/references/design-questions.md +36 -0
  238. package/plugins/toolu/skills/commit/SKILL.md +11 -0
  239. package/plugins/toolu/skills/debug/SKILL.md +54 -0
  240. package/plugins/toolu/skills/debug/evals/README.md +17 -0
  241. package/plugins/toolu/skills/debug/evals/cases.json +24 -0
  242. package/plugins/toolu/skills/debug/evals/results.json +34 -0
  243. package/plugins/toolu/skills/deep-research/SKILL.md +51 -0
  244. package/plugins/toolu/skills/execution/SKILL.md +77 -0
  245. package/plugins/toolu/skills/orchestrator/SKILL.md +145 -0
  246. package/plugins/toolu/skills/orchestrator/references/delegation-cost.md +104 -0
  247. package/plugins/toolu/skills/orchestrator/references/model-routing.md +112 -0
  248. package/plugins/toolu/skills/plan/SKILL.md +56 -0
  249. package/plugins/toolu/skills/plan/references/ledger.md +18 -0
  250. package/plugins/toolu/skills/plan-review/SKILL.md +48 -0
  251. package/plugins/toolu/skills/review-and-commit/SKILL.md +10 -0
  252. package/plugins/toolu/skills/setup/SKILL.md +24 -0
  253. package/plugins/toolu/skills/setup/scripts/setup.sh +206 -0
  254. package/plugins/toolu/skills/spec/SKILL.md +67 -0
  255. package/plugins/toolu/skills/spec-review/SKILL.md +50 -0
  256. package/plugins/toolu/skills/test/SKILL.md +49 -0
  257. package/plugins/toolu/workflows/commit.md +21 -0
  258. package/plugins/toolu/workflows/host-mapping.md +22 -0
  259. package/plugins/toolu/workflows/review-and-commit.md +54 -0
  260. package/plugins/toolu/workflows/semantic-judgments.md +35 -0
  261. package/plugins/toolu-review/.claude-plugin/plugin.json +18 -0
  262. package/plugins/toolu-review/.codex-plugin/plugin.json +7 -0
  263. package/plugins/toolu-review/README.md +17 -0
  264. package/plugins/toolu-review/hooks/hooks.json +15 -0
  265. package/plugins/toolu-review/hooks/session-start.sh +34 -0
  266. package/plugins/toolu-review/skills/review/SKILL.md +90 -0
  267. package/plugins/toolu-review/skills/review/scripts/write-state.sh +189 -0
  268. package/plugins/ts-quality/.claude-plugin/plugin.json +24 -0
  269. package/plugins/ts-quality/.codex-plugin/plugin.json +6 -0
  270. package/plugins/ts-quality/README.md +24 -0
  271. package/plugins/ts-quality/hooks/check-toolu.sh +20 -0
  272. package/plugins/ts-quality/hooks/concerns/00-preamble.sh +123 -0
  273. package/plugins/ts-quality/hooks/concerns/10-imports.sh +33 -0
  274. package/plugins/ts-quality/hooks/concerns/15-type-as.sh +9 -0
  275. package/plugins/ts-quality/hooks/concerns/20-tests.sh +26 -0
  276. package/plugins/ts-quality/hooks/concerns/25-size-file.sh +40 -0
  277. package/plugins/ts-quality/hooks/concerns/30-size-fn.sh +53 -0
  278. package/plugins/ts-quality/hooks/concerns/35-react-hooks.sh +7 -0
  279. package/plugins/ts-quality/hooks/concerns/40-factory.sh +5 -0
  280. package/plugins/ts-quality/hooks/concerns/45-typeguard.sh +6 -0
  281. package/plugins/ts-quality/hooks/concerns/50-type-dup.sh +16 -0
  282. package/plugins/ts-quality/hooks/concerns/55-naming.sh +11 -0
  283. package/plugins/ts-quality/hooks/concerns/60-console.sh +6 -0
  284. package/plugins/ts-quality/hooks/concerns/65-suppression.sh +12 -0
  285. package/plugins/ts-quality/hooks/concerns/70-ui-confirm.sh +8 -0
  286. package/plugins/ts-quality/hooks/concerns/72-ui-radix.sh +12 -0
  287. package/plugins/ts-quality/hooks/concerns/74-react-props.sh +6 -0
  288. package/plugins/ts-quality/hooks/concerns/76-toast.sh +10 -0
  289. package/plugins/ts-quality/hooks/concerns/78-error-ast.sh +242 -0
  290. package/plugins/ts-quality/hooks/concerns/80-throw-literal.sh +23 -0
  291. package/plugins/ts-quality/hooks/concerns/85-no-mocks.sh +109 -0
  292. package/plugins/ts-quality/hooks/concerns/90-duplication.sh +30 -0
  293. package/plugins/ts-quality/hooks/concerns/92-docs.sh +36 -0
  294. package/plugins/ts-quality/hooks/concerns/94-handler.sh +15 -0
  295. package/plugins/ts-quality/hooks/concerns/99-finalize.sh +46 -0
  296. package/plugins/ts-quality/hooks/hooks.json +19 -0
  297. package/plugins/ts-quality/hooks/register.sh +65 -0
  298. package/src/adapter/__tests__/evaluate.test.ts +82 -0
  299. package/src/adapter/__tests__/permission-map.test.ts +91 -0
  300. package/src/adapter/evaluate.ts +54 -0
  301. package/src/adapter/permission-map.ts +177 -0
  302. package/src/bootstrap/__tests__/bootstrap.test.ts +148 -0
  303. package/src/bootstrap/entrypoint.ts +18 -0
  304. package/src/bootstrap/index.ts +5 -0
  305. package/src/bootstrap/readiness.ts +59 -0
  306. package/src/bootstrap/result.ts +21 -0
  307. package/src/bootstrap/runtime.ts +99 -0
  308. package/src/bootstrap/test-helpers.ts +25 -0
  309. package/src/host/__tests__/host.test.ts +37 -0
  310. package/src/host/detect.ts +46 -0
  311. package/src/host/index.ts +10 -0
  312. package/src/host/roots.ts +59 -0
  313. package/src/host/types.ts +14 -0
  314. package/src/inventory/__tests__/inventory.test.ts +69 -0
  315. package/src/inventory/index.ts +9 -0
  316. package/src/inventory/manifest.ts +46 -0
  317. package/src/inventory/scan.ts +66 -0
  318. package/src/inventory/selection.ts +92 -0
  319. package/src/inventory/types.ts +22 -0
  320. package/src/lifecycle/__tests__/lifecycle.test.ts +7 -0
  321. package/src/lifecycle/index.ts +2 -0
  322. package/src/lifecycle/table.ts +42 -0
  323. package/src/plugin/__tests__/plugin-stub.test.ts +6 -0
  324. package/src/plugin/plugin-stub.ts +7 -0
  325. package/src/plugin/toolu.ts +142 -0
  326. package/src/preflight/__tests__/preflight.test.ts +20 -0
  327. package/src/preflight/check.ts +75 -0
  328. package/src/preflight/index.ts +2 -0
  329. package/src/select/__tests__/select.test.ts +52 -0
  330. package/src/select/index.ts +2 -0
  331. package/src/select/resolve.ts +87 -0
@@ -0,0 +1,36 @@
1
+ # --- Output ---
2
+
3
+ if [[ -n "$MESSAGES" ]]; then
4
+ # Record this file's violation in the gate status file (entry keyed by file
5
+ # path — does not clobber failures recorded for other files or hooks).
6
+ GATE_DIR="$(toolu_project_state_root "$PROJECT_ROOT")"
7
+ GATE_FILE="$GATE_DIR/quality-gate-status.json"
8
+ mkdir -p "$GATE_DIR"
9
+ gate_record_failure "$GATE_FILE" "$FILE_PATH" "rust-quality-hook" \
10
+ "Post-edit Rust quality violation(s) detected" "$MESSAGES"
11
+
12
+ jq -n --arg ctx "$MESSAGES" '{
13
+ "hookSpecificOutput": {
14
+ "hookEventName": "PostToolUse",
15
+ "additionalContext": ("QUALITY VIOLATION — fix before proceeding:\n" + $ctx)
16
+ }
17
+ }'
18
+ else
19
+ # Clear this file's entry now that it passes (only if this hook set it).
20
+ # Other files' failures stay recorded; the gate only flips to passing when
21
+ # no entry remains.
22
+ GATE_FILE="$(toolu_project_state_root "$PROJECT_ROOT")/quality-gate-status.json"
23
+ gate_clear_file "$GATE_FILE" "$FILE_PATH" "rust-quality-hook"
24
+
25
+ # Docs advisory (non-blocking — no gate write).
26
+ if [[ -n "$DOC_ADVISORY" ]]; then
27
+ jq -n --arg ctx "$DOC_ADVISORY" '{
28
+ "hookSpecificOutput": {
29
+ "hookEventName": "PostToolUse",
30
+ "additionalContext": $ctx
31
+ }
32
+ }'
33
+ fi
34
+ fi
35
+
36
+ exit 0
@@ -0,0 +1,19 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "startup|resume|clear|compact",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/register.sh"
10
+ },
11
+ {
12
+ "type": "command",
13
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/check-toolu.sh"
14
+ }
15
+ ]
16
+ }
17
+ ]
18
+ }
19
+ }
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env bash
2
+ # SessionStart registry sync for the rust-quality plugin.
3
+ #
4
+ # Assembles hooks/concerns/[0-9][0-9]-*.sh (ordered preamble → concern partials
5
+ # → finalize) into ONE runtime module in the toolu registry
6
+ # (${TOOLU_CONFIG_DIR:-${CLAUDE_CONFIG_DIR:-$HOME/.claude}}/toolu/post-tools.d/) under the
7
+ # namespaced filename rust-quality@toolu__rust-quality.sh. The fragments are
8
+ # partials of a single script; concatenating them in numeric order rebuilds the
9
+ # original monolith so one process does one gate write (preserving
10
+ # byte-identical behavior). Prunes any stale entry bearing OUR prefix, and
11
+ # clears our own crashed tmp residue. Other plugins' entries are never touched.
12
+ #
13
+ # Silent on success (SessionStart stdout becomes context); errors are
14
+ # non-fatal — a failed sync means the registry copy is stale, not broken.
15
+
16
+ SPEC="rust-quality@toolu"
17
+ OUT="rust-quality.sh"
18
+ SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
19
+ SRC_DIR="$SELF_DIR/concerns"
20
+ if [ -n "${TOOLU_CONFIG_DIR:-}" ]; then
21
+ CONFIG_ROOT="$TOOLU_CONFIG_DIR"
22
+ elif [ "${TOOLU_HOST_OVERRIDE:-}" = codex ] || { [ -z "${TOOLU_HOST_OVERRIDE:-}" ] && [ -n "${PLUGIN_ROOT:-}" ]; }; then
23
+ CONFIG_ROOT="${CODEX_HOME:-$HOME/.codex}"
24
+ else
25
+ CONFIG_ROOT="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
26
+ fi
27
+ REG_DIR="$CONFIG_ROOT/toolu/post-tools.d"
28
+
29
+ # Consume stdin so Claude Code's hook IPC never stalls.
30
+ cat > /dev/null 2>&1 || true
31
+
32
+ [ -d "$SRC_DIR" ] || exit 0
33
+ mkdir -p "$REG_DIR" 2>/dev/null || exit 0
34
+
35
+ # Clear OUR orphaned atomic-write residue from prior crashed runs. Age-gated
36
+ # so a concurrent SessionStart's in-flight tmp (seconds old) is never clobbered.
37
+ find "$REG_DIR" -maxdepth 1 -name "${SPEC}__*.sh.tmp.*" -mmin +1 -delete 2>/dev/null
38
+
39
+ # Assemble: concatenate the numeric-prefixed fragments in lexical order into one
40
+ # module. A newline guard between fragments keeps a fragment that lacks a
41
+ # trailing newline from running into the next. __tests__/ and any non-prefixed
42
+ # .sh are skipped by the glob.
43
+ dst="$REG_DIR/${SPEC}__${OUT}"
44
+ tmp="${dst}.tmp.$$"
45
+ : > "$tmp"
46
+ for src in "$SRC_DIR"/[0-9][0-9]-*.sh; do
47
+ [ -f "$src" ] || continue
48
+ cat "$src" >> "$tmp" 2>/dev/null || { rm -f "$tmp"; exit 0; }
49
+ printf '\n' >> "$tmp" 2>/dev/null || { rm -f "$tmp"; exit 0; }
50
+ done
51
+ if [ -s "$tmp" ] && { [ ! -f "$dst" ] || ! cmp -s "$tmp" "$dst"; }; then
52
+ mv "$tmp" "$dst" 2>/dev/null || rm -f "$tmp"
53
+ else
54
+ rm -f "$tmp"
55
+ fi
56
+
57
+ # Prune: remove any entry bearing OUR prefix that is not the current assembled
58
+ # module (e.g. per-concern files left by an older version). Never glob outside
59
+ # our own spec prefix.
60
+ for old in "$REG_DIR/${SPEC}__"*.sh; do
61
+ [ -f "$old" ] || continue
62
+ [ "$(basename "$old")" = "${SPEC}__${OUT}" ] || rm -f "$old"
63
+ done
64
+
65
+ exit 0
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "statusline",
3
+ "version": "6.8.0",
4
+ "description": "Host-native project status: a persistent Claude Code statusline plus an explicit Codex status skill for repository, gate, git, comemory, and Jev readiness. Standalone, no dependencies.",
5
+ "author": {
6
+ "name": "Falconiere Barbosa",
7
+ "email": "hello@falconiere.io"
8
+ },
9
+ "homepage": "https://github.com/falconiere/toolu",
10
+ "repository": "https://github.com/falconiere/toolu.git",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "claude-code",
14
+ "statusline",
15
+ "quality-gate",
16
+ "comemory",
17
+ "jev"
18
+ ]
19
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "statusline",
3
+ "version": "6.8.0",
4
+ "description": "Host-native project status: a persistent Claude Code statusline plus an explicit Codex status skill for repository, gate, git, comemory, and Jev readiness. Standalone, no dependencies.",
5
+ "skills": "./skills/",
6
+ "hooks": "./hooks/hooks.json"
7
+ }
@@ -0,0 +1,108 @@
1
+ # statusline
2
+
3
+ Host-native project status. Claude Code gets an optional persistent one-line
4
+ statusline assembled defensively from the JSON Claude sends on stdin:
5
+
6
+ ```
7
+ model | effort:high | ctx:45k/200k (22%) | example.com | ✗ gate:failing | my-folder | main ↑2↓1 [+2 ~1 ?3] | [COMEMORY:42] | [JEV:READY]
8
+ ```
9
+
10
+ | Segment | Source | Shows when |
11
+ |---------|--------|------------|
12
+ | model | `.model.display_name` | always |
13
+ | effort | `.effort.level` | the model reports an effort level |
14
+ | ctx | `.context_window.*` | always |
15
+ | `example.com` | `.oauthAccount.emailAddress` in `~/.claude.json` (or `$CLAUDE_CONFIG_DIR/.claude.json`) | logged in via Claude OAuth — shows only the email domain, not the full address |
16
+ | `✗ gate:failing` | host-native `.claude/tmp/quality-gate-status.json` at the git root | a **gate writer** (e.g. the `rust-quality` / `ts-quality` / `python-quality` / `toolu` plugins) marks the gate failing |
17
+ | folder + branch + status | git, from the workspace dir | inside a git repo — `↑N↓M` shows ahead/behind of the tracked remote, `[+N ~N ?N]` shows staged/unstaged/untracked file counts (both omitted when clean and up-to-date) |
18
+ | `[COMEMORY:N]` | `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/comemory-status/<repo>.json` | the **comemory** plugin published a memory count this session |
19
+ | `[JEV:READY]` / `[JEV:UNAVAILABLE: reason]` | `<config-dir>/jev/jev.sh`, curl, and `TYPESAFE_API_KEY` in the environment | Jev published a wrapper; green when locally ready, yellow with the reason when unavailable |
20
+
21
+ Codex exposes `$statusline:status` instead of a persistent bar. It reports the
22
+ repository, branch/ahead/behind state, working-tree counts, quality gate from
23
+ `<repo>/.codex/tmp/quality-gate-status.json`, comemory count, and Jev readiness
24
+ (`Jev: ready` or `Jev: unavailable — reason`). It deliberately
25
+ omits account, model, effort, and context-window fields that Codex does not make
26
+ available to the skill.
27
+
28
+ Jev readiness uses the active host's config directory (`CLAUDE_CONFIG_DIR` or
29
+ `CODEX_HOME`, with `TOOLU_CONFIG_DIR` taking priority). It checks for an executable
30
+ wrapper, curl, and a nonempty API key without line breaks. It never prints the
31
+ key, reads `.env`, executes the wrapper, or makes an API call. **Ready means local
32
+ prerequisites are present**; it does not verify authentication or service health.
33
+ An unpublished wrapper hides the segment; a broken published wrapper shows
34
+ `missing executable wrapper`. Other reasons include `missing curl`,
35
+ `missing TYPESAFE_API_KEY`, and `invalid TYPESAFE_API_KEY`. Multiple reasons are
36
+ separated by semicolons. As with the rest of the status display, jq is required.
37
+
38
+ The account, gate, comemory, and git status segments degrade gracefully — if the file
39
+ they read is absent, the segment simply doesn't render. So statusline is
40
+ **standalone**: it declares no plugin dependencies. Those segments just light up
41
+ automatically when the relevant plugins are also installed (or, for the account
42
+ segment, when you're logged in via Claude OAuth rather than an API key).
43
+
44
+ ## Codex install
45
+
46
+ ```bash
47
+ codex plugin add statusline@toolu
48
+ ```
49
+
50
+ Run `$statusline:status` whenever you want a current report. No setup or
51
+ persistent renderer is required.
52
+
53
+ ## Claude Code install & wire up
54
+
55
+ Claude Code does not let a plugin declare `statusLine` in its manifest, so the
56
+ SessionStart hook symlinks the script to a stable, version-independent path:
57
+
58
+ ```
59
+ ~/.claude/statusline/statusline.sh (→ the installed plugin's statusline.sh)
60
+ ```
61
+
62
+ 1. Install the plugin:
63
+
64
+ ```
65
+ /plugin install statusline@toolu
66
+ ```
67
+
68
+ 2. Wire it once. Easiest — run the bundled command:
69
+
70
+ ```
71
+ /statusline:setup
72
+ ```
73
+
74
+ It adds the `statusLine` key below to your `settings.json` idempotently:
75
+ it backs the file up first, never clobbers an existing custom statusLine
76
+ (re-run `/statusline:setup --force` if you do want to replace one), and is a
77
+ no-op once wired. Restart the session afterwards for the bar to appear.
78
+
79
+ Or wire it by hand:
80
+
81
+ ```json
82
+ {
83
+ "statusLine": {
84
+ "type": "command",
85
+ "command": "bash ~/.claude/statusline/statusline.sh"
86
+ }
87
+ }
88
+ ```
89
+
90
+ (Use `$CLAUDE_CONFIG_DIR/statusline/statusline.sh` if you run with a custom
91
+ config dir.) The symlink is refreshed every session, so plugin updates are
92
+ picked up automatically with no settings change. The hook never clobbers a
93
+ real file you place at that path — it only owns its own symlink.
94
+
95
+ ## Migrating from toolu ≤ 1.5.0
96
+
97
+ The statusline used to ship inside the `toolu` plugin and auto-symlinked to
98
+ `~/.claude/toolu/statusline.sh`. It now lives here. To keep your statusline:
99
+
100
+ - `/plugin install statusline@toolu`, and
101
+ - re-point `settings.json` from `~/.claude/toolu/statusline.sh` to
102
+ `~/.claude/statusline/statusline.sh` — `/statusline:setup --force` does this
103
+ for you (the old path is a custom value to it, so plain `/statusline:setup`
104
+ would refuse).
105
+
106
+ Toolu no longer creates the old symlink and sweeps away the dangling one it
107
+ used to own, so an un-migrated `settings.json` will fail loudly (missing file)
108
+ rather than silently pointing into a cleaned plugin cache.
@@ -0,0 +1,30 @@
1
+ # Set up the statusline
2
+
3
+ Wire the statusline into the user's Claude Code `settings.json` so the status
4
+ bar renders. The plugin's SessionStart hook already maintains the script
5
+ symlink, but Claude Code reads `statusLine` only from `settings.json` and a
6
+ plugin cannot declare it — this command adds that one key, safely and
7
+ idempotently. It never clobbers an existing custom statusLine and backs the
8
+ file up before any write.
9
+
10
+ ## Steps
11
+
12
+ 1. Run the setup script. Pass `--force` through **only** if the user explicitly
13
+ asked to replace an existing custom statusLine:
14
+
15
+ ```bash
16
+ bash "${CLAUDE_PLUGIN_ROOT}/scripts/setup.sh" $ARGUMENTS
17
+ ```
18
+
19
+ 2. Read the first word of the output (the STATUS token) and report:
20
+ - **WIRED** / **CREATED** — success. Tell the user to **restart the session**
21
+ (or `/clear`) for the status bar to appear; `statusLine` loads at session
22
+ start.
23
+ - **ALREADY** — already wired; nothing to do.
24
+ - **REFUSED** — a different statusLine is already set. Show the current value
25
+ the script printed, and tell the user to re-run `/statusline:setup --force`
26
+ to replace it (or wire it by hand).
27
+ - **ERROR** — relay the message; do not retry blindly.
28
+
29
+ Do not hand-edit `settings.json` — the script round-trips the JSON and keeps a
30
+ `settings.json.bak` backup.
@@ -0,0 +1,15 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "startup|resume|clear|compact",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh"
10
+ }
11
+ ]
12
+ }
13
+ ]
14
+ }
15
+ }
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env bash
2
+ # SessionStart hook for the statusline plugin.
3
+ #
4
+ # Claude Code does not let a plugin declare `statusLine` in its manifest, so we
5
+ # symlink the script to a stable, version-independent path that settings.json
6
+ # can point at without hardcoding the version-specific plugin cache dir:
7
+ # ${CLAUDE_CONFIG_DIR:-$HOME/.claude}/statusline/statusline.sh
8
+ # The symlink is refreshed every session, so plugin updates are picked up with
9
+ # no settings change. statusline is self-contained — this hook sources no
10
+ # toolu libs; the registry root is just the config dir + /statusline.
11
+ #
12
+ # Silent on success; every step is non-fatal (a failed symlink means the
13
+ # statusline is stale, not that the session breaks).
14
+
15
+ # Consume stdin so Claude Code's hook IPC never stalls.
16
+ cat > /dev/null 2>&1 || true
17
+
18
+ # Resolve the plugin dir from this hook's location: hooks/.. = plugin root.
19
+ # If the cd fails, skip rather than symlinking a bogus "/statusline.sh" path.
20
+ plugin_dir="$(cd "$(dirname "$0")/.." 2>/dev/null && pwd)"
21
+ statusline_src="${plugin_dir:+$plugin_dir/statusline.sh}"
22
+ [ -n "$statusline_src" ] && [ -f "$statusline_src" ] || exit 0
23
+
24
+ if [ -n "${TOOLU_CONFIG_DIR:-}" ]; then
25
+ config_root="$TOOLU_CONFIG_DIR"
26
+ elif [ "${TOOLU_HOST_OVERRIDE:-}" = codex ] || { [ -z "${TOOLU_HOST_OVERRIDE:-}" ] && [ -n "${PLUGIN_ROOT:-}" ]; }; then
27
+ config_root="${CODEX_HOME:-$HOME/.codex}"
28
+ else
29
+ config_root="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
30
+ fi
31
+ reg_root="$config_root/statusline"
32
+ # Non-fatal hook: a failure here (e.g. a non-directory file occupies $reg_root)
33
+ # must not break the session, but leave one stderr breadcrumb so the otherwise-
34
+ # silent no-op is debuggable.
35
+ mkdir -p "$reg_root" 2>/dev/null || { echo "statusline: cannot create $reg_root — statusline not wired" >&2; exit 0; }
36
+
37
+ # Own the path only when it is already our symlink or absent — never clobber a
38
+ # real file a user may have placed at $reg_root/statusline.sh. (-L catches a
39
+ # broken/relinked symlink that -e would report as missing.)
40
+ dst="$reg_root/statusline.sh"
41
+ if [ -L "$dst" ] || [ ! -e "$dst" ]; then
42
+ ln -sf "$statusline_src" "$dst" 2>/dev/null || true
43
+ fi
44
+
45
+ exit 0
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env bash
2
+ # Collect host-neutral project status as JSON for renderers and explicit skills.
3
+ set -euo pipefail
4
+
5
+ command -v jq >/dev/null 2>&1 || {
6
+ printf '%s\n' 'collect-status: jq is required' >&2
7
+ exit 1
8
+ }
9
+
10
+ # Omitted cwd uses the current directory; an explicit empty cwd is profile-only.
11
+ cwd="${1-$PWD}"
12
+ if [ "${TOOLU_HOST_OVERRIDE:-}" = codex ] || {
13
+ [ -z "${TOOLU_HOST_OVERRIDE:-}" ] && [ -n "${PLUGIN_ROOT:-}" ]
14
+ }; then
15
+ host=codex
16
+ config_root="${TOOLU_CONFIG_DIR:-${CODEX_HOME:-$HOME/.codex}}"
17
+ project_state=.codex
18
+ else
19
+ host=claude
20
+ config_root="${TOOLU_CONFIG_DIR:-${CLAUDE_CONFIG_DIR:-$HOME/.claude}}"
21
+ project_state=.claude
22
+ fi
23
+
24
+ repo_root=""
25
+ branch=""
26
+ folder=""
27
+ ahead=0
28
+ behind=0
29
+ staged=0
30
+ unstaged=0
31
+ untracked=0
32
+ if [ -d "$cwd" ]; then
33
+ folder=$(basename "$cwd")
34
+ repo_root=$(git -C "$cwd" --no-optional-locks rev-parse --show-toplevel 2>/dev/null || true)
35
+ fi
36
+
37
+ if [ -n "$repo_root" ]; then
38
+ branch=$(git -C "$cwd" --no-optional-locks symbolic-ref --short HEAD 2>/dev/null || true)
39
+ first=1
40
+ while IFS= read -r line; do
41
+ if [ "$first" -eq 1 ]; then
42
+ first=0
43
+ case "$line" in
44
+ "## "*)
45
+ rest="${line:3}"
46
+ case "$rest" in
47
+ *ahead*)
48
+ value="${rest#*ahead }"
49
+ ahead="${value%%,*}"
50
+ ahead="${ahead%% *}"
51
+ ahead="${ahead%]}"
52
+ ;;
53
+ esac
54
+ case "$rest" in
55
+ *behind*)
56
+ value="${rest#*behind }"
57
+ behind="${value%%,*}"
58
+ behind="${behind%% *}"
59
+ behind="${behind%]}"
60
+ ;;
61
+ esac
62
+ ;;
63
+ esac
64
+ continue
65
+ fi
66
+ [ "${#line}" -ge 2 ] || continue
67
+ case "${line:0:2}" in
68
+ "??") untracked=$((untracked + 1)) ;;
69
+ "!!") ;;
70
+ *)
71
+ [ "${line:0:1}" = " " ] || staged=$((staged + 1))
72
+ [ "${line:1:1}" = " " ] || unstaged=$((unstaged + 1))
73
+ ;;
74
+ esac
75
+ done < <(git -C "$cwd" --no-optional-locks status --porcelain --branch 2>/dev/null || true)
76
+ fi
77
+
78
+ gate_status=""
79
+ gate_reason=""
80
+ gate_file="${repo_root:-$cwd}/$project_state/tmp/quality-gate-status.json"
81
+ if [ -n "$cwd" ] && [ -f "$gate_file" ]; then
82
+ gate_status=$(jq -r '.status | strings // empty' "$gate_file" 2>/dev/null || true)
83
+ gate_reason=$(jq -r '.reason | strings // empty' "$gate_file" 2>/dev/null || true)
84
+ fi
85
+
86
+ comemory_count=""
87
+ if [ -n "$repo_root" ]; then
88
+ common_dir=$(git -C "$cwd" --no-optional-locks rev-parse --git-common-dir 2>/dev/null || true)
89
+ if [ -n "$common_dir" ]; then
90
+ case "$common_dir" in
91
+ /*) ;;
92
+ *) common_dir=$(cd "$cwd" 2>/dev/null && cd "$common_dir" 2>/dev/null && pwd) || common_dir="" ;;
93
+ esac
94
+ if [ -n "$common_dir" ]; then
95
+ marker="$config_root/comemory-status/$(basename "$(dirname "$common_dir")").json"
96
+ if [ -f "$marker" ]; then
97
+ comemory_count=$(jq -r '.count | numbers // empty' "$marker" 2>/dev/null || true)
98
+ fi
99
+ fi
100
+ fi
101
+ fi
102
+
103
+ # Readiness is local configuration, not a service health check. Never execute
104
+ # the wrapper or send a request on the statusline's per-prompt hot path.
105
+ jev_status=""
106
+ jev_reason=""
107
+ jev_wrapper="$config_root/jev/jev.sh"
108
+ if [ -e "$jev_wrapper" ] || [ -L "$jev_wrapper" ]; then
109
+ if [ ! -f "$jev_wrapper" ] || [ ! -x "$jev_wrapper" ]; then
110
+ jev_reason="missing executable wrapper; "
111
+ fi
112
+ command -v curl >/dev/null 2>&1 || jev_reason="${jev_reason}missing curl; "
113
+ if [ -z "${TYPESAFE_API_KEY:-}" ]; then
114
+ jev_reason="${jev_reason}missing TYPESAFE_API_KEY; "
115
+ elif [[ "$TYPESAFE_API_KEY" == *$'\r'* || "$TYPESAFE_API_KEY" == *$'\n'* ]]; then
116
+ jev_reason="${jev_reason}invalid TYPESAFE_API_KEY; "
117
+ fi
118
+ jev_reason="${jev_reason%; }"
119
+ if [ -n "$jev_reason" ]; then
120
+ jev_status=unavailable
121
+ else
122
+ jev_status=ready
123
+ fi
124
+ fi
125
+
126
+ jq -cn \
127
+ --arg host "$host" \
128
+ --arg cwd "$cwd" \
129
+ --arg repo_root "$repo_root" \
130
+ --arg folder "$folder" \
131
+ --arg branch "$branch" \
132
+ --arg gate_status "$gate_status" \
133
+ --arg gate_reason "$gate_reason" \
134
+ --arg comemory_count "$comemory_count" \
135
+ --arg jev_status "$jev_status" \
136
+ --arg jev_reason "$jev_reason" \
137
+ --argjson ahead "${ahead:-0}" \
138
+ --argjson behind "${behind:-0}" \
139
+ --argjson staged "$staged" \
140
+ --argjson unstaged "$unstaged" \
141
+ --argjson untracked "$untracked" \
142
+ '{host:$host,cwd:$cwd,repo_root:$repo_root,folder:$folder,branch:$branch,
143
+ ahead:$ahead,behind:$behind,
144
+ working_tree:{staged:$staged,unstaged:$unstaged,untracked:$untracked},
145
+ gate:{status:$gate_status,reason:$gate_reason},
146
+ jev:{status:$jev_status,reason:$jev_reason},
147
+ comemory_count:(if $comemory_count == "" then null else ($comemory_count | tonumber) end)}'
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env bash
2
+ # /statusline:setup — idempotently wire the statusline into settings.json.
3
+ #
4
+ # Claude Code reads `statusLine` only from settings.json, and a plugin may not
5
+ # declare it in its manifest. So installing the plugin maintains the symlink
6
+ # but cannot turn the status bar on by itself. This script adds the one key,
7
+ # safely:
8
+ # - never clobbers an existing custom statusLine (pass --force to override)
9
+ # - backs settings.json up to settings.json.bak before any write
10
+ # - idempotent: re-running once wired is a no-op
11
+ #
12
+ # Requires python3 for the JSON edit (a half-written settings.json would brick
13
+ # the session — worth the one dependency to round-trip it correctly). Prints a
14
+ # leading STATUS token (WIRED/CREATED/ALREADY/REFUSED/ERROR) the command reads.
15
+
16
+ set -euo pipefail
17
+
18
+ force=0
19
+ for arg in "$@"; do
20
+ case "$arg" in
21
+ --force | -f) force=1 ;;
22
+ *) ;;
23
+ esac
24
+ done
25
+
26
+ cfg_dir="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
27
+ settings="$cfg_dir/settings.json"
28
+
29
+ # Point at the stable symlink the SessionStart hook maintains. Mirror the path
30
+ # style the README documents: a literal ~ for the default dir (Claude Code runs
31
+ # the statusLine command through a shell, so ~ expands), else the explicit dir.
32
+ if [ -n "${CLAUDE_CONFIG_DIR:-}" ]; then
33
+ desired_cmd="bash \"$CLAUDE_CONFIG_DIR/statusline/statusline.sh\""
34
+ else
35
+ desired_cmd="bash ~/.claude/statusline/statusline.sh"
36
+ fi
37
+
38
+ if ! command -v python3 >/dev/null 2>&1; then
39
+ echo "ERROR python3 not found — add this to $settings manually:"
40
+ echo " \"statusLine\": { \"type\": \"command\", \"command\": \"$desired_cmd\" }"
41
+ exit 1
42
+ fi
43
+
44
+ python3 - "$settings" "$desired_cmd" "$force" <<'PY'
45
+ import json, os, shutil, sys
46
+
47
+ settings, desired_cmd, force = sys.argv[1], sys.argv[2], sys.argv[3] == "1"
48
+ marker = "statusline/statusline.sh"
49
+ block = {"type": "command", "command": desired_cmd}
50
+
51
+ created = False
52
+ if os.path.exists(settings) and os.path.getsize(settings) > 0:
53
+ try:
54
+ with open(settings) as f:
55
+ data = json.load(f)
56
+ except (ValueError, OSError) as e:
57
+ print(f"ERROR could not parse {settings}: {e} — not touching it")
58
+ sys.exit(1)
59
+ if not isinstance(data, dict):
60
+ print(f"ERROR {settings} is not a JSON object — not touching it")
61
+ sys.exit(1)
62
+ else:
63
+ data, created = {}, True
64
+
65
+ cur = data.get("statusLine")
66
+
67
+ # Already ours (matches whether it was wired via ~ or an explicit config dir).
68
+ if isinstance(cur, dict) and marker in str(cur.get("command", "")):
69
+ print("ALREADY statusLine already points at the statusline plugin — nothing to do.")
70
+ sys.exit(0)
71
+
72
+ # A different statusLine is present: refuse rather than overwrite, unless forced.
73
+ if cur is not None and not force:
74
+ print("REFUSED a different statusLine is already set in settings.json.")
75
+ print(" current: " + json.dumps(cur))
76
+ print(" re-run with --force to replace it, or set it manually:")
77
+ print(' "statusLine": ' + json.dumps(block))
78
+ sys.exit(3)
79
+
80
+ os.makedirs(os.path.dirname(settings) or ".", exist_ok=True)
81
+ if os.path.exists(settings):
82
+ shutil.copy2(settings, settings + ".bak")
83
+
84
+ data["statusLine"] = block
85
+ with open(settings, "w") as f:
86
+ json.dump(data, f, indent=2)
87
+ f.write("\n")
88
+
89
+ if created:
90
+ print(f"CREATED wrote {settings} with the statusLine wired. Restart the session to see it.")
91
+ else:
92
+ print(f"WIRED added statusLine to {settings} (backup: settings.json.bak). Restart the session to see it.")
93
+ PY
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+ # Print the explicit status report used by the Codex status skill.
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR=$(cd "${BASH_SOURCE[0]%/*}" && pwd)
6
+ status_json=$(TOOLU_HOST_OVERRIDE=codex \
7
+ bash "$SCRIPT_DIR/collect-status.sh" "${1:-$PWD}")
8
+
9
+ host=$(jq -r '.host' <<<"$status_json")
10
+ repo_root=$(jq -r '.repo_root' <<<"$status_json")
11
+ folder=$(jq -r '.folder' <<<"$status_json")
12
+ branch=$(jq -r '.branch' <<<"$status_json")
13
+ ahead=$(jq -r '.ahead' <<<"$status_json")
14
+ behind=$(jq -r '.behind' <<<"$status_json")
15
+ staged=$(jq -r '.working_tree.staged' <<<"$status_json")
16
+ unstaged=$(jq -r '.working_tree.unstaged' <<<"$status_json")
17
+ untracked=$(jq -r '.working_tree.untracked' <<<"$status_json")
18
+ gate_status=$(jq -r '.gate.status' <<<"$status_json")
19
+ gate_reason=$(jq -r '.gate.reason' <<<"$status_json")
20
+ comemory=$(jq -r '.comemory_count // empty' <<<"$status_json")
21
+ jev_status=$(jq -r '.jev.status // empty' <<<"$status_json")
22
+ jev_reason=$(jq -r '.jev.reason // empty' <<<"$status_json")
23
+
24
+ [ "$host" = codex ] && host_label=Codex || host_label='Claude Code'
25
+ printf 'Host: %s\n' "$host_label"
26
+ if [ -n "$repo_root" ]; then
27
+ printf 'Repository: %s\n' "$repo_root"
28
+ [ -n "$branch" ] && printf 'Branch: %s' "$branch" || printf 'Branch: detached HEAD'
29
+ [ "$ahead" -gt 0 ] && printf ' (ahead %s)' "$ahead"
30
+ [ "$behind" -gt 0 ] && printf ' (behind %s)' "$behind"
31
+ printf '\n'
32
+ if [ "$staged" -eq 0 ] && [ "$unstaged" -eq 0 ] && [ "$untracked" -eq 0 ]; then
33
+ printf 'Working tree: clean\n'
34
+ else
35
+ printf 'Working tree: staged %s, unstaged %s, untracked %s\n' \
36
+ "$staged" "$unstaged" "$untracked"
37
+ fi
38
+ else
39
+ printf 'Folder: %s (not a git repository)\n' "$folder"
40
+ fi
41
+
42
+ case "$gate_status" in
43
+ failing)
44
+ printf 'Quality gate: failing'
45
+ [ -z "$gate_reason" ] || printf ' — %s' "$gate_reason"
46
+ printf '\n'
47
+ ;;
48
+ passing) printf 'Quality gate: passing\n' ;;
49
+ *) printf 'Quality gate: no recorded state\n' ;;
50
+ esac
51
+ [ -z "$comemory" ] || printf 'Comemory: %s memories\n' "$comemory"
52
+ case "$jev_status" in
53
+ ready) printf 'Jev: ready\n' ;;
54
+ unavailable) printf 'Jev: unavailable — %s\n' "$jev_reason" ;;
55
+ esac
@@ -0,0 +1,13 @@
1
+ ---
2
+ name: status
3
+ description: Use when the user asks for current repository, branch, working-tree, quality-gate, comemory, or Jev readiness status in Codex.
4
+ ---
5
+
6
+ # Status
7
+
8
+ Run `TOOLU_HOST_OVERRIDE=codex bash ../../scripts/status.sh` resolved from this
9
+ skill directory and return its output verbatim. The explicit override is
10
+ required because lifecycle-only plugin variables are not exported to ordinary
11
+ skill shell calls. The report includes only fields available from local
12
+ repository and toolu state. Do not invent Claude-only account, model, effort,
13
+ or context-window values when the active host does not expose them.