Skip to content

Commit c746137

Browse files
hooks: Show install guidance when sce is missing
Add fail-open missing-CLI guidance for generated Claude hook commands, OpenCode plugin wrappers, and the git post-commit hook. Preserve normal hook delegation when sce is installed while surfacing the install URL when hook runtime cannot find the CLI. Co-authored-by: SCE <sce@crocoder.dev>
1 parent 9cf41dd commit c746137

25 files changed

Lines changed: 186 additions & 42 deletions

.claude/hooks/run-sce-or-show-install-guidance.sh

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.claude/settings.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.opencode/plugins/sce-agent-trace.ts

Lines changed: 19 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.opencode/plugins/sce-bash-policy.ts

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/assets/hooks/post-commit

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ set -eu
33

44
remote_url="$(git remote get-url origin 2>/dev/null || true)"
55

6+
if ! command -v sce >/dev/null 2>&1; then
7+
echo "sce CLI not found. Install it from https://sce.crocoder.dev/docs/getting-started#install-cli" >&2
8+
exit 0
9+
fi
10+
611
if [ -n "$remote_url" ]; then
712
exec sce hooks post-commit --vcs git --remote-url "$remote_url" "$@"
813
fi
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
if ! command -v sce >/dev/null 2>&1; then
5+
echo "sce CLI not found. Install it from https://sce.crocoder.dev/docs/getting-started#install-cli" >&2
6+
exit 0
7+
fi
8+
9+
exec "$@"

config/.claude/settings.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"hooks": [
77
{
88
"type": "command",
9-
"command": "sce hooks session-model"
9+
"command": "bash .claude/hooks/run-sce-or-show-install-guidance.sh sce hooks session-model"
1010
}
1111
]
1212
}
@@ -17,7 +17,7 @@
1717
"hooks": [
1818
{
1919
"type": "command",
20-
"command": "sce policy bash"
20+
"command": "bash .claude/hooks/run-sce-or-show-install-guidance.sh sce policy bash"
2121
}
2222
]
2323
}
@@ -28,15 +28,15 @@
2828
"hooks": [
2929
{
3030
"type": "command",
31-
"command": "sce hooks diff-trace"
31+
"command": "bash .claude/hooks/run-sce-or-show-install-guidance.sh sce hooks diff-trace"
3232
}
3333
]
3434
},
3535
{
3636
"hooks": [
3737
{
3838
"type": "command",
39-
"command": "sce hooks conversation-trace"
39+
"command": "bash .claude/hooks/run-sce-or-show-install-guidance.sh sce hooks conversation-trace"
4040
}
4141
]
4242
}
@@ -46,7 +46,7 @@
4646
"hooks": [
4747
{
4848
"type": "command",
49-
"command": "sce hooks conversation-trace"
49+
"command": "bash .claude/hooks/run-sce-or-show-install-guidance.sh sce hooks conversation-trace"
5050
}
5151
]
5252
}
@@ -56,7 +56,7 @@
5656
"hooks": [
5757
{
5858
"type": "command",
59-
"command": "sce hooks conversation-trace"
59+
"command": "bash .claude/hooks/run-sce-or-show-install-guidance.sh sce hooks conversation-trace"
6060
}
6161
]
6262
}

config/.opencode/plugins/sce-agent-trace.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import type { Hooks, Plugin } from "@opencode-ai/plugin";
33

44
type OpenCodeEvent = Parameters<NonNullable<Hooks["event"]>>[0]["event"];
55

6+
const SCE_INSTALL_URL =
7+
"https://sce.crocoder.dev/docs/getting-started#install-cli";
8+
69
const REQUIRED_EVENTS: Set<OpenCodeEvent["type"]> = new Set([
710
"message.updated",
811
"message.part.updated",
@@ -332,7 +335,14 @@ async function runDiffTraceHook(
332335
stdio: ["pipe", "ignore", "ignore"],
333336
});
334337

335-
child.on("error", () => resolve());
338+
child.on("error", (err: NodeJS.ErrnoException) => {
339+
if (err.code === "ENOENT") {
340+
console.warn(
341+
`sce CLI not found. Install it from ${SCE_INSTALL_URL}`,
342+
);
343+
}
344+
resolve();
345+
});
336346
child.on("close", () => resolve());
337347

338348
child.stdin.end(`${JSON.stringify(payload)}\n`);
@@ -352,7 +362,14 @@ async function runConversationTraceHook(
352362
stdio: ["pipe", "ignore", "ignore"],
353363
});
354364

355-
child.on("error", () => resolve());
365+
child.on("error", (err: NodeJS.ErrnoException) => {
366+
if (err.code === "ENOENT") {
367+
console.warn(
368+
`sce CLI not found. Install it from ${SCE_INSTALL_URL}`,
369+
);
370+
}
371+
resolve();
372+
});
356373
child.on("close", () => resolve());
357374

358375
child.stdin.end(`${JSON.stringify(payload)}\n`);

config/.opencode/plugins/sce-bash-policy.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ interface JsonPolicyResult {
1010
policy_id?: string;
1111
}
1212

13+
const SCE_INSTALL_URL =
14+
"https://sce.crocoder.dev/docs/getting-started#install-cli";
15+
1316
/**
1417
* Evaluate a bash command against SCE bash-tool policy by delegating to the
1518
* Rust `sce policy bash` command. Returns the parsed JSON result, or null if
@@ -28,6 +31,11 @@ function evaluateBashCommandPolicy(command: string): JsonPolicyResult | null {
2831
);
2932

3033
if (result.error) {
34+
if ((result.error as NodeJS.ErrnoException).code === "ENOENT") {
35+
console.warn(
36+
`sce CLI not found. Install it from ${SCE_INSTALL_URL}`,
37+
);
38+
}
3139
return null;
3240
}
3341

config/automated/.opencode/plugins/sce-agent-trace.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ import type { Hooks, Plugin } from "@opencode-ai/plugin";
33

44
type OpenCodeEvent = Parameters<NonNullable<Hooks["event"]>>[0]["event"];
55

6+
const SCE_INSTALL_URL =
7+
"https://sce.crocoder.dev/docs/getting-started#install-cli";
8+
69
const REQUIRED_EVENTS: Set<OpenCodeEvent["type"]> = new Set([
710
"message.updated",
811
"message.part.updated",
@@ -332,7 +335,14 @@ async function runDiffTraceHook(
332335
stdio: ["pipe", "ignore", "ignore"],
333336
});
334337

335-
child.on("error", () => resolve());
338+
child.on("error", (err: NodeJS.ErrnoException) => {
339+
if (err.code === "ENOENT") {
340+
console.warn(
341+
`sce CLI not found. Install it from ${SCE_INSTALL_URL}`,
342+
);
343+
}
344+
resolve();
345+
});
336346
child.on("close", () => resolve());
337347

338348
child.stdin.end(`${JSON.stringify(payload)}\n`);
@@ -352,7 +362,14 @@ async function runConversationTraceHook(
352362
stdio: ["pipe", "ignore", "ignore"],
353363
});
354364

355-
child.on("error", () => resolve());
365+
child.on("error", (err: NodeJS.ErrnoException) => {
366+
if (err.code === "ENOENT") {
367+
console.warn(
368+
`sce CLI not found. Install it from ${SCE_INSTALL_URL}`,
369+
);
370+
}
371+
resolve();
372+
});
356373
child.on("close", () => resolve());
357374

358375
child.stdin.end(`${JSON.stringify(payload)}\n`);

0 commit comments

Comments
 (0)