# How Kimi Code Lifecycle Hooks Work: Events, Execution, and Configuration

> Unlock Kimi Code's power. Learn how lifecycle hooks map session events to shell commands, control workflow with exit codes, and handle errors gracefully. Maximize your AI coding.

- Repository: [Moonshot AI/kimi-code](https://github.com/MoonshotAI/kimi-code)
- Tags: internals
- Published: 2026-07-22

---

**Kimi Code lifecycle hooks map session events like `SessionStart` or `PreToolUse` to shell commands that receive JSON payloads via stdin, execute with configurable timeouts, and use exit codes (0 to allow, 2 to block) to control workflow flow without stopping execution on errors.**

Kimi Code provides a generic hook system that allows you to intercept and react to key moments in an AI session's lifecycle. Implemented in [`packages/agent-core-v2/src/hooks.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/hooks.ts), these lifecycle hooks enable everything from audit logging to security blocking by running external scripts when specific events fire. Understanding how this system processes events and handles responses is essential for customizing your Kimi Code workflow safely.

## What Are Lifecycle Hooks in Kimi Code?

A **lifecycle hook** is a rule that binds a specific event—such as `SessionStart`, `UserPromptSubmit`, or `PreToolUse`—to a shell command. When the event occurs, Kimi Code executes the command asynchronously, passing contextual data as JSON.

The core implementation resides in [`packages/agent-core-v2/src/hooks.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/hooks.ts), which exports `OrderedHookSlot` and `createHooks` to manage hook registration and execution. Hooks are defined in your `~/.kimi-code/config.toml` under the `[[hooks]]` array, making them configurable without modifying the source code.

## How Lifecycle Hooks Execute

When an event triggers, Kimi Code follows a strict execution protocol:

1. **Payload delivery** – The CLI collects event-specific data (session ID, working directory, tool inputs) and writes it as JSON to the hook command's **stdin**.
2. **Timeout enforcement** – Commands run with a configurable timeout that defaults to **30 seconds**.
3. **Exit code interpretation**:
   - `0`: Allow the operation to proceed
   - `2`: Block the operation (for blockable events)
   - Any other non-zero: Allow (fail-open behavior)
4. **Stdout parsing** – The CLI can read structured JSON responses from stdout to modify behavior.

Because the system is **fail-open**, timeouts or errors in hook scripts never halt the main Kimi Code session; they are logged and the workflow continues. This design prioritizes availability while still permitting security-oriented interception.

## Available Lifecycle Events

Kimi Code supports distinct events categorized by whether they can block operations or only observe them:

- **`UserPromptSubmit`** – Fires when text is entered. **Blockable**; use to amend or filter user input before the model processes it.
- **`PreToolUse`** – Fires before a tool executes. **Blockable**; use to validate dangerous operations like shell commands.
- **`Stop`** – Intercepts the model's stop signal. **Blockable**; allows injection of follow-up messages.
- **`SessionStart`** / **`SessionEnd`** – Fires on startup, resume, or exit. Observation-only; use for logging and resource initialization.
- **`PostToolUse`** / **`PostToolUseFailure`** – Fires after tool execution. Observation-only; use for telemetry and notifications.

Additional events like `Notification` (for background task state changes) are documented in [`docs/en/customization/hooks.md`](https://github.com/MoonshotAI/kimi-code/blob/main/docs/en/customization/hooks.md).

## Configuring Lifecycle Hooks

Define hooks in `~/.kimi-code/config.toml` using TOML array syntax. Each hook requires an `event`, optional `matcher` for filtering, `command` to execute, and `timeout` in seconds.

```toml
[[hooks]]
event   = "SessionStart"
matcher = "startup"
command = "node ~/.kimi-code/hooks/log-session.mjs"
timeout = 30

```

The `matcher` field filters events when the event type supports it (e.g., matching specific tool names for `PreToolUse`). Omitting it catches all instances of that event.

## Practical Lifecycle Hook Examples

### Sending Desktop Notifications on Task Completion

Fire a macOS notification when background tasks complete using the `Notification` event:

```toml
[[hooks]]
event   = "Notification"
matcher = "task\\.completed"
command = "terminal-notifier -title Kimi -message 'Task done'"
timeout = 30

```

### Blocking Dangerous Shell Commands with PreToolUse

Create a security gate that prevents `rm -rf` execution by exiting with code `2`:

```toml
[[hooks]]
event   = "PreToolUse"
matcher = "Bash"
command = "node ~/.kimi-code/hooks/block-dangerous-bash.mjs"
timeout = 5

```

```javascript
// block-dangerous-bash.mjs
let input = '';
process.stdin.on('data', chunk => (input += chunk));
process.stdin.on('end', () => {
  const payload = JSON.parse(input);
  const cmd = payload.tool_input?.command ?? '';
  
  if (cmd.includes('rm -rf')) {
    console.error('Dangerous command detected, blocked');
    process.exit(2);  // Block operation
  }
  process.exit(0);      // Allow operation
});

```

### Logging Session Start and End Events

The test suite in [`packages/agent-core/test/session/lifecycle-hooks.test.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/test/session/lifecycle-hooks.test.ts) demonstrates logging by capturing JSON payloads:

```typescript
// Helper script that records payloads to a file
const scriptPath = join(dir, 'record-hook.cjs');
await writeFile(
  scriptPath,
  [
    "const { appendFileSync } = require('node:fs');",
    "let input = '';",
    "process.stdin.on('data', chunk => { input += chunk; });",
    "process.stdin.on('end', () => {",
    "  appendFileSync(process.argv[2], input.trim() + '\\n');",
    "});",
  ].join('\n'),
  'utf-8',
);

// Session configuration with hooks
const session = new Session({
  hooks: [
    { event: 'SessionStart', matcher: 'startup', command: scriptPath, timeout: 5 },
    { event: 'SessionEnd',   matcher: 'exit',    command: scriptPath, timeout: 5 },
  ],
});

```

The resulting JSON payload contains:

```json
{
  "hook_event_name": "SessionStart",
  "session_id": "session-123",
  "cwd": "/workspace",
  "source": "startup"
}

```

## When to Use Lifecycle Hooks

Choose hooks based on your operational requirements:

- **Audit and logging** – Use `SessionStart` and `PostToolUse` to write immutable logs of all AI activity.
- **Security validation** – Use `PreToolUse` with exit code `2` to block dangerous operations before execution.
- **Context enrichment** – Use `UserPromptSubmit` to inject Git branch names or environment metadata into prompts.
- **System integration** – Use `Notification` to trigger external alerts when long-running tasks complete.
- **Resource management** – Use `SessionEnd` to clean up temporary files or terminate background processes.

## Summary

- **Lifecycle hooks** in Kimi Code connect session events to shell commands via [`packages/agent-core-v2/src/hooks.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/hooks.ts).
- Commands receive JSON payloads on **stdin** and communicate decisions through **exit codes** (`0` allow, `2` block).
- The system is **fail-open**; script failures or timeouts never crash the main session.
- Configure hooks in `~/.kimi-code/config.toml` using the `[[hooks]]` array syntax.
- **Blockable events** (`PreToolUse`, `UserPromptSubmit`) can halt operations, while observation events provide telemetry without interrupting flow.

## Frequently Asked Questions

### What happens if a lifecycle hook script crashes or times out?

If a hook exits with a non-zero code other than `2`, or exceeds its configured timeout (default 30 seconds), Kimi Code logs the failure and allows the operation to proceed. This **fail-open** design ensures that hook errors never disrupt your coding session.

### Can I modify the JSON payload before it reaches the model?

Yes. The `UserPromptSubmit` event allows you to intercept user input via stdin, and you can write a modified JSON object to stdout. However, the specific implementation details for payload mutation depend on the event type; blocking events typically check exit codes while transformation events parse stdout.

### Where are lifecycle hooks configured?

Hooks are defined in your user configuration file at `~/.kimi-code/config.toml` under the `[[hooks]]` TOML array. This location keeps user customizations separate from the Kimi Code source code in [`packages/agent-core-v2/src/hooks.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/hooks.ts).

### Which events can actually block operations versus just observe them?

According to the source code documentation in [`docs/en/customization/hooks.md`](https://github.com/MoonshotAI/kimi-code/blob/main/docs/en/customization/hooks.md), **blockable** events include `UserPromptSubmit`, `PreToolUse`, and `Stop`. Events like `SessionStart`, `SessionEnd`, `PostToolUse`, and `PostToolUseFailure` are observation-only and cannot halt execution.