UNPKG

claudekit

Version:

CLI tools for Claude Code development workflow

66 lines (53 loc) 2.04 kB
import type { HookContext, HookResult } from './base.js'; import { BaseHook } from './base.js'; import { TranscriptParser } from '../utils/transcript-parser.js'; export class CheckTodosHook extends BaseHook { name = 'check-todos'; static metadata = { id: 'check-todos', displayName: 'Check Todo Completion', description: 'Validate todo completions', category: 'project-management' as const, triggerEvent: ['Stop', 'SubagentStop'] as const, matcher: '*', }; async execute(context: HookContext): Promise<HookResult> { const { payload } = context; // Get transcript path const transcriptPath = payload.transcript_path as string | undefined; if (transcriptPath === undefined || transcriptPath === '') { // Allow stop - no transcript to check return { exitCode: 0 }; } const parser = new TranscriptParser(transcriptPath); if (!parser.exists()) { // Allow stop - transcript not found return { exitCode: 0 }; } // Find the most recent todo state const todoState = parser.findLatestTodoState(); if (!todoState) { // No todos found, allow stop return { exitCode: 0 }; } // Check for incomplete todos const incompleteTodos = todoState.filter((todo) => todo.status !== 'completed'); if (incompleteTodos.length > 0) { // Block stop and return JSON response const reason = `You have ${ incompleteTodos.length } incomplete todo items. You must complete all tasks before stopping:\n\n${incompleteTodos .map((todo) => ` - [${todo.status}] ${todo.content}`) .join( '\n' )}\n\nUse TodoRead to see the current status, then complete all remaining tasks. Mark each task as completed using TodoWrite as you finish them.`; this.jsonOutput({ decision: 'block', reason, }); return { exitCode: 0 }; // Note: exit 0 for Stop hooks, JSON controls decision } // All todos complete, allow stop return { exitCode: 0 }; } }