Skip to main content

Claude Component

The <Claude> component is the core of Smithers. It executes Claude via Claude Code CLI with full tool access, database logging, and structured output support.

Basic Usage

import { Claude } from "smithers/smithers-orchestrator/src/components/Claude";

<Claude
  model="sonnet"
  maxTurns={10}
  onFinished={(result) => console.log(result.output)}
>
  Analyze this codebase and suggest improvements.
</Claude>

Props

Model Configuration

model
'opus' | 'sonnet' | 'haiku'
default:"sonnet"
The Claude model to use.
<Claude model="opus">Complex reasoning task</Claude>
<Claude model="sonnet">Standard task</Claude>
<Claude model="haiku">Quick, simple task</Claude>
maxTurns
number
Maximum number of agentic turns (tool use cycles).
<Claude maxTurns={5}>Limited iteration task</Claude>
maxTokens
number
Maximum tokens for the response.
timeout
number
Timeout in milliseconds.
<Claude timeout={60000}>Task with 1 minute timeout</Claude>

System Prompt

systemPrompt
string
Custom system prompt for Claude.
<Claude systemPrompt="You are a security expert. Focus on vulnerabilities.">
  Review this code.
</Claude>

Tool Configuration

tools
Tool[]
Custom tools to provide to Claude.
<Claude tools={[myCustomTool]}>
  Use the custom tool.
</Claude>
allowedTools
string[]
Restrict Claude to only these built-in tools.
<Claude allowedTools={["Read", "Glob", "Grep"]}>
  Research only - no edits.
</Claude>
disallowedTools
string[]
Prevent Claude from using these tools.
<Claude disallowedTools={["Bash"]}>
  No shell commands.
</Claude>
permissionMode
'default' | 'acceptEdits' | 'plan'
Permission handling mode.
<Claude permissionMode="acceptEdits">
  Auto-accept file edits.
</Claude>

Structured Output

schema
ZodSchema
Zod schema for structured output validation.
const ResultSchema = z.object({
  summary: z.string(),
  issues: z.array(z.string()),
});

<Claude schema={ResultSchema}>
  Return structured analysis.
</Claude>
validate
(output: T) => boolean
Custom validation function.
<Claude validate={(r) => r.issues.length > 0}>
  Must find at least one issue.
</Claude>
retryOnValidationFailure
boolean
default:"true"
Retry if validation fails.
maxRetries
number
default:"2"
Maximum validation retries.

Callbacks

onFinished
(result: AgentResult) => void
Called when execution completes.
<Claude onFinished={(result) => {
  console.log(result.output);
  console.log(result.structured);  // If schema provided
  console.log(result.tokensUsed);
}}>
  Task
</Claude>
onError
(error: Error) => void
Called on execution error.
<Claude onError={(err) => console.error(err)}>
  Risky task
</Claude>
onProgress
(message: string) => void
Called with progress updates.
onToolCall
(tool: string, input: any) => void
Called when Claude uses a tool.

Stop Conditions

stopConditions
StopCondition[]
Conditions that can stop execution early.
<Claude
  stopConditions={[
    { type: "token_limit", value: 10000 },
    { type: "pattern", value: /DONE/i },
  ]}
>
  Task with stop conditions
</Claude>

AgentResult Type

interface AgentResult<T = any> {
  output: string;              // Raw text output
  structured?: T;              // Validated structured output
  tokensUsed: {
    input: number;
    output: number;
  };
  turnsUsed: number;
  stopReason: 'completed' | 'stop_condition' | 'error' | 'cancelled';
  durationMs: number;
  exitCode?: number;
  sessionId?: string;
}

Structured Output with Zod

Get typed, validated responses:
import { z } from 'zod';

const AnalysisSchema = z.object({
  summary: z.string(),
  issues: z.array(z.object({
    severity: z.enum(['low', 'medium', 'high', 'critical']),
    file: z.string(),
    description: z.string(),
  })),
  recommendations: z.array(z.string()),
});

<Claude
  model="sonnet"
  schema={AnalysisSchema}
  maxRetries={2}
  onFinished={(result) => {
    // result.structured is typed as z.infer<typeof AnalysisSchema>
    for (const issue of result.structured.issues) {
      console.log(`[${issue.severity}] ${issue.file}: ${issue.description}`);
    }
  }}
>
  Analyze this codebase for security issues.
  Return a structured analysis.
</Claude>

Tool Restrictions

Control what Claude can do:
// Research only - no modifications
<Claude allowedTools={["Read", "Glob", "Grep"]}>
  Find all files that import the auth module.
</Claude>

// Full edit access
<Claude
  allowedTools={["Read", "Edit", "Write", "Bash"]}
  permissionMode="acceptEdits"
>
  Implement the feature.
</Claude>

// No shell access
<Claude disallowedTools={["Bash"]}>
  Analyze the code (no commands).
</Claude>

Conditional Rendering

Use signals to control when Claude runs:
function ConditionalClaude() {
  const [phase, setPhase] = createSignal("research");

  return (
    <Ralph maxIterations={5}>
      {phase() === "research" && (
        <Claude
          allowedTools={["Read", "Glob"]}
          onFinished={() => setPhase("implement")}
        >
          Research the codebase.
        </Claude>
      )}

      {phase() === "implement" && (
        <Claude
          allowedTools={["Edit", "Write"]}
          onFinished={() => setPhase("done")}
        >
          Implement the solution.
        </Claude>
      )}
    </Ralph>
  );
}

Nested Prompt Components

Compose prompts with child components:
<Claude model="sonnet">
  <Sqlite path="./data.db">
    Database contains users and orders tables.
  </Sqlite>

  Find the top 10 customers by order value.
  Export results to a CSV file.
</Claude>

Error Handling

function ResilientClaude() {
  const [attempts, setAttempts] = createSignal(0);
  const [error, setError] = createSignal<Error | null>(null);

  return (
    <Ralph maxIterations={3}>
      {error() && attempts() < 3 && (
        <Claude
          onFinished={() => setError(null)}
          onError={(err) => {
            setError(err);
            setAttempts(a => a + 1);
          }}
        >
          Previous attempt failed: {error()?.message}
          Try a different approach.
        </Claude>
      )}

      {!error() && (
        <Claude
          onFinished={(r) => console.log("Success:", r.output)}
          onError={setError}
        >
          Complete the task.
        </Claude>
      )}
    </Ralph>
  );
}

Best Practices

Prevent runaway iterations:
<Claude maxTurns={10}>...</Claude>
Follow principle of least privilege:
// Research phase - read only
<Claude allowedTools={["Read", "Glob", "Grep"]}>

// Implementation phase - edit access
<Claude allowedTools={["Read", "Edit", "Write"]}>
Validate responses with Zod:
<Claude schema={MySchema} maxRetries={2}>