CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-anthropic-ai--claude-agent-sdk

SDK for building AI agents with Claude Code's capabilities to programmatically interact with Claude and build autonomous agents that can understand codebases, edit files, and execute workflows.

Overview
Eval results
Files

hooks.mddocs/apis/

Hook System

Intercept and modify agent behavior at key execution points.

Hook Events

type HookEvent =
  | 'PreToolUse'            // Before tool execution
  | 'PostToolUse'           // After successful execution
  | 'PostToolUseFailure'    // After execution failure
  | 'PermissionRequest'     // During permission request
  | 'UserPromptSubmit'      // User submits prompt
  | 'SessionStart'          // Session starts
  | 'SessionEnd'            // Session ends
  | 'Stop'                  // Execution stops
  | 'SubagentStart'         // Subagent starts
  | 'SubagentStop'          // Subagent stops
  | 'PreCompact'            // Before compaction
  | 'Notification';         // System notification

Hook Callback

type HookCallback = (
  input: HookInput,
  toolUseID: string | undefined,
  options: {signal: AbortSignal}
) => Promise<HookJSONOutput>;

interface HookCallbackMatcher {
  matcher?: string;
  hooks: HookCallback[];
  timeout?: number;
}

Hook Input Types

interface PreToolUseHookInput {
  hook_event_name: 'PreToolUse';
  tool_name: string;
  tool_input: unknown;
  tool_use_id: string;
  session_id: string;
  transcript_path: string;
  cwd: string;
  permission_mode?: string;
}

interface PostToolUseHookInput {
  hook_event_name: 'PostToolUse';
  tool_name: string;
  tool_input: unknown;
  tool_response: unknown;
  tool_use_id: string;
  // ... base fields
}

interface PostToolUseFailureHookInput {
  hook_event_name: 'PostToolUseFailure';
  tool_name: string;
  tool_input: unknown;
  tool_use_id: string;
  error: string;
  is_interrupt?: boolean;
  // ... base fields
}

// See types.md for complete list

Hook Output

interface SyncHookJSONOutput {
  continue?: boolean;
  suppressOutput?: boolean;
  stopReason?: string;
  decision?: 'approve' | 'block';
  systemMessage?: string;
  reason?: string;
  hookSpecificOutput?:
    | {hookEventName: 'PreToolUse'; permissionDecision?: 'allow' | 'deny' | 'ask'; permissionDecisionReason?: string; updatedInput?: Record<string, unknown>}
    | {hookEventName: 'UserPromptSubmit'; additionalContext?: string}
    | {hookEventName: 'SessionStart'; additionalContext?: string}
    | {hookEventName: 'PostToolUse'; additionalContext?: string; updatedMCPToolOutput?: unknown}
    | {hookEventName: 'PostToolUseFailure'; additionalContext?: string}
    | {hookEventName: 'PermissionRequest'; decision: {behavior: 'allow'; updatedInput?: Record<string, unknown>} | {behavior: 'deny'; message?: string; interrupt?: boolean}};
}

interface AsyncHookJSONOutput {
  async: true;
  asyncTimeout?: number;
}

type HookJSONOutput = SyncHookJSONOutput | AsyncHookJSONOutput;

Examples

Logging

hooks: {
  PreToolUse: [{
    hooks: [async (input) => {
      if (input.hook_event_name === 'PreToolUse') {
        console.log(`[${input.tool_name}]`, input.tool_input);
      }
      return {continue: true};
    }]
  }],
  PostToolUse: [{
    hooks: [async (input) => {
      if (input.hook_event_name === 'PostToolUse') {
        console.log(`[${input.tool_name} ✓]`);
      }
      return {continue: true};
    }]
  }]
}

Block Operations

hooks: {
  PreToolUse: [{
    hooks: [async (input) => {
      if (input.hook_event_name === 'PreToolUse') {
        if (input.tool_name === 'Bash' &&
            (input.tool_input as any).command?.includes('rm -rf')) {
          return {
            continue: false,
            stopReason: 'Dangerous command blocked',
            hookSpecificOutput: {
              hookEventName: 'PreToolUse',
              permissionDecision: 'deny',
              permissionDecisionReason: 'rm -rf not allowed'
            }
          };
        }
      }
      return {continue: true};
    }]
  }]
}

Add Context

hooks: {
  SessionStart: [{
    hooks: [async (input) => {
      if (input.hook_event_name === 'SessionStart') {
        return {
          continue: true,
          hookSpecificOutput: {
            hookEventName: 'SessionStart',
            additionalContext: 'Project uses TypeScript. Follow TS best practices.'
          }
        };
      }
      return {continue: true};
    }]
  }]
}

Complete Example

const result = query({
  prompt: 'Build project',
  options: {
    hooks: {
      PreToolUse: [{
        hooks: [async (input) => {
          if (input.hook_event_name === 'PreToolUse') {
            console.log(`[PRE] ${input.tool_name}:`, input.tool_input);
          }
          return {continue: true};
        }],
        timeout: 5
      }],

      PostToolUse: [{
        hooks: [async (input) => {
          if (input.hook_event_name === 'PostToolUse') {
            console.log(`[POST] ${input.tool_name} completed`);
          }
          return {continue: true};
        }]
      }],

      PostToolUseFailure: [{
        hooks: [async (input) => {
          if (input.hook_event_name === 'PostToolUseFailure') {
            console.error(`[FAIL] ${input.tool_name}:`, input.error);
          }
          return {continue: true};
        }]
      }],

      SessionStart: [{
        hooks: [async (input) => {
          if (input.hook_event_name === 'SessionStart') {
            console.log('Session started:', input.source);
            return {
              continue: true,
              hookSpecificOutput: {
                hookEventName: 'SessionStart',
                additionalContext: 'Use TypeScript best practices'
              }
            };
          }
          return {continue: true};
        }]
      }]
    }
  }
});

for await (const msg of result) {
  if (msg.type === 'system' && msg.subtype === 'hook_response') {
    console.log('Hook:', msg.hook_name, msg.hook_event);
    if (msg.exit_code !== 0) {
      console.error('Hook failed:', msg.stderr);
    }
  }
}

Constants

const HOOK_EVENTS: readonly ["PreToolUse", "PostToolUse", "PostToolUseFailure", "Notification", "UserPromptSubmit", "SessionStart", "SessionEnd", "Stop", "SubagentStart", "SubagentStop", "PreCompact", "PermissionRequest"];

Install with Tessl CLI

npx tessl i tessl/npm-anthropic-ai--claude-agent-sdk

docs

apis

agents.md

hooks.md

mcp.md

messages.md

options.md

permissions.md

query-api.md

sandbox.md

tools.md

index.md

patterns.md

quick-reference.md

types.md

tile.json