# How to Debug Kimi-CLI Session Issues Using the Wire File and Session State Files

> Debug Kimi-CLI session issues by inspecting state.json and wire.jsonl. Trace errors, analyze tool calls, and replay conversations for deterministic debugging.

- Repository: [Moonshot AI/kimi-cli](https://github.com/MoonshotAI/kimi-cli)
- Tags: how-to-guide
- Published: 2026-07-22

---

**Kimi-CLI persists every interaction in [`state.json`](https://github.com/MoonshotAI/kimi-cli/blob/main/state.json) (high-level metadata) and `wire.jsonl` (message log), allowing you to inspect session health, trace missing tool calls, and replay conversations for deterministic debugging.**

When a Kimi-CLI session behaves unexpectedly—whether it is missing a tool call, losing context, or getting stuck in a loop—the root cause often lies in how session data is persisted. According to the MoonshotAI/kimi-cli source code, the CLI stores session metadata in [`state.json`](https://github.com/MoonshotAI/kimi-cli/blob/main/state.json) and maintains a complete message audit trail in `wire.jsonl`, giving you two complementary entry points to diagnose issues.

## Understanding Session Persistence Architecture

Kimi-CLI uses a dual-file persistence model that separates high-level session state from low-level message traffic.

### The Session State File ([`state.json`](https://github.com/MoonshotAI/kimi-cli/blob/main/state.json))

Located at `<session-dir>/state.json`, this file stores a JSON-encoded **SessionState** model containing high-level metadata such as approval flags, custom titles, todo lists, and archive status. As defined in [`src/kimi_cli/session_state.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/session_state.py) (lines 12-44), this state is managed by the `SessionState` class and loaded via the `load_session_state()` function.

### The Wire Log (`wire.jsonl`)

The `wire.jsonl` file (also in the session directory) acts as a line-delimited JSON log of every **WireMessage** sent or received. As implemented in [`src/kimi_cli/wire/file.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/wire/file.py) (lines 18-26), the first line contains a **WireFileMetadata** header with the wire-protocol version, followed by **WireMessageRecord** entries containing timestamps and message payloads.

## Step-by-Step Debugging Workflow

To diagnose session issues, inspect both files using the following workflow.

### 1. Load and Inspect Session State

Call `load_session_state(session_dir)` to read [`state.json`](https://github.com/MoonshotAI/kimi-cli/blob/main/state.json) into a **SessionState** object. This reveals whether the session thinks it is archived, what todo items are pending, and whether any legacy [`metadata.json`](https://github.com/MoonshotAI/kimi-cli/blob/main/metadata.json) was migrated. According to [`src/kimi_cli/session_state.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/session_state.py) (lines 99-127), this function handles path resolution and migration logic automatically.

### 2. Read and Analyze the Wire Log

Initialize `WireFile(session_dir / "wire.jsonl")` to iterate over stored records. Each **WireMessageRecord** contains the original message (tool calls, UI events, hook requests) plus a monotonic timestamp ([`src/kimi_cli/wire/file.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/wire/file.py), lines 59-66). You can filter for specific event types like **ToolCallPart** or **HookTriggered** to trace when specific actions occurred.

### 3. Correlate Timestamps and Events

Because the wire file stores a monotonic timestamp for each record, you can line up events with high-level state changes captured in [`state.json`](https://github.com/MoonshotAI/kimi-cli/blob/main/state.json). For example, if "plan mode" is missing in the state, check for a `HookTriggered` event that never arrived in the wire log, indicating a message delivery failure.

### 4. Detect Corrupted Files

Both persistence layers include error resilience. `load_session_state` falls back to defaults and logs a warning if [`state.json`](https://github.com/MoonshotAI/kimi-cli/blob/main/state.json) is malformed (lines 104-108 in [`session_state.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/session_state.py)). Similarly, `WireFile.iter_records()` skips unparsable lines while logging failures, allowing you to spot truncated or malformed wire entries ([`src/kimi_cli/wire/file.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/wire/file.py), lines 95-112).

### 5. Replay Sessions for Reproduction

The **KimiSoul** runtime can reconstruct sessions from the wire log for deterministic debugging. During replay, the server reads each **WireMessage** from the file and re-executes the same tool calls ([`src/kimi_cli/wire/server.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/wire/server.py), lines 815-848). This is invaluable for reproducing race conditions or timing-dependent bugs.

## Practical Code Examples

Run the following snippets in a Python REPL to inspect a session located at `~/.kimi/sessions/<hash>`.

```python
from pathlib import Path
from kimi_cli.session_state import load_session_state
from kimi_cli.wire.file import WireFile

# ----------------------------------------------------------------------

# 1️⃣ Load the high‑level session state

# ----------------------------------------------------------------------

session_dir = Path.home() / ".kimi" / "sessions" / "<hash>"
state = load_session_state(session_dir)
print("Session title:", state.custom_title or "(none)")
print("Todo items:", [(t.title, t.status) for t in state.todos])
print("Archived:", state.archived, "at", state.archived_at)
print("Wire protocol version:", state.wire_mtime)

# ----------------------------------------------------------------------

# 2️⃣ Iterate over the wire log

# ----------------------------------------------------------------------

wire = WireFile(session_dir / "wire.jsonl")
print("\nWire file header protocol version:", wire.version)

# Print the first few messages with timestamps

import itertools
for record in itertools.islice(wire.iter_records(), 10):
    msg = record.to_wire_message()
    print(f"{record.timestamp:.3f}s – {type(msg).__name__}: {msg}")

# ----------------------------------------------------------------------

# 3️⃣ Find a specific type of event (e.g., a tool call)

# ----------------------------------------------------------------------

from kimi_cli.wire.types import is_wire_message, ToolCallPart

matches = []
for rec in wire.iter_records():
    msg = rec.to_wire_message()
    # ToolCallPart is a payload for a tool request; adjust as needed

    if hasattr(msg, "tool_call"):
        matches.append((rec.timestamp, msg.tool_call))
        if len(matches) >= 5:
            break

print("\nFirst few tool calls:")
for ts, tc in matches:
    print(f"{ts:.3f}s → {tc}")

# ----------------------------------------------------------------------

# 4️⃣ Detect malformed lines (helpful when the wire file is corrupted)

# ----------------------------------------------------------------------

for rec in wire.iter_records():
    # The iterator skips bad lines, but we can count them via logging

    pass
print("\nIf you saw warnings in the console, those lines were unparsable.")

```

## Summary

- **Session state** is stored in [`state.json`](https://github.com/MoonshotAI/kimi-cli/blob/main/state.json) and managed by the `SessionState` class in [`src/kimi_cli/session_state.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/session_state.py), tracking metadata like todos and archive status.
- **Message history** is logged to `wire.jsonl` via the `WireFile` class in [`src/kimi_cli/wire/file.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/wire/file.py), with each record containing a timestamp and payload.
- **Debugging workflow** involves loading the state, iterating over wire records with `iter_records()`, correlating timestamps, and checking for corruption warnings.
- **Session replay** is supported by `KimiSoul` in [`src/kimi_cli/wire/server.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/wire/server.py), enabling deterministic reproduction of issues from the wire log.

## Frequently Asked Questions

### Where does Kimi-CLI store session files?

Session files are stored in `~/.kimi/sessions/<hash>/`, where `<hash>` is a unique session identifier. Each session directory contains both [`state.json`](https://github.com/MoonshotAI/kimi-cli/blob/main/state.json) (metadata) and `wire.jsonl` (message log).

### What does the wire protocol version indicate?

The wire protocol version is stored in the **WireFileMetadata** header (first line of `wire.jsonl`) and indicates the schema version of the message format. The `SessionState` object tracks the last modification time of the wire file in its `wire_mtime` field to detect external changes.

### How do I recover from a corrupted [`state.json`](https://github.com/MoonshotAI/kimi-cli/blob/main/state.json) file?

The `load_session_state()` function automatically falls back to default values and logs a warning if [`state.json`](https://github.com/MoonshotAI/kimi-cli/blob/main/state.json) is malformed or missing. You can manually delete the file to force regeneration, though you will lose custom titles and todo items. Archived sessions can be restored by toggling the `archived` flag back to `false` in the regenerated state.

### Can I manually edit `wire.jsonl` to fix session issues?

While technically possible, manual editing is not recommended because the file uses a strict line-delimited JSON format with monotonic timestamps. Corrupted entries will be skipped by `WireFile.iter_records()`, but may cause the replay functionality in [`src/kimi_cli/wire/server.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/wire/server.py) to fail. Use the replay feature instead to recreate sessions programmatically.