parser

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 1, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package parser provides JSONL session file parsing for the recall system.

It parses AI coding assistant session transcripts into structured Go types that can be rendered, searched, and analyzed. The package uses a tool-agnostic Session output type with tool-specific parsers (e.g., ClaudeCodeParser).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RegisteredTools

func RegisteredTools() []string

RegisteredTools returns the list of supported tools.

Returns:

  • []string: Tool identifiers for all registered parsers

Types

type ClaudeCodeParser

type ClaudeCodeParser struct{}

ClaudeCodeParser parses Claude Code JSONL session files.

Claude Code stores sessions as JSONL files where each line is a self-contained JSON object representing a message. Messages are linked via parentUuid and grouped by sessionId.

func NewClaudeCodeParser

func NewClaudeCodeParser() *ClaudeCodeParser

NewClaudeCodeParser creates a new Claude Code session parser.

Returns:

  • *ClaudeCodeParser: A parser instance for Claude Code JSONL files

func (*ClaudeCodeParser) CanParse

func (p *ClaudeCodeParser) CanParse(path string) bool

CanParse returns true if the file appears to be a Claude Code session file.

Checks if the file has a .jsonl extension and contains Claude Code message format (sessionId and slug fields in the first few lines).

Parameters:

  • path: File path to check

Returns:

  • bool: True if this parser can handle the file

func (*ClaudeCodeParser) ParseFile

func (p *ClaudeCodeParser) ParseFile(path string) ([]*Session, error)

ParseFile reads a Claude Code JSONL file and returns all sessions.

Parses each line as a JSON message, groups messages by session ID, and constructs Session objects with timing, token counts, and message content. Sessions are sorted by start time.

Parameters:

  • path: Path to the JSONL file to parse

Returns:

  • []*Session: All sessions found in the file, sorted by start time
  • error: Non-nil if the file cannot be opened or read

func (*ClaudeCodeParser) ParseLine

func (p *ClaudeCodeParser) ParseLine(line []byte) (*Message, string, error)

ParseLine parses a single JSONL line into a Message.

Unmarshals the JSON, extracts the message content, and converts it to the common Message type. Non-message lines (e.g., file-history-snapshot) are skipped and return nil.

Parameters:

  • line: Raw JSONL line bytes to parse

Returns:

  • *Message: The parsed message, or nil if the line should be skipped
  • string: The session ID this message belongs to
  • error: Non-nil if JSON unmarshaling fails

func (*ClaudeCodeParser) Tool

func (p *ClaudeCodeParser) Tool() string

Tool returns the tool identifier for this parser.

Returns:

  • string: The identifier "claude-code"

type Message

type Message struct {
	ID        string    `json:"id"`
	Timestamp time.Time `json:"timestamp"`
	Role      string    `json:"role"`

	Text        string       `json:"text,omitempty"`
	Thinking    string       `json:"thinking,omitempty"`
	ToolUses    []ToolUse    `json:"tool_uses,omitempty"`
	ToolResults []ToolResult `json:"tool_results,omitempty"`

	TokensIn  int `json:"tokens_in,omitempty"`
	TokensOut int `json:"tokens_out,omitempty"`
}

Message represents a single message in a session.

This is tool-agnostic - all parsers normalize to this format.

Fields:

Identity:

  • ID: Unique message identifier
  • Timestamp: When the message was created
  • Role: Message role ("user" or "assistant")

Content:

  • Text: Main text content
  • Thinking: Reasoning content (if available)
  • ToolUses: Tool invocations in this message
  • ToolResults: Results from tool invocations

Token Usage:

  • TokensIn: Input tokens for this message (if available)
  • TokensOut: Output tokens for this message (if available)

func (*Message) HasToolUses

func (m *Message) HasToolUses() bool

HasToolUses returns true if this message contains tool invocations.

Returns:

  • bool: True if ToolUses slice is non-empty

func (*Message) IsAssistant

func (m *Message) IsAssistant() bool

IsAssistant returns true if this is an assistant message.

Returns:

  • bool: True if Role is "assistant"

func (*Message) IsUser

func (m *Message) IsUser() bool

IsUser returns true if this is a user message.

Returns:

  • bool: True if Role is "user"

func (*Message) Preview

func (m *Message) Preview(maxLen int) string

Preview returns a truncated preview of the message text.

Parameters:

  • maxLen: Maximum length before truncation (adds "..." if exceeded)

Returns:

  • string: The text, truncated with "..." suffix if longer than maxLen

type Session

type Session struct {
	ID   string `json:"id"`
	Slug string `json:"slug,omitempty"`

	Tool       string `json:"tool"`
	SourceFile string `json:"source_file"`

	CWD       string `json:"cwd,omitempty"`
	Project   string `json:"project,omitempty"`
	GitBranch string `json:"git_branch,omitempty"`

	StartTime time.Time     `json:"start_time"`
	EndTime   time.Time     `json:"end_time"`
	Duration  time.Duration `json:"duration"`

	Messages  []Message `json:"messages"`
	TurnCount int       `json:"turn_count"`

	TotalTokensIn  int `json:"total_tokens_in,omitempty"`
	TotalTokensOut int `json:"total_tokens_out,omitempty"`
	TotalTokens    int `json:"total_tokens,omitempty"`

	HasErrors    bool   `json:"has_errors,omitempty"`
	FirstUserMsg string `json:"first_user_msg,omitempty"`
	Model        string `json:"model,omitempty"`
}

Session represents a reconstructed conversation session.

This is the tool-agnostic output type that all parsers produce. It contains common fields that make sense across different AI tools.

Fields:

Identity:

  • ID: Unique session identifier
  • Slug: URL-friendly session identifier

Source:

  • Tool: Source tool ("claude-code", "aider", "cursor", etc.)
  • SourceFile: Original file path

Context:

  • CWD: Working directory when session started
  • Project: Project name (derived from last component of CWD)
  • GitBranch: Git branch name if available

Timing:

  • StartTime: When the session started
  • EndTime: When the session ended
  • Duration: Total session duration

Messages:

  • Messages: All messages in the session
  • TurnCount: Count of user messages

Token Statistics:

  • TotalTokensIn: Input tokens used (if available)
  • TotalTokensOut: Output tokens used (if available)
  • TotalTokens: Total tokens used (if available)

Derived:

  • HasErrors: True if any tool errors occurred
  • FirstUserMsg: Preview text of first user message (truncated)
  • Model: Primary model used in the session

func FindSessions

func FindSessions(additionalDirs ...string) ([]*Session, error)

FindSessions searches for session files in common locations.

It checks:

  1. ~/.claude/projects/ (Claude Code default)
  2. The specified directory (if provided)

Parameters:

  • additionalDirs: Optional additional directories to scan

Returns:

  • []*Session: Deduplicated sessions sorted by start time (newest first)
  • error: Non-nil if scanning fails (partial results may still be returned)

func FindSessionsForCWD

func FindSessionsForCWD(
	cwd string, additionalDirs ...string,
) ([]*Session, error)

FindSessionsForCWD searches for sessions matching the given working directory.

Matching is done in order of preference:

  1. Git remote URL match - if both directories are git repos with the same remote
  2. Path relative to home - e.g., "WORKSPACE/ctx" matches across users
  3. Exact CWD match - fallback for non-git, non-home paths

Parameters:

  • cwd: Working directory to filter by
  • additionalDirs: Optional additional directories to scan

Returns:

  • []*Session: Filtered sessions sorted by start time (newest first)
  • error: Non-nil if scanning fails

func ParseFile

func ParseFile(path string) ([]*Session, error)

ParseFile parses a session file using the appropriate parser.

It auto-detects the file format by trying each registered parser.

Parameters:

  • path: Path to the session file to parse

Returns:

  • []*Session: All sessions found in the file
  • error: Non-nil if no parser can handle the file or parsing fails

func ScanDirectory

func ScanDirectory(dir string) ([]*Session, error)

ScanDirectory recursively scans a directory for session files.

It finds all parseable files, parses them, and aggregates sessions. Sessions are sorted by start time (newest first). Parse errors for individual files are silently ignored; use ScanDirectoryWithErrors if you need to report them.

Parameters:

  • dir: Root directory to scan recursively

Returns:

  • []*Session: All sessions found, sorted by start time (newest first)
  • error: Non-nil if directory traversal fails

func ScanDirectoryWithErrors

func ScanDirectoryWithErrors(dir string) ([]*Session, []error, error)

ScanDirectoryWithErrors is like ScanDirectory but also returns parse errors.

Use this when you want to report files that failed to parse while still returning successfully parsed sessions.

Parameters:

  • dir: Root directory to scan recursively

Returns:

  • []*Session: Successfully parsed sessions, sorted by start time
  • []error: Errors from files that failed to parse
  • error: Non-nil if directory traversal fails

func (*Session) AllToolUses

func (s *Session) AllToolUses() []ToolUse

AllToolUses returns all tool uses across all messages.

Returns:

  • []ToolUse: Aggregated list of all tool invocations in the session

func (*Session) AssistantMessages

func (s *Session) AssistantMessages() []Message

AssistantMessages returns only assistant messages from the session.

Returns:

  • []Message: Filtered list containing only messages with Role "assistant"

func (*Session) UserMessages

func (s *Session) UserMessages() []Message

UserMessages returns only user messages from the session.

Returns:

  • []Message: Filtered list containing only messages with Role "user"

type SessionParser

type SessionParser interface {
	// ParseFile reads a session file and returns all sessions found.
	// A single file may contain multiple sessions (grouped by session ID).
	ParseFile(path string) ([]*Session, error)

	// ParseLine parses a single line from a session file.
	// Returns nil if the line should be skipped (e.g., non-message lines).
	ParseLine(line []byte) (*Message, string, error) // message, sessionID, error

	// CanParse returns true if this parser can handle the given file.
	// Implementations may check file extension, peek at content, etc.
	CanParse(path string) bool

	// Tool returns the tool identifier (e.g., "claude-code", "aider").
	Tool() string
}

SessionParser defines the interface for tool-specific session parsers.

Each AI tool (Claude Code, Aider, Cursor) implements this interface to parse its specific format into the common Session type.

func Parser

func Parser(tool string) SessionParser

Parser returns a parser for the specified tool.

Parameters:

  • tool: Tool identifier (e.g., "claude-code")

Returns:

  • SessionParser: The parser for the tool, or nil if not found

type ToolResult

type ToolResult struct {
	ToolUseID string `json:"tool_use_id"`
	Content   string `json:"content"`
	IsError   bool   `json:"is_error,omitempty"`
}

ToolResult represents the result of a tool invocation.

Fields:

  • ToolUseID: ID of the ToolUse this result corresponds to
  • Content: The tool's output content
  • IsError: True if the tool execution failed

type ToolUse

type ToolUse struct {
	ID    string `json:"id"`
	Name  string `json:"name"`
	Input string `json:"input"`
}

ToolUse represents a tool invocation by the assistant.

Fields:

  • ID: Unique identifier for this tool use
  • Name: Tool name (e.g., "Bash", "Read", "Write", "Grep")
  • Input: JSON string of input parameters passed to the tool

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL