Hook Components
Hook components listen for external events and trigger their children when those events occur. They’re useful for building reactive workflows that respond to CI/CD events, commits, and other triggers.
OnCIFailure
Monitors CI status and triggers children when a failure is detected.
import { OnCIFailure } from "smithers-orchestrator";
<OnCIFailure
provider="github-actions"
pollInterval={60000}
onFailure={(failure) => console.log('CI failed:', failure)}
>
{(failure) => (
<Claude>
The CI has failed. Here are the logs:
{failure.logs}
Analyze the failure and fix the issue.
</Claude>
)}
</OnCIFailure>
Props
CI provider to monitor. Currently only GitHub Actions is supported.
Polling interval in milliseconds.
onFailure
(failure: CIFailure) => void
Callback when a CI failure is detected.
children
ReactNode | ((failure: CIFailure) => ReactNode)
required
Content to render when a failure is detected. Can be a render prop function that receives the failure object.
CIFailure Type
interface CIFailure {
failed: boolean;
runId?: string;
workflowName?: string;
failedJobs?: string[];
logs?: string;
}
How It Works
- On mount, starts polling GitHub Actions for the latest run status
- When a failed run is detected (that hasn’t been processed before), triggers children
- Keeps track of processed run IDs to avoid re-triggering on the same failure
- Persists processed run IDs to database state for restart resilience
PostCommit
Triggers children when a git commit is made.
import { PostCommit } from "smithers-orchestrator";
<PostCommit runOn="smithers-only">
<Claude>
Review the latest commit and suggest improvements.
</Claude>
</PostCommit>
Props
runOn
'all' | 'smithers-only'
default:"all"
Filter which commits trigger the hook:
all: All commits trigger
smithers-only: Only commits with smithers metadata in git notes
Run children in background (non-blocking).
Content to render when a commit is detected.
How It Works
- On mount, installs a git post-commit hook that calls
bunx smithers hook-trigger post-commit "$COMMIT_HASH"
- Polls database state for
last_hook_trigger to detect new commits
- When a commit is detected (matching the
runOn filter), renders children
- Marks triggers as processed to avoid re-triggering
Git Hook Installation
The PostCommit component automatically installs this hook at .git/hooks/post-commit:
#!/bin/bash
COMMIT_HASH=$(git rev-parse HEAD)
bunx smithers hook-trigger post-commit "$COMMIT_HASH"
Example: CI Recovery Workflow
function CIRecoveryWorkflow() {
return (
<SmithersProvider db={db} executionId={executionId} maxIterations={3}>
<OnCIFailure
provider="github-actions"
pollInterval={30000}
onFailure={(f) => console.log(`CI failed: ${f.workflowName}`)}
>
{(failure) => (
<>
<Phase name="Analyze">
<Step name="analyze">
<Claude
allowedTools={["Read", "Grep", "Glob"]}
onFinished={(r) => db.state.set("analysis", r.output)}
>
Analyze these CI failure logs and identify the root cause:
Failed jobs: {failure.failedJobs?.join(", ")}
Logs:
{failure.logs}
</Claude>
</Step>
</Phase>
<Phase name="Fix">
<Step name="fix">
<Claude
allowedTools={["Read", "Edit", "Write"]}
onFinished={() => db.state.set("phase", "test")}
>
Based on the analysis, fix the failing tests or code.
</Claude>
</Step>
</Phase>
<Phase name="Commit">
<Step name="commit">
<Commit
autoGenerate
all
notes={{ smithers: true, ciRecovery: true }}
/>
</Step>
</Phase>
</>
)}
</OnCIFailure>
</SmithersProvider>
);
}
Example: Post-Commit Review
function PostCommitReview() {
return (
<SmithersProvider db={db} executionId={executionId}>
<PostCommit runOn="all">
<Review
target={{ type: "commit", ref: "HEAD" }}
criteria={[
"No security vulnerabilities",
"Code follows style guide",
"Tests are included",
]}
onFinished={(review) => {
if (!review.approved) {
console.log("Review issues:", review.issues);
}
}}
/>
</PostCommit>
</SmithersProvider>
);
}