Skip to content
Back to skills

Claude Hooks Sdk

BSecurity

Expert guide for building Claude Code hooks using the claude-hooks-sdk npm package. Use when implementing TypeScript hooks with HookManager, Logger, transforms, context tracking, or troubleshooting SDK features.

  • 666 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added February 8, 2026
toolstypescriptbashreactgitapi

Works with

  • claude code
  • cli
  • api

Security analysis

B89/100
  • highPerforms destructive filesystem operations
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned February 12, 2026

npx -y skills add majiayu000/claude-skill-registry --skill claude-hooks-sdk --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Claude Hooks Sdk?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Claude Hooks Sdk
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/majiayu000-claude-hooks-sdk/badge)](https://www.skillsdirectory.com/skills/majiayu000-claude-hooks-sdk)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: claude-hooks-sdk
description: Expert guide for building Claude Code hooks using the claude-hooks-sdk npm package. Use when implementing TypeScript hooks with HookManager, Logger, transforms, context tracking, or troubleshooting SDK features.
---

# Claude Hooks SDK Expert

You are an expert on the `claude-hooks-sdk` npm package. Help users build, configure, and troubleshoot Claude Code hooks using the SDK.

## Quick Reference

### Installation
```bash
bun add claude-hooks-sdk
# or
npm install claude-hooks-sdk
```

### Basic Setup
```typescript
#!/usr/bin/env bun
import { HookManager, success, block, createLogger } from 'claude-hooks-sdk';

const logger = createLogger('my-hook');

const manager = new HookManager({
  logEvents: true,
  clientId: 'my-hook',
  enableContextTracking: true,
  trackEdits: true,
});

manager.onPreToolUse(async (input, context) => {
  if (input.tool_name === 'Bash' && input.tool_input.command.includes('rm -rf /')) {
    return block('Dangerous command blocked');
  }
  return success();
});

manager.run();
```

### Configuration Options

```typescript
interface HookManagerOptions {
  // Logging
  logEvents?: boolean;
  clientId?: string;
  logDir?: string;
  debug?: boolean;

  // Context & Tracking
  enableContextTracking?: boolean;
  trackEdits?: boolean;

  // Error Handling
  blockOnFailure?: boolean;
  enableFailureQueue?: boolean;
  maxRetries?: number;
  handlerTimeout?: number;
}
```

## Logger Utility

```typescript
import { createLogger } from 'claude-hooks-sdk';

const logger = createLogger('my-hook');

logger.info('Always shown');
logger.logDebug('Only shown when DEBUG=1');
logger.warn('Warning message');
logger.error(new Error('Something failed'));
```

## Constants

```typescript
import {
  DEFAULT_HANDLER_TIMEOUT_MS,  // 30000
  DEFAULT_MAX_RETRIES,         // 3
  EXIT_CODE_SUCCESS,           // 0
  EXIT_CODE_ERROR,             // 1
  EXIT_CODE_BLOCK,             // 2
} from 'claude-hooks-sdk';
```

## Transforms

### ConversationLogger
```typescript
import { ConversationLogger } from 'claude-hooks-sdk';

const conversationLogger = new ConversationLogger();

manager.onUserPromptSubmit((input) => {
  conversationLogger.recordUserPrompt(input);
  return success();
});

manager.onStop(async (input, context) => {
  const turn = await conversationLogger.recordStop(input, context);
  console.log(`Turn ${turn.turn_number} recorded`);
  return success();
});
```

### FileChangeTracker
```typescript
import { FileChangeTracker } from 'claude-hooks-sdk';

const fileTracker = new FileChangeTracker();

manager.onPostToolUse((input) => {
  fileTracker.recordChange(input);
  return success();
});

manager.onStop(async (input) => {
  const changes = fileTracker.getBatch(input.session_id);
  console.log(`${changes.total_files} files modified`);
  return success();
});
```

## Hook Event Handlers

```typescript
manager.onSessionStart(async (input, context) => {
  console.log('Session started:', input.session_id);
  return success();
});

manager.onUserPromptSubmit(async (input, context) => {
  // Add context to Claude's prompt
  return success();
});

manager.onPreToolUse(async (input, context) => {
  // Block dangerous operations
  if (shouldBlock(input)) {
    return block('Reason for blocking');
  }
  return success();
});

manager.onPostToolUse(async (input, context) => {
  // React to tool completion
  return success();
});

manager.onStop(async (input, context) => {
  // Session ending - access context.editedFiles
  console.log('Edited files:', context.editedFiles);
  return success();
});
```

## Context Tracking

```typescript
interface EventContext {
  transactionId: string;
  conversationId: string;
  promptId?: string;
  project_dir?: string;
  git?: {
    user: string;
    email: string;
    repo: string;
    branch: string;
    commit: string;
    dirty: boolean;
  };
  editedFiles?: string[];  // When trackEdits: true
}
```

## Session Context Injection

One-liner to inject session info into Claude's context:

```typescript
#!/usr/bin/env bun
import { createUserPromptSubmitHook } from 'claude-hooks-sdk';

createUserPromptSubmitHook();
```

With customization:
```typescript
createUserPromptSubmitHook({
  format: (name, id) => `Session: ${name} [${id.slice(0, 8)}]`,
  customContext: async (input) => `Branch: ${getBranch()}`,
});
```

## Failure Queue

```typescript
const manager = new HookManager({
  enableFailureQueue: true,
  maxRetries: 3,
  onErrorQueueNotEmpty: (size) => {
    console.warn(`${size} events queued for retry`);
  },
});
```

## Blocking vs Non-Blocking

**Non-blocking (default):** Hook failures don't stop Claude Code
```typescript
const manager = new HookManager({
  blockOnFailure: false,
});
```

**Blocking:** Hook failures stop Claude Code
```typescript
const manager = new HookManager({
  blockOnFailure: true,
});
```

## Common Patterns

### API Integration
```typescript
manager.onStop(async (input, context) => {
  await fetch('https://api.example.com/events', {
    method: 'POST',
    body: JSON.stringify({ event: input, context }),
  });
  return success();
});
```

### Command Blocking
```typescript
manager.onPreToolUse(async (input) => {
  if (input.tool_name !== 'Bash') return success();

  const dangerous = [/rm\s+-rf\s+\//, /dd\s+if=\/dev\/zero/];
  for (const pattern of dangerous) {
    if (pattern.test(input.tool_input.command)) {
      return block('Blocked dangerous command');
    }
  }
  return success();
});
```

### File Change Notifications
```typescript
manager.onStop(async (input, context) => {
  if (context.editedFiles?.length > 10) {
    await sendSlackMessage({
      text: `Large changeset: ${context.editedFiles.length} files`,
    });
  }
  return success();
});
```

## Troubleshooting

### Logs not appearing
- Check `logEvents: true` is set
- Log path: `.claude/hooks/{clientId}/logs/events.jsonl`

### Context not enriched
- Verify `enableContextTracking: true`
- For git metadata: must be in a git repo
- For editedFiles: `trackEdits: true` required

### Handler timeout
```typescript
const manager = new HookManager({
  handlerTimeout: 30000,  // 30 seconds
});
```

## Resources

- **npm:** https://www.npmjs.com/package/claude-hooks-sdk
- **GitHub:** https://github.com/hgeldenhuys/claude-hooks-sdk
- **Examples:** https://github.com/hgeldenhuys/claude-hooks-sdk-examples

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.