init claude-code
This commit is contained in:
@@ -0,0 +1,236 @@
|
||||
/**
|
||||
* Zod schema for keybindings.json configuration.
|
||||
* Used for validation and JSON schema generation.
|
||||
*/
|
||||
|
||||
import { z } from 'zod/v4'
|
||||
import { lazySchema } from '../utils/lazySchema.js'
|
||||
|
||||
/**
|
||||
* Valid context names where keybindings can be applied.
|
||||
*/
|
||||
export const KEYBINDING_CONTEXTS = [
|
||||
'Global',
|
||||
'Chat',
|
||||
'Autocomplete',
|
||||
'Confirmation',
|
||||
'Help',
|
||||
'Transcript',
|
||||
'HistorySearch',
|
||||
'Task',
|
||||
'ThemePicker',
|
||||
'Settings',
|
||||
'Tabs',
|
||||
// New contexts for keybindings migration
|
||||
'Attachments',
|
||||
'Footer',
|
||||
'MessageSelector',
|
||||
'DiffDialog',
|
||||
'ModelPicker',
|
||||
'Select',
|
||||
'Plugin',
|
||||
] as const
|
||||
|
||||
/**
|
||||
* Human-readable descriptions for each keybinding context.
|
||||
*/
|
||||
export const KEYBINDING_CONTEXT_DESCRIPTIONS: Record<
|
||||
(typeof KEYBINDING_CONTEXTS)[number],
|
||||
string
|
||||
> = {
|
||||
Global: 'Active everywhere, regardless of focus',
|
||||
Chat: 'When the chat input is focused',
|
||||
Autocomplete: 'When autocomplete menu is visible',
|
||||
Confirmation: 'When a confirmation/permission dialog is shown',
|
||||
Help: 'When the help overlay is open',
|
||||
Transcript: 'When viewing the transcript',
|
||||
HistorySearch: 'When searching command history (ctrl+r)',
|
||||
Task: 'When a task/agent is running in the foreground',
|
||||
ThemePicker: 'When the theme picker is open',
|
||||
Settings: 'When the settings menu is open',
|
||||
Tabs: 'When tab navigation is active',
|
||||
Attachments: 'When navigating image attachments in a select dialog',
|
||||
Footer: 'When footer indicators are focused',
|
||||
MessageSelector: 'When the message selector (rewind) is open',
|
||||
DiffDialog: 'When the diff dialog is open',
|
||||
ModelPicker: 'When the model picker is open',
|
||||
Select: 'When a select/list component is focused',
|
||||
Plugin: 'When the plugin dialog is open',
|
||||
}
|
||||
|
||||
/**
|
||||
* All valid keybinding action identifiers.
|
||||
*/
|
||||
export const KEYBINDING_ACTIONS = [
|
||||
// App-level actions (Global context)
|
||||
'app:interrupt',
|
||||
'app:exit',
|
||||
'app:toggleTodos',
|
||||
'app:toggleTranscript',
|
||||
'app:toggleBrief',
|
||||
'app:toggleTeammatePreview',
|
||||
'app:toggleTerminal',
|
||||
'app:redraw',
|
||||
'app:globalSearch',
|
||||
'app:quickOpen',
|
||||
// History navigation
|
||||
'history:search',
|
||||
'history:previous',
|
||||
'history:next',
|
||||
// Chat input actions
|
||||
'chat:cancel',
|
||||
'chat:killAgents',
|
||||
'chat:cycleMode',
|
||||
'chat:modelPicker',
|
||||
'chat:fastMode',
|
||||
'chat:thinkingToggle',
|
||||
'chat:submit',
|
||||
'chat:newline',
|
||||
'chat:undo',
|
||||
'chat:externalEditor',
|
||||
'chat:stash',
|
||||
'chat:imagePaste',
|
||||
'chat:messageActions',
|
||||
// Autocomplete menu actions
|
||||
'autocomplete:accept',
|
||||
'autocomplete:dismiss',
|
||||
'autocomplete:previous',
|
||||
'autocomplete:next',
|
||||
// Confirmation dialog actions
|
||||
'confirm:yes',
|
||||
'confirm:no',
|
||||
'confirm:previous',
|
||||
'confirm:next',
|
||||
'confirm:nextField',
|
||||
'confirm:previousField',
|
||||
'confirm:cycleMode',
|
||||
'confirm:toggle',
|
||||
'confirm:toggleExplanation',
|
||||
// Tabs navigation actions
|
||||
'tabs:next',
|
||||
'tabs:previous',
|
||||
// Transcript viewer actions
|
||||
'transcript:toggleShowAll',
|
||||
'transcript:exit',
|
||||
// History search actions
|
||||
'historySearch:next',
|
||||
'historySearch:accept',
|
||||
'historySearch:cancel',
|
||||
'historySearch:execute',
|
||||
// Task/agent actions
|
||||
'task:background',
|
||||
// Theme picker actions
|
||||
'theme:toggleSyntaxHighlighting',
|
||||
// Help menu actions
|
||||
'help:dismiss',
|
||||
// Attachment navigation (select dialog image attachments)
|
||||
'attachments:next',
|
||||
'attachments:previous',
|
||||
'attachments:remove',
|
||||
'attachments:exit',
|
||||
// Footer indicator actions
|
||||
'footer:up',
|
||||
'footer:down',
|
||||
'footer:next',
|
||||
'footer:previous',
|
||||
'footer:openSelected',
|
||||
'footer:clearSelection',
|
||||
'footer:close',
|
||||
// Message selector (rewind) actions
|
||||
'messageSelector:up',
|
||||
'messageSelector:down',
|
||||
'messageSelector:top',
|
||||
'messageSelector:bottom',
|
||||
'messageSelector:select',
|
||||
// Diff dialog actions
|
||||
'diff:dismiss',
|
||||
'diff:previousSource',
|
||||
'diff:nextSource',
|
||||
'diff:back',
|
||||
'diff:viewDetails',
|
||||
'diff:previousFile',
|
||||
'diff:nextFile',
|
||||
// Model picker actions (ant-only)
|
||||
'modelPicker:decreaseEffort',
|
||||
'modelPicker:increaseEffort',
|
||||
// Select component actions (distinct from confirm: to avoid collisions)
|
||||
'select:next',
|
||||
'select:previous',
|
||||
'select:accept',
|
||||
'select:cancel',
|
||||
// Plugin dialog actions
|
||||
'plugin:toggle',
|
||||
'plugin:install',
|
||||
// Permission dialog actions
|
||||
'permission:toggleDebug',
|
||||
// Settings config panel actions
|
||||
'settings:search',
|
||||
'settings:retry',
|
||||
'settings:close',
|
||||
// Voice actions
|
||||
'voice:pushToTalk',
|
||||
] as const
|
||||
|
||||
/**
|
||||
* Schema for a single keybinding block.
|
||||
*/
|
||||
export const KeybindingBlockSchema = lazySchema(() =>
|
||||
z
|
||||
.object({
|
||||
context: z
|
||||
.enum(KEYBINDING_CONTEXTS)
|
||||
.describe(
|
||||
'UI context where these bindings apply. Global bindings work everywhere.',
|
||||
),
|
||||
bindings: z
|
||||
.record(
|
||||
z
|
||||
.string()
|
||||
.describe('Keystroke pattern (e.g., "ctrl+k", "shift+tab")'),
|
||||
z
|
||||
.union([
|
||||
z.enum(KEYBINDING_ACTIONS),
|
||||
z
|
||||
.string()
|
||||
.regex(/^command:[a-zA-Z0-9:\-_]+$/)
|
||||
.describe(
|
||||
'Command binding (e.g., "command:help", "command:compact"). Executes the slash command as if typed.',
|
||||
),
|
||||
z.null().describe('Set to null to unbind a default shortcut'),
|
||||
])
|
||||
.describe(
|
||||
'Action to trigger, command to invoke, or null to unbind',
|
||||
),
|
||||
)
|
||||
.describe('Map of keystroke patterns to actions'),
|
||||
})
|
||||
.describe('A block of keybindings for a specific context'),
|
||||
)
|
||||
|
||||
/**
|
||||
* Schema for the entire keybindings.json file.
|
||||
* Uses object wrapper format with optional $schema and $docs metadata.
|
||||
*/
|
||||
export const KeybindingsSchema = lazySchema(() =>
|
||||
z
|
||||
.object({
|
||||
$schema: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('JSON Schema URL for editor validation'),
|
||||
$docs: z.string().optional().describe('Documentation URL'),
|
||||
bindings: z
|
||||
.array(KeybindingBlockSchema())
|
||||
.describe('Array of keybinding blocks by context'),
|
||||
})
|
||||
.describe(
|
||||
'Claude Code keybindings configuration. Customize keyboard shortcuts by context.',
|
||||
),
|
||||
)
|
||||
|
||||
/**
|
||||
* TypeScript types derived from the schema.
|
||||
*/
|
||||
export type KeybindingsSchemaType = z.infer<
|
||||
ReturnType<typeof KeybindingsSchema>
|
||||
>
|
||||
Reference in New Issue
Block a user