Hooks
With hooks, you can insert custom logic into key lifecycle nodes of CodeArts Agent IDE and extensions to extend functionality without modifying any existing code.
Unlike prompts that rely on model understanding, hook operations yield deterministic outcomes. Once an event is triggered, the designated script executes reliably and consistently, without being affected by model understanding discrepancies.
Constraints
| Category | Description |
|---|---|
| Function | Hook scripts currently do not support real-time loading; a reload is required before they can be used. |
| Language | Hook scripts support only JavaScript and TypeScript. |
| External dependencies | If external dependency packages are used, you must create a package.json file in the configuration directory where the hook is located and declare the required dependencies. |
Supported Hook Events
| Event Category | Event Name | Trigger Time | Blockable | Typical Application Scenario | Description |
|---|---|---|---|---|---|
| Chat message | chat.message | Triggered after a user sends a message but before it enters the processing workflow. | Yes | Chat message processing | Automatically triggered when a new message arrives. Supports editing message content and parts. |
| Chat parameter | chat.params | Triggered before each LLM call. | Yes | Chat parameter modification | Supports dynamically adjusting LLM inference parameters (including temperature, topP, topK, etc.) to optimize model output as needed. |
| Chat request header | chat.headers | Triggered before each LLM call. | Yes | Chat request header modification | Supports customizing and modifying HTTP request header fields to adapt to complex requirements such as network proxies and interface authentication. |
| Chat response | chat.response | Triggered after the LLM returns a response. | No | Chat response logging | Automatically captures core metrics of the model response, such as tokens, cost, and duration, achieving precise billing statistics, efficient troubleshooting, and complete log retention. |
| Chat error | chat.error | Triggered when an error occurs during an LLM call. | No | Chat error logging | Logs error details when an LLM call fails. |
| Chat compression | chat.compression | Triggered during context compression. | No | Chat compression logging | Logs the token counts before and after context compression to assist in storage and performance tuning. |
| Chat end | chat.finished | Triggered when a chat ends. | No | Chat end logging | Logs the chat end event, including the token consumption and running information of the current run. |
| User approval | user.approval | Triggered when a user confirmation or approval action is required. | Yes | User approval logging | Intercepts high-risk operations and initiates manual confirmation and approval, controlling the execution permissions of sensitive operations. |
| Turn end | turn.end | Triggered when each chat turn ends. | No | Turn end logging | Logs the end of each chat turn, containing key information such as processing duration and termination reasons. |
| Command execution | command.execute.before | Triggered before a command is executed. | Yes | Command preprocessing | Supports custom configuration of parts to achieve command preprocessing and flexible adaptation. |
| Tool execution | tool.execute.before | Triggered before a tool is executed. | Yes | Tool execution pre-parameter adjustment | Supports customizing and modifying args before tool execution to achieve validation, dynamic rewriting, and service adaptation. |
| tool.execute.after | Triggered after a tool is executed. | Yes | Tool execution post-result processing | Supports customizing and modifying returned results, including the title, output, and metadata fields. | |
| Tool definition | tool.definition | Triggered before a tool definition is sent to the LLM. | Yes | Tool definition modification | Supports customizing configuration descriptions and parameters before tool definitions are pushed to the model, ensuring precise adaptation to service scenarios. |
| Shell environment | shell.env | Triggered when fetching Shell environment variables. | Yes | Shell environment variable configuration and management | Supports adding or modifying environment variables when Shell environment variables are fetched. |
| Permission request | permission.ask | Triggered when permission verification is required. | Yes | Permission request processing | Processes permission validation requests and supports configuring three strategies: allow, deny, and ask. |
| Message conversion | experimental.chat.messages.transform | Triggered before the message list is sent to the LLM. | Yes | Message conversion | Supports preprocessing the chat list before it is reported to the model. |
| System message conversion | experimental.chat.system.transform | Triggered before the system prompt is sent. | Yes | System message conversion | Supports optimizing prompt content before the prompt is sent. |
| Session compression | experimental.session.compacting | Triggered before context compression starts. | Yes | Chat compression | Supports customizing the compression prompt before context compression is executed. |
| Text completion | experimental.text.complete | Triggered when text completion finishes. | Yes | Text completion result customization | Supports modifying the output content after text completion is completed. |
| Configuration loading | config | Triggered when application startup configurations are loaded. | No | Configuration loading | Performs configuration initialization and dynamic parameter injection and is triggered during the loading of custom configurations. |
| Common event | event | Triggered when all Bus events are subscribed to. | No | Event processing | Processes common events. |
Storage Paths for Plug-ins and Dependency Files
A plug-in is a JavaScript/TypeScript module that operates by exporting plug-in functions. Each function receives a context object and returns the corresponding hook object. If external packages are required within a plug-in file, you must create a package.json file in the configuration directory and configure the necessary dependencies. CodeArts Agent automatically installs these dependencies when it starts.
| Plug-in Type | Plug-in File Storage Path | Plug-in Dependency Storage Path | Description |
|---|---|---|---|
| Project | Root directory of the current project: ./codeartsdoer/plugin or ./codeartsdoer/plugins | Root directory of the current project: ./codeartsdoer/ | Valid only for the current project. |
| User | Local %USERPROFILE%/.codeartsdoer/plugin or %USERPROFILE%/.codeartsdoer/plugins | Local %USERPROFILE%/.codeartsdoer/ | Valid for all projects of the current user. |
Quick Start
The following example demonstrates how to filter sensitive information, such as passwords and keys, from user inputs to effectively prevent data leaks.
- Create a directory for storing the plug-in file.
Create a directory named plugin in the project root directory ./ .codeartsdoer.
Figure 1 Creating the plugin directory
- Create a script.
In the plugin directory, create a new file named sensitiveInfoFilteringPlugin.ts, write the hook logic code in the file, and save the file.
// Import the plug-in type to define the plug-in. import type { Plugin } from "@opencode-ai/plugin" // Export the plugin implementation. Plugin is an asynchronous function that receives plugin input parameters and returns a hook object. export const SensitiveInfoFilteringPlugin: Plugin = async ({}) => { // Return a hooks object containing various hook functions. return { // Listen to the hook after the tool is executed. This function is triggered after the tool execution is complete. "tool.execute.after": async ( // Input parameters include the tool name, session ID, call ID, inference ID, and other information. input: { tool: string; sessionID: string; callID: string; args: any }, // Output parameters include the title, output, and metadata of the tool execution result. output: { title: string output: string metadata: any }, ) => { // Check if the operation is to read a file (tool name is "read") and the output content exists. if (input.tool === "read" && output.output) { // Sensitive information matching patterns (supporting JSON and other common formats). // Matches "password": "value" or password: value. // First regex: matches JSON format, such as "password": "***". // Second regex: matches common key-value formats, such as password=*** orpassword:***. const sensitivePatterns = [ // Matches sensitive fields in JSON format: double-quoted key + colon + double-quoted value. new RegExp(`"password|passwd|pwd|api[_-]?key|secret|token|key|password"\\s*:\\s*"([^"]+)"`, "g"), // Matches sensitive fields in common format: key + colon or equal sign + unquoted value. new RegExp(`(password|passwd|pwd|api[_-]?key|secret|token)\\s*[:=]\\s*([^"'\\s\\\\]+)`, "gi"), ] // Assign the tool output content to the local variable content for subsequent processing. let content = output.output // Traverse all sensitive information matching patterns and replace them one by one. for (const pattern of sensitivePatterns) { // Use the replace method for substitution, passing a callback function to handle match results. // match: the fully matched string. // key: capture group 1, i.e., the sensitive field name (password, api_key, etc.) // value: capture group 2, i.e., the actual content of the sensitive field (e.g., actual password or key) content = content.replace(pattern, (match, key, value) => { // If sensitive information is matched, replace the actual value with the [Sensitive Info] placeholder. return match.replace(value, "[Sensitive Info]") }) } // Update the output field in the output object to write back the filtered content. output.output = content } } } } - Restart the IDE.
In the upper left corner of CodeArts Agent IDE, click File and choose Restart IDE. Because the current hook script does not support real-time loading, you need to restart the IDE for the script to take effect.
To ensure that the script takes effect, it is advised to terminate all Bun processes in the task manager to completely clear any remaining instances.
- Verify the effect.
After you enter a prompt in the input box, the sensitive information in the results returned by the model will be automatically masked.
Creating Hooks
- Select an event.
Select an event name in Supported Hook Events based on service requirements.
- Compile the hook script.
- Create a plug-in file.
Create a .ts or .js file in the directory described in Storage Paths for Plug-ins and Dependency Files.
- Compile the hook logic.
In Hook Event Reference, locate // Hook implementations go here, and write your specific hook implementation code there based on your actual service requirements.
- Create a plug-in file.
- (Optional) Configure dependencies. If external packages are required within a plug-in file, you must create a package.json file in the configuration directory described in Storage Paths for Plug-ins and Dependency Files and configure the necessary dependencies.
{ "dependencies": { "Dependency package name 1": "Version number", "Dependency package name 2": "Version number" } }The following is an example of the package.json file:
{ "dependencies": { "@opencode-ai/plugin": "*", "@babel/core": "7.29.0", "@langfuse/otel": "4.5.1" } } - Restart the IDE to verify the effect.
Hook Event Reference
Examples of supported hook events are provided below. Write your specific implementation logic at the // Hook implementations go here comment. Once the code is written, it can be used directly.
Usage Example
Taking "displaying a pop-up window to prompt for high-risk operations before deleting a file" as an example, this section provides a detailed guide on how to use a hook. This example uses a project-level configuration within the plug-in directory.
- Select an event based on the description in Supported Hook Events.
Deletions of files will call a tool, usually the deleteFile tool. Because the pop-up window needs to appear before the file is deleted, you should select the tool.execute.before event here.
- Compile the hook script.
- Create a directory named plugin in the project root directory ./ .codeartsdoer.
- In the plugin directory, create a file named deleteFileHintPlugin.ts.
- Compile the script and save the file.
// Import the type definition of the OpenCode plug-in. import type {Plugin} from "@opencode-ai/plugin"; // Import the Node.js child process module to execute system commands. import { exec } from "child_process"; // Import the promisify function from the util module to convert callback functions into Promises. import { promisify } from "util"; // Convert the exec callback function into a Promise-based asynchronous function. const execAsync = promisify(exec); // Define and export the plug-in, accepting a client parameter to interact with OpenCode. export const DeleteFileHintPlugin: Plugin = async ({ client }) => { // Return the hook collection of the plug-in. return { // Listen for the hook for tool.execute.before. "tool.execute.before": async ( // Input parameters: tool name, session ID, call ID, and inference ID. input: { tool: string; sessionID: string; callID: string; inferenceID?: string }, // Output parameters: parameters for tool calling. output: { args: any } ) => { // Check if the operation is to delete a file. if (input.tool === "deleteFile") { // Define the message content for the warning pop-up window. const message = `Deleting files is a high-risk operation. Exercise caution when performing this operation.` // Execute commands based on the operating system. if (process.platform === "win32") { // Windows: Use PowerShell to call the system MessageBox. const cmd = `powershell -NoProfile -Command "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show('${message}', 'Warning', 'OK', 'Warning')"` await execAsync(cmd) } else if (process.platform === "darwin") { // macOS: Use osascript to call the system pop-up window. const cmd = `osascript -e 'display alert "Warning" message "${message}"'` await execAsync(cmd) } else if (process.platform === "linux") { // Linux: Use notify-send to send a desktop notification. const cmd = `notify-send "Warning" "${message}"` await execAsync(cmd) } } } } }
- Restart the IDE to verify the effect.
- In the upper left corner of CodeArts Agent IDE, click File and choose Restart IDE. Because the current hook script does not support real-time loading, you need to restart the IDE for the script to take effect.
To ensure that the script takes effect, it is advised to terminate all Bun processes in the task manager to completely clear any remaining instances.
- Enter Delete file *** in the text box. A warning window is displayed on the client.
*** indicates the name of the file to be deleted.
- In the upper left corner of CodeArts Agent IDE, click File and choose Restart IDE. Because the current hook script does not support real-time loading, you need to restart the IDE for the script to take effect.
Feedback
Was this page helpful?
Provide feedbackThank you very much for your feedback. We will continue working to improve the documentation.See the reply and handling status in My Cloud VOC.
For any further questions, feel free to contact us through the chatbot.
Chatbot