ClaudeCode.History (ClaudeCode v0.16.0)
View SourceUtilities 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 responsessystem- System events (errors, etc.)summary- Conversation summaryfile-history-snapshot- File tracking metadataqueue-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
@type history_entry() :: map()
@type parsed_message() :: ClaudeCode.Message.AssistantMessage.t() | ClaudeCode.Message.UserMessage.t() | map()
@type session_id() :: String.t()
Functions
@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)
@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")
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"
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"
@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")
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()
@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")
@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")
@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")
@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")