Skip to content

■ PEOPLE // FIELD NOTE

John Lindquist's TypeScript Hooks for Claude Code

How the egghead.io co-founder brings type safety to Claude Code automation after spending over 1 billion tokens on AI-assisted development

John Lindquist's TypeScript Hooks for Claude Code
[!] OPERATOR DOSSIER
[!] ON THIS PAGE

John Lindquist co-founded egghead.io in 2013 and invented the bite-sized screencast format that taught millions of developers AngularJS, React, and TypeScript. After 16 years of teaching developers, he now works on AI developer experience at Vercel and has spent over 1 billion tokens using Claude Code.

His claude-hooks project solves a specific problem: Claude Code hooks are powerful but writing them in raw shell scripts means no autocomplete, no type checking, and constant trips to the documentation to remember payload structures.

Background

  • Co-founded egghead.io in 2013, turning free AngularJS screencasts into a developer education platform
  • Previously Technical Architect at Roundarch, building apps for the Air Force, HBO, and Bloomberg
  • WebStorm evangelist at JetBrains before going full-time on egghead
  • Created Script Kit , an automation tool with 4.2k GitHub stars
  • Currently AI DX at Vercel

GitHub | Twitter | Site

Type-Safe Hooks

The claude-hooks project gives you TypeScript definitions for all hook events. Instead of guessing what fields exist on a PreToolUse payload, you get IntelliSense:

npx claude-hooks

This scaffolds a .claude/hooks/ directory with typed payloads:

// .claude/hooks/index.ts
import { PreToolUse, PostToolUse, Notification, Stop } from './lib'

export async function preToolUse(payload: PreToolUse) {
  // payload.tool_name, payload.tool_input fully typed
  if (payload.tool_name === 'write_file') {
    // Block writes to production files
    if (payload.tool_input.path.includes('production')) {
      return { action: 'block', reason: 'Cannot modify production files' }
    }
  }
}

export async function postToolUse(payload: PostToolUse) {
  // Run formatters after file edits
  if (payload.tool_name === 'write_file') {
    await formatFile(payload.tool_input.path)
  }
}

The type definitions cover all eight lifecycle events: UserPromptSubmit, PreToolUse, PostToolUse, Notification, Stop, and the session variants.

Hook Events

EventWhen It FiresUse Case
UserPromptSubmitBefore Claude sees your promptValidate or enhance prompts
PreToolUseBefore any tool executionBlock dangerous operations
PostToolUseAfter tool completionFormat code, run tests
NotificationWhen Claude sends notificationsCustom alerts (Slack, native)
StopWhen Claude finishes respondingSession cleanup, logging

Beyond Hooks

John also created mdflow , a CLI that runs Markdown files as executable prompts against Claude, Codex, Gemini, or Copilot. Write your prompt once in .md, run it against any backend:

mdflow run prompt.md --backend claude
mdflow run prompt.md --backend codex

His Claude Code Power-User workshop has trained 333 developers across seven cohorts, covering hooks, the SDK, sub-agents, and MCP integrations.

Key Takeaways

PrincipleImplementation
Type everythingUse claude-hooks for typed payloads instead of raw JSON
Automate formattingPostToolUse hooks run prettier/eslint after every edit
Block mistakes earlyPreToolUse hooks prevent writes to sensitive paths
Learn from volume1 billion tokens reveals patterns you miss in casual use

Next: Boris Cherny’s Claude Code