Updated on 2026-07-29 GMT+08:00

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

Table 1 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

Table 2 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.

Table 3 Plug-in file loading paths

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.

  1. 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

  2. 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
          }
        }
      }
    }

  3. 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.

  4. 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

  1. Select an event.

    Select an event name in Supported Hook Events based on service requirements.

  2. Compile the hook script.

    1. Create a plug-in file.

      Create a .ts or .js file in the directory described in Storage Paths for Plug-ins and Dependency Files.

    2. 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.

  3. (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"
      }
    }

  4. 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.

  1. 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.

  2. Compile the hook script.

    1. Create a directory named plugin in the project root directory ./ .codeartsdoer.
    2. In the plugin directory, create a file named deleteFileHintPlugin.ts.
    3. 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)
              }
            }
          }
        }
      }

  3. Restart the IDE to verify the effect.

    1. 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.

    2. Enter Delete file *** in the text box. A warning window is displayed on the client.

      *** indicates the name of the file to be deleted.