# Understanding Kimi Code Lifecycle Hooks: Event-Driven Automation and Security

> Learn how Kimi Code lifecycle hooks automate and secure AI interactions. Trigger shell commands with JSON payloads at key session events for auditing and modification.

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

---

**Kimi Code lifecycle hooks are asynchronous shell command triggers configured in `~/.kimi-code/config.toml` that execute at specific session events—passing JSON payloads via stdin and using exit codes to allow (0), block (2), or ignore failures—enabling users to audit, intercept, or modify AI interactions without modifying the core codebase.**

The MoonshotAI/kimi-code repository provides a generic hook system in [`packages/agent-core-v2/src/hooks.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/hooks.ts) that exposes session lifecycle events to external scripts. These **Kimi Code lifecycle hooks** bridge the CLI's internal state with user-defined automation, supporting everything from security policy enforcement to desktop notifications through a fail-open architecture that prioritizes workflow continuity.

## Architecture of the Kimi Code Hook System

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 defines `OrderedHookSlot` and the `createHooks` factory. When an event fires, the CLI:

1. **Collects payload data** (session ID, cwd, event-specific fields) as JSON
2. **Writes the payload to stdin** of the configured command
3. **Executes with a timeout** (default 30 seconds, configurable per hook)
4. **Interprets exit codes** using fail-open semantics: `0` allows continuation, `2` explicitly blocks the operation, and any other non-zero exit allows continuation but logs the error

This **fail-open** design ensures that hook failures or timeouts never interrupt the main session flow, making the system safe for production observability while still permitting strict security controls when scripts intentionally exit with code `2`.

## Available Lifecycle Events and When to Use Them

The CLI exposes distinct event types as documented in [`docs/en/customization/hooks.md`](https://github.com/MoonshotAI/kimi-code/blob/main/docs/en/customization/hooks.md). Each event carries a specific payload structure and blocking capability:

### Session Management Events

- **SessionStart**: Fires during `startup` or `resume`. Non-blocking. Typical for initializing resources or logging session creation with metadata including `session_id` and `cwd`.
- **SessionEnd**: Fires on `exit`. Non-blocking. Used for cleanup scripts, flushing logs, or terminating background processes.

### User Interaction Hooks

- **UserPromptSubmit**: Intercepts text entered by the user before model processing. **Blockable** (exit code 2). Ideal for input validation, auto-appending Git branch context, or preventing prompt injection attacks.

### Tool Execution Hooks

- **PreToolUse**: Executes before any tool invocation. **Blockable**. Receives `tool_name` and `tool_input` in the JSON payload. Critical for security policies that prevent dangerous shell commands.
- **PostToolUse**: Fires after successful tool execution. Non-blocking. Used for success logging, metrics collection, or firing notification events.
- **PostToolUseFailure**: Captures tool execution errors. Non-blocking. Enables failure alerting and debugging workflows.

### Control Flow Interception

- **Stop**: Intercepts the model's stop signal. **Blockable**. Allows injection of follow-up messages or preventing session termination.

## Configuring Hooks in config.toml

Hooks are defined in the TOML array `[[hooks]]` within `~/.kimi-code/config.toml`. Each entry requires:

- `event`: The lifecycle event name (e.g., `"PreToolUse"`)
- `matcher`: Optional filter (e.g., tool name `"Bash"` or regex pattern like `"task\\.completed"`)
- `command`: Shell command or script path to execute
- `timeout`: Execution limit in seconds (optional, defaults to 30)

## Practical Implementation Examples

### Desktop Notifications on Task Completion

Configure a non-blocking notification when background tasks finish:

```toml

# ~/.kimi-code/config.toml

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

```

### Security: Blocking Dangerous Bash Commands

Implement a safety guard using `PreToolUse` with a Node.js validator:

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

```

The corresponding script reads the JSON payload from stdin:

```javascript
// ~/.kimi-code/hooks/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);  // Exit 2 blocks execution
  }
  process.exit(0);      // Exit 0 allows execution
});

```

### Session Audit Logging

Capture session boundaries for compliance tracking using the test suite pattern from [`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):

```typescript
// Script: record-hook.cjs
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`);
});

```

Configure the hooks to log to a specific file:

```toml
[[hooks]]
event   = "SessionStart"
matcher = "startup"
command = "node ~/.kimi-code/hooks/record-hook.cjs ~/logs/kimi-sessions.jsonl"
timeout = 5

[[hooks]]
event   = "SessionEnd"
matcher = "exit"
command = "node ~/.kimi-code/hooks/record-hook.cjs ~/logs/kimi-sessions.jsonl"
timeout = 5

```

The resulting JSON Lines file contains structured payloads:

```json
{"hook_event_name": "SessionStart", "session_id": "session-123", "cwd": "/work", "source": "startup"}
{"hook_event_name": "SessionEnd", "session_id": "session-123", "cwd": "/work", "reason": "exit"}

```

## Summary

- **Kimi Code lifecycle hooks** execute shell commands asynchronously at specific session events defined in [`packages/agent-core-v2/src/hooks.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/hooks.ts).
- The system uses **JSON payloads via stdin** and **exit codes** (`0` allow, `2` block, other non-zero allow with logging) to communicate between the CLI and external scripts.
- **Fail-open architecture** ensures hook timeouts or crashes never disrupt the main session, suitable for both observability and security use cases.
- Configure hooks in **`~/.kimi-code/config.toml`** under the `[[hooks]]` array using `event`, `matcher`, `command`, and `timeout` fields.
- **Blockable events** (`UserPromptSubmit`, `PreToolUse`, `Stop`) enable security policies and input validation, while **observability events** (`SessionStart`, `PostToolUse`) support auditing and notifications.

## Frequently Asked Questions

### Can I modify the user prompt before it reaches the model using hooks?

Yes. The `UserPromptSubmit` event fires before the model processes input. While you cannot directly mutate the payload by writing to stdout, you can implement validation logic that inspects the JSON payload from stdin and uses exit code `2` to block disallowed inputs. For enrichment workflows, you would typically handle this through client-side integrations rather than the hook system itself, though hooks excel at validation and blocking.

### What happens if my hook script exceeds the timeout or crashes?

The Kimi Code hook system operates on a **fail-open** basis. If your script exceeds the configured `timeout` (default 30 seconds) or exits with any non-zero code other than `2`, the CLI logs the error but allows the main operation to proceed. Only exit code `2` explicitly blocks execution, ensuring that infrastructure failures don't accidentally freeze AI sessions while still permitting intentional security blocks.

### How do I prevent specific dangerous commands like `rm -rf /` from executing?

Use the `PreToolUse` event with a matcher for the `Bash` tool. Create a validation script—such as the `block-dangerous-bash.mjs` example—that parses the JSON payload from stdin, inspects `payload.tool_input.command` for dangerous patterns, and exits with code `2` to block execution. This pattern is documented in [`docs/en/customization/hooks.md`](https://github.com/MoonshotAI/kimi-code/blob/main/docs/en/customization/hooks.md) and tested in the `packages/agent-core` test suite.

### Are lifecycle hooks available in all Kimi Code editions?

The hook system is part of the open-source `kimi-code` core in `packages/agent-core-v2`, meaning it is available in standard CLI deployments configured via `~/.kimi-code/config.toml`. The system is validated by [`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), confirming its availability in the open-source distribution and standard desktop builds.