ClaudeCode.History (ClaudeCode v0.16.0)

View Source

Utilities for reading and parsing Claude Code session history files.

Claude Code stores conversation history in JSONL files at: ~/.claude/projects/<encoded-project-path>/<session-id>.jsonl

This module provides functions to:

  • Find session files by session ID
  • Read and parse session JSONL files
  • Extract conversation history (user/assistant messages)

Session File Format

Session files contain various message types:

  • user - User messages (prompts and tool results)
  • assistant - Assistant responses
  • system - System events (errors, etc.)
  • summary - Conversation summary
  • file-history-snapshot - File tracking metadata
  • queue-operation - Internal operations

Examples

# Read a session by ID
{:ok, messages} = ClaudeCode.History.read_session("abc123-def456")

# Get just the conversation (user/assistant messages)
{:ok, conversation} = ClaudeCode.History.conversation("abc123-def456")

# Read from a specific file path
{:ok, messages} = ClaudeCode.History.read_file("/path/to/session.jsonl")

# Find session file location
{:ok, path} = ClaudeCode.History.find_session_path("abc123-def456")

Summary

Functions

Extracts the conversation history from a session.

Extracts the conversation history from a session file path.

Decodes an encoded project path back to a path format.

Encodes a project path to the format used by Claude Code.

Finds the file path for a session ID.

Lists all projects that have session history.

Lists all session IDs for a project.

Reads and parses a session JSONL file from a specific path.

Reads and parses a session file by session ID.

Gets the conversation summary from a session, if available.

Types

history_entry()

@type history_entry() :: map()

parsed_message()

session_id()

@type session_id() :: String.t()

Functions

conversation(session_id, opts \\ [])

@spec conversation(
  session_id(),
  keyword()
) :: {:ok, [parsed_message()]} | {:error, term()}

Extracts the conversation history from a session.

Returns only user and assistant messages, parsed into SDK message structs. Other message types (system events, metadata) are excluded.

Options

Same as read_session/2.

Examples

{:ok, conversation} = ClaudeCode.History.conversation("abc123-def456")

# Each message is a UserMessage or AssistantMessage struct
Enum.each(conversation, fn
  %UserMessage{message: %{content: content}} ->
    IO.puts("User: #{inspect(content)}")
  %AssistantMessage{message: %{content: content}} ->
    IO.puts("Assistant: #{inspect(content)}")
end)

conversation_from_file(path)

@spec conversation_from_file(Path.t()) :: {:ok, [parsed_message()]} | {:error, term()}

Extracts the conversation history from a session file path.

Returns only user and assistant messages, parsed into SDK message structs.

Examples

{:ok, conversation} = ClaudeCode.History.conversation_from_file("/path/to/session.jsonl")

decode_project_path(encoded)

@spec decode_project_path(String.t()) :: Path.t()

Decodes an encoded project path back to a path format.

Replaces - with /. Note that this encoding is lossy - if the original path contained - or _ characters, they cannot be distinguished from path separators. For example, /a/b-c, /a/b_c, and /a/b/c all encode to -a-b-c.

This function is primarily useful for display purposes. For matching against known paths, use encode_project_path/1 instead.

Examples

iex> ClaudeCode.History.decode_project_path("-Users-me-project")
"/Users/me/project"

encode_project_path(path)

@spec encode_project_path(Path.t()) :: String.t()

Encodes a project path to the format used by Claude Code.

Replaces / and _ with - in the path to match the CLI's encoding.

Examples

iex> ClaudeCode.History.encode_project_path("/Users/me/project")
"-Users-me-project"

iex> ClaudeCode.History.encode_project_path("/Users/me/my_project")
"-Users-me-my-project"

find_session_path(session_id, opts \\ [])

@spec find_session_path(
  session_id(),
  keyword()
) :: {:ok, Path.t()} | {:error, term()}

Finds the file path for a session ID.

Searches through all project directories in ~/.claude/projects/.

Options

  • :project_path - Specific project path to search in (optional)
  • :claude_dir - Override the Claude directory (default: ~/.claude)

Examples

{:ok, "/Users/me/.claude/projects/-my-project/abc123.jsonl"} =
  ClaudeCode.History.find_session_path("abc123")

{:error, {:session_not_found, "abc123"}} =
  ClaudeCode.History.find_session_path("nonexistent")

list_projects(opts \\ [])

@spec list_projects(keyword()) :: {:ok, [Path.t()]} | {:error, term()}

Lists all projects that have session history.

Options

  • :claude_dir - Override the Claude directory (default: ~/.claude)

Examples

{:ok, ["/Users/me/project1", "/Users/me/project2"]} =
  ClaudeCode.History.list_projects()

list_sessions(project_path, opts \\ [])

@spec list_sessions(
  Path.t(),
  keyword()
) :: {:ok, [session_id()]} | {:error, term()}

Lists all session IDs for a project.

Options

  • :claude_dir - Override the Claude directory (default: ~/.claude)

Examples

{:ok, ["abc123", "def456"]} = ClaudeCode.History.list_sessions("/my/project")

read_file(path)

@spec read_file(Path.t()) :: {:ok, [history_entry()]} | {:error, term()}

Reads and parses a session JSONL file from a specific path.

Returns all entries from the file as maps with normalized keys.

Examples

{:ok, entries} = ClaudeCode.History.read_file("/path/to/session.jsonl")

read_session(session_id, opts \\ [])

@spec read_session(
  session_id(),
  keyword()
) :: {:ok, [history_entry()]} | {:error, term()}

Reads and parses a session file by session ID.

Searches through all project directories to find the session file. Returns all entries from the session file, including metadata entries.

Options

  • :project_path - Specific project path to search in (optional)
  • :claude_dir - Override the Claude directory (default: ~/.claude)

Examples

{:ok, messages} = ClaudeCode.History.read_session("abc123-def456")

# Search in a specific project
{:ok, messages} = ClaudeCode.History.read_session("abc123", project_path: "/my/project")

summary(session_id, opts \\ [])

@spec summary(
  session_id(),
  keyword()
) :: {:ok, String.t() | nil} | {:error, term()}

Gets the conversation summary from a session, if available.

Returns the summary text or nil if no summary exists.

Examples

{:ok, "User asked about..."} = ClaudeCode.History.summary("abc123-def456")
{:ok, nil} = ClaudeCode.History.summary("new-session-id")