/** * App-specific wrapper around ink's KeybindingSetup. * * Wires up app-specific dependencies (notification system, binding loading, * file watching, debug logging) and re-exports as KeybindingSetup. */ import { useCallback } from 'react' import { useNotifications } from '../context/notifications.js' import { count } from '../utils/array.js' import { logForDebugging } from '../utils/debug.js' import { plural } from '../utils/stringUtils.js' import { KeybindingSetup as InkKeybindingSetup } from '@anthropic/ink' import type { KeybindingWarning } from '@anthropic/ink' import { initializeKeybindingWatcher, loadKeybindingsSyncWithWarnings, subscribeToKeybindingChanges, } from './loadUserBindings.js' type Props = { children: React.ReactNode } /** * Keybinding provider with default + user bindings and hot-reload support. * * Usage: Wrap your app with this provider to enable keybinding support. * * ```tsx * * * * * * ``` * * Features: * - Loads default bindings from code * - Merges with user bindings from ~/.claude/keybindings.json * - Watches for file changes and reloads automatically (hot-reload) * - User bindings override defaults (later entries win) * - Chord support with automatic timeout */ export function KeybindingSetup({ children }: Props): React.ReactNode { const { addNotification, removeNotification } = useNotifications() const handleWarnings = useCallback( (warnings: KeybindingWarning[], _isReload: boolean) => { const notificationKey = 'keybinding-config-warning' if (warnings.length === 0) { removeNotification(notificationKey) return } const errorCount = count(warnings, w => w.severity === 'error') const warnCount = count(warnings, w => w.severity === 'warning') let message: string if (errorCount > 0 && warnCount > 0) { message = `Found ${errorCount} keybinding ${plural(errorCount, 'error')} and ${warnCount} ${plural(warnCount, 'warning')}` } else if (errorCount > 0) { message = `Found ${errorCount} keybinding ${plural(errorCount, 'error')}` } else { message = `Found ${warnCount} keybinding ${plural(warnCount, 'warning')}` } message += ' ยท /doctor for details' addNotification({ key: notificationKey, text: message, color: errorCount > 0 ? 'error' : 'warning', priority: errorCount > 0 ? 'immediate' : 'high', timeoutMs: 60000, }) }, [addNotification, removeNotification], ) return ( {children} ) }