@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.
- package/generated/GENERATED-NOTES.md +16 -0
- package/generated/agents/toolu--architect.md +52 -0
- package/generated/agents/toolu--deep-explore.md +65 -0
- package/generated/agents/toolu--implementer.md +50 -0
- package/generated/agents/toolu--quick-task.md +54 -0
- package/generated/agents/toolu--research-agent.md +101 -0
- package/generated/commands/toolu--commit.md +8 -0
- package/generated/commands/toolu--review-and-commit.md +8 -0
- package/generated/opencode.toolu.json +116 -0
- package/generated/skills/toolu--brainstorm/SKILL.md +57 -0
- package/generated/skills/toolu--brainstorm/references/design-questions.md +36 -0
- package/generated/skills/toolu--commit--skill/SKILL.md +11 -0
- package/generated/skills/toolu--debug/SKILL.md +54 -0
- package/generated/skills/toolu--deep-research/SKILL.md +51 -0
- package/generated/skills/toolu--execution/SKILL.md +77 -0
- package/generated/skills/toolu--orchestrator/SKILL.md +145 -0
- package/generated/skills/toolu--orchestrator/references/delegation-cost.md +104 -0
- package/generated/skills/toolu--orchestrator/references/model-routing.md +112 -0
- package/generated/skills/toolu--plan/SKILL.md +56 -0
- package/generated/skills/toolu--plan/references/ledger.md +18 -0
- package/generated/skills/toolu--plan-review/SKILL.md +48 -0
- package/generated/skills/toolu--review-and-commit--skill/SKILL.md +10 -0
- package/generated/skills/toolu--setup/SKILL.md +24 -0
- package/generated/skills/toolu--setup/scripts/setup.sh +206 -0
- package/generated/skills/toolu--spec/SKILL.md +67 -0
- package/generated/skills/toolu--spec-review/SKILL.md +50 -0
- package/generated/skills/toolu--test/SKILL.md +49 -0
- package/package.json +51 -0
- package/plugins/agent-browser/.claude-plugin/plugin.json +18 -0
- package/plugins/agent-browser/.codex-plugin/plugin.json +7 -0
- package/plugins/agent-browser/README.md +18 -0
- package/plugins/agent-browser/hooks/hooks.json +15 -0
- package/plugins/agent-browser/hooks/session-start.sh +42 -0
- package/plugins/agent-browser/skills/agent-browser/SKILL.md +77 -0
- package/plugins/agent-browser/skills/agent-browser/scripts/agent-browser.sh +80 -0
- package/plugins/ast-grep/.claude-plugin/plugin.json +18 -0
- package/plugins/ast-grep/.codex-plugin/plugin.json +7 -0
- package/plugins/ast-grep/README.md +21 -0
- package/plugins/ast-grep/hooks/hooks.json +15 -0
- package/plugins/ast-grep/hooks/post-tools.d/byte-savings.sh +67 -0
- package/plugins/ast-grep/hooks/pre-tools.d/search-nudge.sh +170 -0
- package/plugins/ast-grep/hooks/register.sh +68 -0
- package/plugins/ast-grep/scripts/byte-savings-report.sh +28 -0
- package/plugins/ast-grep/skills/ast-grep/SKILL.md +127 -0
- package/plugins/ast-grep/skills/ast-grep/references/ast-grep-advanced.md +44 -0
- package/plugins/ast-grep/skills/ast-grep/scripts/ast-grep.sh +103 -0
- package/plugins/context7/.claude-plugin/plugin.json +18 -0
- package/plugins/context7/.codex-plugin/plugin.json +7 -0
- package/plugins/context7/README.md +19 -0
- package/plugins/context7/hooks/hooks.json +15 -0
- package/plugins/context7/hooks/session-start.sh +42 -0
- package/plugins/context7/skills/context7/SKILL.md +64 -0
- package/plugins/context7/skills/context7/scripts/search.sh +151 -0
- package/plugins/exa-search/.claude-plugin/plugin.json +18 -0
- package/plugins/exa-search/.codex-plugin/plugin.json +7 -0
- package/plugins/exa-search/README.md +19 -0
- package/plugins/exa-search/hooks/hooks.json +15 -0
- package/plugins/exa-search/hooks/session-start.sh +34 -0
- package/plugins/exa-search/skills/exa-search/SKILL.md +91 -0
- package/plugins/exa-search/skills/exa-search/scripts/search.sh +221 -0
- package/plugins/jev/.claude-plugin/plugin.json +19 -0
- package/plugins/jev/.codex-plugin/plugin.json +7 -0
- package/plugins/jev/README.md +61 -0
- package/plugins/jev/hooks/hooks.json +25 -0
- package/plugins/jev/hooks/lib/common.sh +49 -0
- package/plugins/jev/hooks/session-start.sh +45 -0
- package/plugins/jev/hooks/user-prompt-submit.sh +41 -0
- package/plugins/jev/skills/jev/SKILL.md +81 -0
- package/plugins/jev/skills/jev/evals/README.md +98 -0
- package/plugins/jev/skills/jev/references/problem-solving.md +198 -0
- package/plugins/jev/skills/jev/scripts/jev.sh +405 -0
- package/plugins/jira/.claude-plugin/plugin.json +18 -0
- package/plugins/jira/.codex-plugin/plugin.json +7 -0
- package/plugins/jira/README.md +42 -0
- package/plugins/jira/hooks/hooks.json +15 -0
- package/plugins/jira/hooks/session-start.sh +34 -0
- package/plugins/jira/skills/jira/SKILL.md +123 -0
- package/plugins/jira/skills/jira/scripts/jira.sh +70 -0
- package/plugins/jira/skills/jira/scripts/lib/adf.sh +17 -0
- package/plugins/jira/skills/jira/scripts/lib/attachment.sh +94 -0
- package/plugins/jira/skills/jira/scripts/lib/board.sh +58 -0
- package/plugins/jira/skills/jira/scripts/lib/http.sh +184 -0
- package/plugins/jira/skills/jira/scripts/lib/issue.sh +159 -0
- package/plugins/jira/skills/jira/scripts/lib/paginate.sh +45 -0
- package/plugins/jira/skills/jira/scripts/lib/plan-parse.sh +70 -0
- package/plugins/jira/skills/jira/scripts/lib/plan-run.sh +115 -0
- package/plugins/jira/skills/jira/scripts/lib/plan-store.sh +168 -0
- package/plugins/jira/skills/jira/scripts/lib/plan.sh +108 -0
- package/plugins/jira/skills/jira/scripts/lib/project.sh +42 -0
- package/plugins/jira/skills/jira/scripts/lib/raw.sh +15 -0
- package/plugins/jira/skills/jira/scripts/lib/search.sh +41 -0
- package/plugins/jira/skills/jira/scripts/lib/sprint.sh +88 -0
- package/plugins/jira/skills/jira/scripts/lib/user.sh +45 -0
- package/plugins/jira/skills/jira/scripts/lib/worklog.sh +56 -0
- package/plugins/pr-babysit/.claude-plugin/plugin.json +25 -0
- package/plugins/pr-babysit/.codex-plugin/plugin.json +7 -0
- package/plugins/pr-babysit/README.md +38 -0
- package/plugins/pr-babysit/commands/babysit.md +13 -0
- package/plugins/pr-babysit/hooks/check-toolu.sh +20 -0
- package/plugins/pr-babysit/hooks/hooks.json +15 -0
- package/plugins/pr-babysit/scripts/babysit-tick.sh +133 -0
- package/plugins/pr-babysit/scripts/collect-pr.sh +224 -0
- package/plugins/pr-babysit/scripts/lib/common.sh +146 -0
- package/plugins/pr-babysit/scripts/lib/gh.sh +150 -0
- package/plugins/pr-babysit/scripts/lib/lock.sh +84 -0
- package/plugins/pr-babysit/scripts/lib/normalize.sh +98 -0
- package/plugins/pr-babysit/scripts/lib/state.sh +37 -0
- package/plugins/pr-babysit/scripts/parse-verdict.sh +171 -0
- package/plugins/pr-babysit/scripts/record.sh +69 -0
- package/plugins/pr-babysit/scripts/reduce-state.sh +245 -0
- package/plugins/pr-babysit/scripts/reply-thread.sh +90 -0
- package/plugins/pr-babysit/scripts/resolve-thread.sh +71 -0
- package/plugins/pr-babysit/skills/babysit/SKILL.md +31 -0
- package/plugins/pr-babysit/skills/babysit/references/helper.md +209 -0
- package/plugins/pr-babysit/workflows/babysit.md +722 -0
- package/plugins/python-quality/.claude-plugin/plugin.json +24 -0
- package/plugins/python-quality/.codex-plugin/plugin.json +6 -0
- package/plugins/python-quality/README.md +23 -0
- package/plugins/python-quality/hooks/check-toolu.sh +20 -0
- package/plugins/python-quality/hooks/concerns/00-preamble.sh +85 -0
- package/plugins/python-quality/hooks/concerns/10-size-file.sh +6 -0
- package/plugins/python-quality/hooks/concerns/20-tests.sh +37 -0
- package/plugins/python-quality/hooks/concerns/30-suppression.sh +33 -0
- package/plugins/python-quality/hooks/concerns/50-size-fn.sh +49 -0
- package/plugins/python-quality/hooks/concerns/70-no-mocks.sh +76 -0
- package/plugins/python-quality/hooks/concerns/90-docs.sh +52 -0
- package/plugins/python-quality/hooks/concerns/99-finalize.sh +36 -0
- package/plugins/python-quality/hooks/hooks.json +19 -0
- package/plugins/python-quality/hooks/register.sh +65 -0
- package/plugins/rust-quality/.claude-plugin/plugin.json +24 -0
- package/plugins/rust-quality/.codex-plugin/plugin.json +6 -0
- package/plugins/rust-quality/README.md +24 -0
- package/plugins/rust-quality/hooks/check-toolu.sh +20 -0
- package/plugins/rust-quality/hooks/concerns/00-preamble.sh +93 -0
- package/plugins/rust-quality/hooks/concerns/10-size-file.sh +10 -0
- package/plugins/rust-quality/hooks/concerns/20-tests.sh +84 -0
- package/plugins/rust-quality/hooks/concerns/30-suppression.sh +26 -0
- package/plugins/rust-quality/hooks/concerns/40-unsafe.sh +39 -0
- package/plugins/rust-quality/hooks/concerns/50-size-fn.sh +38 -0
- package/plugins/rust-quality/hooks/concerns/55-size-impl.sh +28 -0
- package/plugins/rust-quality/hooks/concerns/60-error-handling.sh +149 -0
- package/plugins/rust-quality/hooks/concerns/70-no-mocks.sh +139 -0
- package/plugins/rust-quality/hooks/concerns/90-docs.sh +32 -0
- package/plugins/rust-quality/hooks/concerns/99-finalize.sh +36 -0
- package/plugins/rust-quality/hooks/hooks.json +19 -0
- package/plugins/rust-quality/hooks/register.sh +65 -0
- package/plugins/statusline/.claude-plugin/plugin.json +19 -0
- package/plugins/statusline/.codex-plugin/plugin.json +7 -0
- package/plugins/statusline/README.md +108 -0
- package/plugins/statusline/commands/setup.md +30 -0
- package/plugins/statusline/hooks/hooks.json +15 -0
- package/plugins/statusline/hooks/session-start.sh +45 -0
- package/plugins/statusline/scripts/collect-status.sh +147 -0
- package/plugins/statusline/scripts/setup.sh +93 -0
- package/plugins/statusline/scripts/status.sh +55 -0
- package/plugins/statusline/skills/status/SKILL.md +13 -0
- package/plugins/statusline/statusline.sh +177 -0
- package/plugins/toolu/.claude-plugin/plugin.json +19 -0
- package/plugins/toolu/.codex-plugin/plugin.json +7 -0
- package/plugins/toolu/README.md +35 -0
- package/plugins/toolu/agents/.gitkeep +0 -0
- package/plugins/toolu/agents/architect.md +52 -0
- package/plugins/toolu/agents/deep-explore.md +65 -0
- package/plugins/toolu/agents/implementer.md +50 -0
- package/plugins/toolu/agents/quick-task.md +54 -0
- package/plugins/toolu/agents/research-agent.md +107 -0
- package/plugins/toolu/assets/agents/architect.toml +9 -0
- package/plugins/toolu/assets/agents/deep-explore.toml +9 -0
- package/plugins/toolu/assets/agents/implementer.toml +9 -0
- package/plugins/toolu/assets/agents/quick-task.toml +9 -0
- package/plugins/toolu/assets/agents/research-agent.toml +9 -0
- package/plugins/toolu/commands/.gitkeep +0 -0
- package/plugins/toolu/commands/commit.md +5 -0
- package/plugins/toolu/commands/review-and-commit.md +5 -0
- package/plugins/toolu/hooks/docs/gates.md +157 -0
- package/plugins/toolu/hooks/docs/model-routing.md +14 -0
- package/plugins/toolu/hooks/docs/post-compaction.md +3 -0
- package/plugins/toolu/hooks/docs/push-review.md +123 -0
- package/plugins/toolu/hooks/docs/session-start-python.md +3 -0
- package/plugins/toolu/hooks/docs/session-start-rust.md +4 -0
- package/plugins/toolu/hooks/docs/session-start-ts.md +3 -0
- package/plugins/toolu/hooks/docs/session-start.md +16 -0
- package/plugins/toolu/hooks/hooks.json +76 -0
- package/plugins/toolu/hooks/lib/config.sh +355 -0
- package/plugins/toolu/hooks/lib/detect.sh +929 -0
- package/plugins/toolu/hooks/lib/diff-sha.sh +32 -0
- package/plugins/toolu/hooks/lib/dispatch.sh +365 -0
- package/plugins/toolu/hooks/lib/docs-sync-config.sh +81 -0
- package/plugins/toolu/hooks/lib/edit-records.sh +157 -0
- package/plugins/toolu/hooks/lib/gate-file.sh +201 -0
- package/plugins/toolu/hooks/lib/gate-mode.sh +244 -0
- package/plugins/toolu/hooks/lib/host.sh +205 -0
- package/plugins/toolu/hooks/lib/permissions.sh +125 -0
- package/plugins/toolu/hooks/lib/plan-ledger-parse.sh +219 -0
- package/plugins/toolu/hooks/lib/plan-ledger-preflight.sh +137 -0
- package/plugins/toolu/hooks/lib/plan-ledger.sh +749 -0
- package/plugins/toolu/hooks/lib/push-waiver.sh +116 -0
- package/plugins/toolu/hooks/lib/quality-config.sh +184 -0
- package/plugins/toolu/hooks/lib/registry.sh +72 -0
- package/plugins/toolu/hooks/lib/state-sweeper.sh +194 -0
- package/plugins/toolu/hooks/lib/telemetry.sh +94 -0
- package/plugins/toolu/hooks/lib/verdict.sh +477 -0
- package/plugins/toolu/hooks/post-tools/mod.sh +42 -0
- package/plugins/toolu/hooks/post-tools/modules/gate-status.sh +140 -0
- package/plugins/toolu/hooks/post-tools/modules/push-waiver.sh +97 -0
- package/plugins/toolu/hooks/pre-compact.sh +18 -0
- package/plugins/toolu/hooks/pre-tools/agent-tier.sh +111 -0
- package/plugins/toolu/hooks/pre-tools/mod.sh +37 -0
- package/plugins/toolu/hooks/pre-tools/modules/bash-commands.sh +187 -0
- package/plugins/toolu/hooks/pre-tools/modules/code-edit-rules.sh +78 -0
- package/plugins/toolu/hooks/pre-tools/modules/commit-gate.sh +70 -0
- package/plugins/toolu/hooks/pre-tools/modules/docs-sync.sh +137 -0
- package/plugins/toolu/hooks/pre-tools/modules/mcp-blocker.sh +151 -0
- package/plugins/toolu/hooks/pre-tools/modules/plan-ledger.sh +201 -0
- package/plugins/toolu/hooks/pre-tools/modules/protected-files.sh +177 -0
- package/plugins/toolu/hooks/pre-tools/modules/push-review.sh +273 -0
- package/plugins/toolu/hooks/pre-tools/modules/quality-gate.sh +87 -0
- package/plugins/toolu/hooks/session-start.sh +379 -0
- package/plugins/toolu/hooks/user-prompt-submit.sh +197 -0
- package/plugins/toolu/scripts/context-budget.sh +111 -0
- package/plugins/toolu/scripts/debug-log.sh +98 -0
- package/plugins/toolu/scripts/debug-stack.sh +108 -0
- package/plugins/toolu/scripts/debug-testfail.sh +97 -0
- package/plugins/toolu/settings/.gitkeep +0 -0
- package/plugins/toolu/settings/README.md +127 -0
- package/plugins/toolu/settings/bash-allowlist.txt +12 -0
- package/plugins/toolu/settings/bash-denylist.txt +25 -0
- package/plugins/toolu/settings/code-edit-rules.json +67 -0
- package/plugins/toolu/settings/commit-prefixes.txt +12 -0
- package/plugins/toolu/settings/mcp-blocklist.txt +8 -0
- package/plugins/toolu/settings/permissions.fragment.json +36 -0
- package/plugins/toolu/settings/protected-files.txt +30 -0
- package/plugins/toolu/settings/rust-unsafe-exemptions.txt +5 -0
- package/plugins/toolu/settings/toolu.config.example.json +130 -0
- package/plugins/toolu/skills/.gitkeep +0 -0
- package/plugins/toolu/skills/brainstorm/SKILL.md +57 -0
- package/plugins/toolu/skills/brainstorm/references/design-questions.md +36 -0
- package/plugins/toolu/skills/commit/SKILL.md +11 -0
- package/plugins/toolu/skills/debug/SKILL.md +54 -0
- package/plugins/toolu/skills/debug/evals/README.md +17 -0
- package/plugins/toolu/skills/debug/evals/cases.json +24 -0
- package/plugins/toolu/skills/debug/evals/results.json +34 -0
- package/plugins/toolu/skills/deep-research/SKILL.md +51 -0
- package/plugins/toolu/skills/execution/SKILL.md +77 -0
- package/plugins/toolu/skills/orchestrator/SKILL.md +145 -0
- package/plugins/toolu/skills/orchestrator/references/delegation-cost.md +104 -0
- package/plugins/toolu/skills/orchestrator/references/model-routing.md +112 -0
- package/plugins/toolu/skills/plan/SKILL.md +56 -0
- package/plugins/toolu/skills/plan/references/ledger.md +18 -0
- package/plugins/toolu/skills/plan-review/SKILL.md +48 -0
- package/plugins/toolu/skills/review-and-commit/SKILL.md +10 -0
- package/plugins/toolu/skills/setup/SKILL.md +24 -0
- package/plugins/toolu/skills/setup/scripts/setup.sh +206 -0
- package/plugins/toolu/skills/spec/SKILL.md +67 -0
- package/plugins/toolu/skills/spec-review/SKILL.md +50 -0
- package/plugins/toolu/skills/test/SKILL.md +49 -0
- package/plugins/toolu/workflows/commit.md +21 -0
- package/plugins/toolu/workflows/host-mapping.md +22 -0
- package/plugins/toolu/workflows/review-and-commit.md +54 -0
- package/plugins/toolu/workflows/semantic-judgments.md +35 -0
- package/plugins/toolu-review/.claude-plugin/plugin.json +18 -0
- package/plugins/toolu-review/.codex-plugin/plugin.json +7 -0
- package/plugins/toolu-review/README.md +17 -0
- package/plugins/toolu-review/hooks/hooks.json +15 -0
- package/plugins/toolu-review/hooks/session-start.sh +34 -0
- package/plugins/toolu-review/skills/review/SKILL.md +90 -0
- package/plugins/toolu-review/skills/review/scripts/write-state.sh +189 -0
- package/plugins/ts-quality/.claude-plugin/plugin.json +24 -0
- package/plugins/ts-quality/.codex-plugin/plugin.json +6 -0
- package/plugins/ts-quality/README.md +24 -0
- package/plugins/ts-quality/hooks/check-toolu.sh +20 -0
- package/plugins/ts-quality/hooks/concerns/00-preamble.sh +123 -0
- package/plugins/ts-quality/hooks/concerns/10-imports.sh +33 -0
- package/plugins/ts-quality/hooks/concerns/15-type-as.sh +9 -0
- package/plugins/ts-quality/hooks/concerns/20-tests.sh +26 -0
- package/plugins/ts-quality/hooks/concerns/25-size-file.sh +40 -0
- package/plugins/ts-quality/hooks/concerns/30-size-fn.sh +53 -0
- package/plugins/ts-quality/hooks/concerns/35-react-hooks.sh +7 -0
- package/plugins/ts-quality/hooks/concerns/40-factory.sh +5 -0
- package/plugins/ts-quality/hooks/concerns/45-typeguard.sh +6 -0
- package/plugins/ts-quality/hooks/concerns/50-type-dup.sh +16 -0
- package/plugins/ts-quality/hooks/concerns/55-naming.sh +11 -0
- package/plugins/ts-quality/hooks/concerns/60-console.sh +6 -0
- package/plugins/ts-quality/hooks/concerns/65-suppression.sh +12 -0
- package/plugins/ts-quality/hooks/concerns/70-ui-confirm.sh +8 -0
- package/plugins/ts-quality/hooks/concerns/72-ui-radix.sh +12 -0
- package/plugins/ts-quality/hooks/concerns/74-react-props.sh +6 -0
- package/plugins/ts-quality/hooks/concerns/76-toast.sh +10 -0
- package/plugins/ts-quality/hooks/concerns/78-error-ast.sh +242 -0
- package/plugins/ts-quality/hooks/concerns/80-throw-literal.sh +23 -0
- package/plugins/ts-quality/hooks/concerns/85-no-mocks.sh +109 -0
- package/plugins/ts-quality/hooks/concerns/90-duplication.sh +30 -0
- package/plugins/ts-quality/hooks/concerns/92-docs.sh +36 -0
- package/plugins/ts-quality/hooks/concerns/94-handler.sh +15 -0
- package/plugins/ts-quality/hooks/concerns/99-finalize.sh +46 -0
- package/plugins/ts-quality/hooks/hooks.json +19 -0
- package/plugins/ts-quality/hooks/register.sh +65 -0
- package/src/adapter/__tests__/evaluate.test.ts +82 -0
- package/src/adapter/__tests__/permission-map.test.ts +91 -0
- package/src/adapter/evaluate.ts +54 -0
- package/src/adapter/permission-map.ts +177 -0
- package/src/bootstrap/__tests__/bootstrap.test.ts +148 -0
- package/src/bootstrap/entrypoint.ts +18 -0
- package/src/bootstrap/index.ts +5 -0
- package/src/bootstrap/readiness.ts +59 -0
- package/src/bootstrap/result.ts +21 -0
- package/src/bootstrap/runtime.ts +99 -0
- package/src/bootstrap/test-helpers.ts +25 -0
- package/src/host/__tests__/host.test.ts +37 -0
- package/src/host/detect.ts +46 -0
- package/src/host/index.ts +10 -0
- package/src/host/roots.ts +59 -0
- package/src/host/types.ts +14 -0
- package/src/inventory/__tests__/inventory.test.ts +69 -0
- package/src/inventory/index.ts +9 -0
- package/src/inventory/manifest.ts +46 -0
- package/src/inventory/scan.ts +66 -0
- package/src/inventory/selection.ts +92 -0
- package/src/inventory/types.ts +22 -0
- package/src/lifecycle/__tests__/lifecycle.test.ts +7 -0
- package/src/lifecycle/index.ts +2 -0
- package/src/lifecycle/table.ts +42 -0
- package/src/plugin/__tests__/plugin-stub.test.ts +6 -0
- package/src/plugin/plugin-stub.ts +7 -0
- package/src/plugin/toolu.ts +142 -0
- package/src/preflight/__tests__/preflight.test.ts +20 -0
- package/src/preflight/check.ts +75 -0
- package/src/preflight/index.ts +2 -0
- package/src/select/__tests__/select.test.ts +52 -0
- package/src/select/index.ts +2 -0
- 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,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.
|