Skip to main content

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

provider
'github-actions'
required
CI provider to monitor. Currently only GitHub Actions is supported.
pollInterval
number
default:"30000"
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

  1. On mount, starts polling GitHub Actions for the latest run status
  2. When a failed run is detected (that hasn’t been processed before), triggers children
  3. Keeps track of processed run IDs to avoid re-triggering on the same failure
  4. 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
async
boolean
default:"false"
Run children in background (non-blocking).
children
ReactNode
required
Content to render when a commit is detected.

How It Works

  1. On mount, installs a git post-commit hook that calls bunx smithers hook-trigger post-commit "$COMMIT_HASH"
  2. Polls database state for last_hook_trigger to detect new commits
  3. When a commit is detected (matching the runOn filter), renders children
  4. 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>
  );
}