Skip to content

Commit 22d8e08

Browse files
Merge pull request #13 from johnlindquist/refactor/typescript-focus
Refactor: Reposition project focus from security to TypeScript convenience
2 parents dada34f + 73f8dcf commit 22d8e08

File tree

2 files changed

+66
-35
lines changed

2 files changed

+66
-35
lines changed

README.md

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
[![Version](https://img.shields.io/npm/v/claude-hooks.svg)](https://npmjs.org/package/claude-hooks)
44
[![License](https://img.shields.io/npm/l/claude-hooks.svg)](https://github.com/johnlindquist/claude-hooks/blob/main/LICENSE)
55

6-
> Simple CLI to initialize Claude Code hooks in your project
6+
> TypeScript-powered hook system for Claude Code - write hooks with full type safety and auto-completion
77
88
## Overview
99

10-
`claude-hooks` is a straightforward CLI tool that sets up Claude Code hooks in your project. It creates the necessary files and configuration to intercept and log Claude's tool usage, with basic security protection against dangerous commands.
10+
`claude-hooks` gives you a powerful, TypeScript-based way to customize Claude Code's behavior. Write hooks with full type safety, auto-completion, and access to strongly-typed payloads - all in familiar TypeScript syntax. No more guessing payload structures or dealing with untyped data!
1111

1212
## Quick Start
1313

@@ -17,9 +17,9 @@ npx claude-hooks
1717

1818
This will:
1919
- Create `.claude/settings.json` with hook configuration
20-
- Generate `.claude/hooks/index.ts` with default handlers
21-
- Set up session logging in system temp directory
22-
- Create supporting files (lib.ts and session.ts)
20+
- Generate `.claude/hooks/index.ts` with TypeScript handlers
21+
- Set up typed payload interfaces for all hook types
22+
- Create utilities for easy hook development
2323

2424
## Installation
2525

@@ -38,15 +38,16 @@ claude-hooks
3838

3939
## What It Does
4040

41-
The CLI generates a basic hook setup that:
41+
The CLI sets up a complete TypeScript development environment for Claude hooks:
4242

43-
1. **Logs all Claude interactions** - Saves session data for all hook types (PreToolUse, PostToolUse, Notification, Stop) to the system temp directory
44-
2. **Blocks dangerous commands** - Prevents `rm -rf /` and `rm -rf ~` commands
45-
3. **Creates necessary files**:
43+
1. **Full TypeScript Support** - Write hooks with complete type safety and IntelliSense
44+
2. **Typed Payloads** - Access strongly-typed payload data for all hook types (PreToolUse, PostToolUse, Notification, Stop)
45+
3. **Ready-to-Customize** - Simple, clean TypeScript files ready for your custom logic
46+
4. **Generated Files**:
4647
- `.claude/settings.json` - Hook configuration
47-
- `.claude/hooks/index.ts` - Hook handlers
48-
- `.claude/hooks/lib.ts` - Base utilities and types
49-
- `.claude/hooks/session.ts` - Session logging utilities
48+
- `.claude/hooks/index.ts` - Your main hook handlers (edit this!)
49+
- `.claude/hooks/lib.ts` - Type definitions and utilities
50+
- `.claude/hooks/session.ts` - Optional session tracking utilities
5051

5152
## Generated Structure
5253

@@ -63,18 +64,34 @@ Session logs are saved to: `<system-temp-dir>/claude-hooks-sessions/`
6364

6465
## Customizing Hooks
6566

66-
After running the setup, you can edit `.claude/hooks/index.ts` to add your own logic:
67+
The real power comes from editing `.claude/hooks/index.ts`. You get full TypeScript support with typed payloads:
6768

6869
```typescript
69-
// Example: Block additional dangerous commands
70-
if (command && command.includes('DROP DATABASE')) {
71-
return {
72-
action: 'block',
73-
stopReason: 'Database drop commands are not allowed'
74-
};
70+
// Example: Track and log specific tool usage
71+
async function preToolUse(payload: PreToolUsePayload): Promise<HookResponse> {
72+
// Full type safety - TypeScript knows exactly what's in the payload!
73+
if (payload.tool_name === 'Write' && payload.tool_input) {
74+
const { file_path, content } = payload.tool_input as WriteToolInput
75+
console.log(`Claude is writing to: ${file_path}`)
76+
77+
// Add your custom logic here
78+
// Maybe notify a webhook, update a dashboard, etc.
79+
}
80+
81+
return { action: 'continue' }
82+
}
83+
84+
// Example: React to completed tasks
85+
async function postToolUse(payload: PostToolUsePayload): Promise<void> {
86+
if (payload.tool_name === 'Bash' && payload.success) {
87+
// TypeScript gives you auto-completion for all payload properties!
88+
console.log(`Command completed: ${payload.tool_input.command}`)
89+
}
7590
}
7691
```
7792

93+
The beauty is that you're writing regular TypeScript - use any npm packages, async/await, or patterns you're familiar with!
94+
7895
## Command Options
7996

8097
```bash

templates/hooks/index.ts

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,56 @@ import {
1111
} from './lib'
1212
import {saveSessionData} from './session'
1313

14-
// PreToolUse handler - validate and potentially block dangerous commands
14+
// PreToolUse handler - called before Claude uses any tool
1515
async function preToolUse(payload: PreToolUsePayload): Promise<HookResponse> {
16-
// Save session data
16+
// Save session data (optional - remove if not needed)
1717
await saveSessionData('PreToolUse', payload)
1818

19-
// Example: Block dangerous commands
19+
// Example: Log when Claude is about to edit files
20+
if (payload.tool_name === 'Edit' && payload.tool_input) {
21+
const { file_path } = payload.tool_input as any
22+
console.log(`📝 Claude is editing: ${file_path}`)
23+
}
24+
25+
// Example: Track bash commands
2026
if (payload.tool_name === 'Bash' && payload.tool_input && 'command' in payload.tool_input) {
2127
const bashInput = payload.tool_input as BashToolInput
22-
const command = bashInput.command
23-
24-
// Block rm -rf commands
25-
if (command && (command.includes('rm -rf /') || command.includes('rm -rf ~'))) {
26-
return {
27-
action: 'block',
28-
stopReason: 'Dangerous command detected: rm -rf on system directories',
29-
}
30-
}
28+
console.log(`🚀 Running command: ${bashInput.command}`)
3129
}
3230

33-
// Allow all other commands
31+
// Add your custom logic here!
32+
// You have full TypeScript support and can use any npm packages
33+
3434
return {action: 'continue'}
3535
}
3636

37-
// PostToolUse handler - log tool results
37+
// PostToolUse handler - called after Claude uses a tool
3838
async function postToolUse(payload: PostToolUsePayload): Promise<void> {
39+
// Save session data (optional - remove if not needed)
3940
await saveSessionData('PostToolUse', payload)
41+
42+
// Example: React to successful file writes
43+
if (payload.tool_name === 'Write' && payload.success) {
44+
console.log(`✅ File written successfully!`)
45+
}
46+
47+
// Add your custom post-processing logic here
4048
}
4149

42-
// Notification handler - log notifications
50+
// Notification handler - receive Claude's notifications
4351
async function notification(payload: NotificationPayload): Promise<void> {
4452
await saveSessionData('Notification', payload)
53+
54+
// Example: Log Claude's progress
55+
console.log(`🔔 ${payload.message}`)
4556
}
4657

47-
// Stop handler - log session end
58+
// Stop handler - called when Claude stops
4859
async function stop(payload: StopPayload): Promise<void> {
4960
await saveSessionData('Stop', payload)
61+
62+
// Example: Summary or cleanup logic
63+
console.log(`👋 Session ended: ${payload.reason}`)
5064
}
5165

5266
// Run the hook with our handlers

0 commit comments

Comments
 (0)