Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .roo/hooks/example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: "1"
hooks:
PreToolUse:
- id: edit-verification
matcher: "edit"
enabled: true
command: 'echo "Edit verification triggered for $ROO_TOOL_NAME"'
timeout: 5
1 change: 1 addition & 0 deletions packages/types/src/global-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ export const globalSettingsSchema = z.object({

mcpEnabled: z.boolean().optional(),
enableMcpServerCreation: z.boolean().optional(),
hooksEnabled: z.boolean().optional(),

mode: z.string().optional(),
modeApiConfigs: z.record(z.string(), z.string()).optional(),
Expand Down
2 changes: 2 additions & 0 deletions packages/types/src/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ export function isNonBlockingAsk(ask: ClineAsk): ask is NonBlockingAsk {
* - `condense_context`: Context condensation/summarization has started
* - `condense_context_error`: Error occurred during context condensation
* - `codebase_search_result`: Results from searching the codebase
* - `hook_triggered`: Notification that a hook has been executed
*/
export const clineSays = [
"error",
Expand Down Expand Up @@ -179,6 +180,7 @@ export const clineSays = [
"condense_context_error",
"sliding_window_truncation",
"codebase_search_result",
"hook_triggered",
"user_edit_todos",
] as const

Expand Down
109 changes: 109 additions & 0 deletions packages/types/src/vscode-extension-host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export interface ExtensionMessage {
| "customToolsResult"
| "modes"
| "taskWithAggregatedCosts"
| "hookExecutionStatus"
text?: string
payload?: any // eslint-disable-line @typescript-eslint/no-explicit-any
checkpointWarning?: {
Expand Down Expand Up @@ -190,6 +191,98 @@ export interface ExtensionMessage {
childrenCost: number
}
historyItem?: HistoryItem
hookExecutionStatus?: HookExecutionStatusPayload
}

/**
* HookExecutionStatusPayload
* Sent when hook execution starts, completes, or fails.
*/
export interface HookExecutionStatusPayload {
/** Status of the hook execution */
status: "running" | "completed" | "failed" | "blocked"
/** Event type that triggered the hook */
event: string
/** Tool name if this is a tool-related event */
toolName?: string
/** Hook ID being executed */
hookId?: string
/** Duration in milliseconds (only for completed/failed) */
duration?: number
/** Error message if failed */
error?: string
/** Block message if hook blocked the operation */
blockMessage?: string
/** Whether tool input was modified */
modified?: boolean
}

/**
* Serializable hook information for webview display.
* This is a subset of ResolvedHook that can be safely serialized to JSON.
*/
export interface HookInfo {
/** Unique identifier for this hook */
id: string
/** File path where this hook was defined (if known) */
filePath?: string
/** The event type this hook is registered for */
event: string
/** Tool name filter (regex/glob pattern) */
matcher?: string
/** Preview of the command (truncated for display) */
commandPreview: string
/** Whether this hook is enabled */
enabled: boolean
/** Source of this hook configuration */
source: "project" | "mode" | "global"
/** Timeout in seconds */
timeout: number
/** Override shell if specified */
shell?: string
/** Human-readable description */
description?: string
}

/**
* Serializable hook execution record for webview display.
*/
export interface HookExecutionRecord {
/** When the hook was executed (ISO string) */
timestamp: string
/** The hook ID that was executed */
hookId: string
/** The event that triggered execution */
event: string
/** Tool name if this was a tool-related event */
toolName?: string
/** Exit code from the process */
exitCode: number | null
/** Execution duration in milliseconds */
duration: number
/** Whether the hook timed out */
timedOut: boolean
/** Whether the hook blocked execution */
blocked: boolean
/** Error message if the hook failed */
error?: string
/** Block message if the hook blocked */
blockMessage?: string
}

/**
* Hooks state for webview display.
* Contains all information needed to render the Hooks settings tab.
*/
export interface HooksState {
/** Array of resolved hooks with display information */
enabledHooks: HookInfo[]
/** Recent execution history (last N records) */
executionHistory: HookExecutionRecord[]
/** Whether project-level hooks are present (for security warnings) */
hasProjectHooks: boolean
/** When the config snapshot was last loaded (ISO string) */
snapshotTimestamp?: string
}

export type ExtensionState = Pick<
Expand Down Expand Up @@ -289,6 +382,7 @@ export type ExtensionState = Pick<

mcpEnabled: boolean
enableMcpServerCreation: boolean
hooksEnabled: boolean

mode: string
customModes: ModeConfig[]
Expand Down Expand Up @@ -335,6 +429,9 @@ export type ExtensionState = Pick<
claudeCodeIsAuthenticated?: boolean
openAiCodexIsAuthenticated?: boolean
debug?: boolean

/** Hooks configuration and execution state for the Hooks settings tab */
hooks?: HooksState
}

export interface Command {
Expand Down Expand Up @@ -521,6 +618,13 @@ export interface WebviewMessage {
| "requestModes"
| "switchMode"
| "debugSetting"
| "hooksReloadConfig"
| "hooksSetEnabled"
| "hooksSetAllEnabled"
| "hooksOpenConfigFolder"
| "hooksDeleteHook"
| "hooksOpenHookFile"
| "hooksCreateNew"
text?: string
editedMessageContent?: string
tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "cloud"
Expand Down Expand Up @@ -576,6 +680,11 @@ export interface WebviewMessage {
list?: string[] // For dismissedUpsells response
organizationId?: string | null // For organization switching
useProviderSignup?: boolean // For rooCloudSignIn to use provider signup flow
hookId?: string // For hooksSetEnabled, hooksDeleteHook
hookEnabled?: boolean // For hooksSetEnabled
hooksEnabled?: boolean // For hooksSetAllEnabled
hooksSource?: "global" | "project" | "mode" // For hooksOpenConfigFolder, hooksDeleteHook
filePath?: string // For hooksOpenHookFile
codeIndexSettings?: {
// Global state settings
codebaseIndexEnabled: boolean
Expand Down
74 changes: 67 additions & 7 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading