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 ¶
- func RegisteredTools() []string
- type ClaudeCodeParser
- type Message
- type Session
- func FindSessions(additionalDirs ...string) ([]*Session, error)
- func FindSessionsForCWD(cwd string, additionalDirs ...string) ([]*Session, error)
- func ParseFile(path string) ([]*Session, error)
- func ScanDirectory(dir string) ([]*Session, error)
- func ScanDirectoryWithErrors(dir string) ([]*Session, []error, error)
- type SessionParser
- type ToolResult
- type ToolUse
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) Matches ¶ added in v0.3.0
func (p *ClaudeCodeParser) Matches(path string) bool
Matches 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) BelongsToAssistant ¶ added in v0.3.0
BelongsToAssistant returns true if this is an assistant message.
Returns:
- bool: True if Role is "assistant"
func (*Message) BelongsToUser ¶ added in v0.3.0
BelongsToUser returns true if this is a user message.
Returns:
- bool: True if Role is "user"
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 ¶
FindSessions searches for session files in common locations.
It checks:
- ~/.claude/projects/ (Claude Code default)
- 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 ¶
FindSessionsForCWD searches for sessions matching the given working directory.
Matching is done in order of preference:
- Git remote URL match - if both directories are git repos with the same remote
- Path relative to home - e.g., "WORKSPACE/ctx" matches across users
- 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 ¶
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 ¶
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 ¶
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 ¶
AllToolUses returns all tool uses across all messages.
Returns:
- []ToolUse: Aggregated list of all tool invocations in the session
func (*Session) AssistantMessages ¶
AssistantMessages returns only assistant messages from the session.
Returns:
- []Message: Filtered list containing only messages with Role "assistant"
func (*Session) UserMessages ¶
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
// Matches returns true if this parser can handle the given file.
// Implementations may check file extension, peek at content, etc.
Matches(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