How the agentsview CLI Manages Different Agent Session Formats
The agentsview CLI manages different agent session formats through a centralized AgentDef registry in internal/parser/types.go, where each AI agent registers custom discovery and parsing functions that normalize diverse formats into a unified SQLite schema.
The agentsview CLI from the kenn-io/agentsview repository is a Go-based command-line tool that monitors directories containing session files from multiple AI coding assistants. Understanding how the agentsview CLI manages different agent session formats reveals a plugin-style architecture that abstracts away format-specific complexities, allowing the same sync engine and HTTP API to handle everything from Claude Code's JSONL streams to Cursor's project layouts.
The Agent Registry: Centralized Format Definitions
At the heart of the format management system lies the AgentDef struct defined in internal/parser/types.go. This struct serves as a contract that every supported agent must implement:
type AgentDef struct {
Type AgentType // “claude”, “codex”, …
DisplayName string // Human‑readable name
EnvVar string // “CLAUDE_PROJECTS_DIR”, …
ConfigKey string // TOML key, empty when not configurable
DefaultDirs []string // e.g. []string{".codex/sessions"}
IDPrefix string // “codex:” etc.
WatchSubdirs []string // Sub‑directories to watch (nil ⇒ watch root)
ShallowWatch bool // Watch root only, rely on periodic sync
FileBased bool // false for DB‑backed agents (Claude AI, ChatGPT …)
// Functions supplied by each agent’s parser
DiscoverFunc func(string) []DiscoveredFile // Walk a root, return session files
FindSourceFunc func(string, string) string // Locate a single session’s source file
WatchRootsFunc func(string) []string // Optional custom watch‑root resolver
ShallowWatchRootsFunc func(string) []string // Optional extra roots for shallow watch
}
All agent definitions are collected in the global Registry slice. During startup, the CLI iterates over this registry in cmd/agentsview/main.go to build a watch list, applying environment variable overrides (via EnvVar) and resolving default directories (via DefaultDirs) for each file-based agent.
Discovery: Agent-Specific File Walking
Each parser supplies a DiscoverFunc that knows how to locate session files within its specific directory structure. For example, internal/parser/claude.go implements DiscoverClaudeSessions(root string) []DiscoveredFile which walks the ~/.claude/projects tree to collect every *.jsonl file.
The discovery phase operates as follows:
- The sync engine resolves roots using environment variables or default paths
- It invokes
def.DiscoverFunc(root)for each registered agent - Returned
DiscoveredFileobjects are queued for parsing
Agents like Copilot, Cursor, and Kilo maintain analogous discovery functions in their respective parser files, each handling their unique file naming conventions and sub_directory structures.
Parsing and Normalization: Unified Output Structure
After discovery, the sync engine loads each file and calls the appropriate parser. Claude's parser (ParseClaudeSession in internal/parser/claude.go) handles the most complex format, processing JSON-L streams that may contain UUID/parent-UUID DAGs, merging streamed assistant chunks, and resolving tool-result references.
Crucially, every parser returns the same ParseResult type defined in internal/parser/types.go:
type ParseResult struct {
Session ParsedSession
Messages []ParsedMessage
}
This contract ensures that downstream components—the SQLite writer in internal/db/sessions.go, the SSE server, and the frontend—treat every session uniformly regardless of its original on-disk representation.
Session ID Management and Prefix Disambiguation
The CLI uses the IDPrefix field to disambiguate between agents when handling session identifiers. For example:
- Codex: Uses prefix
codex: - Cursor: Uses prefix
cursor: - Claude Code: Uses an empty string (un-prefixed UUID)
The AgentByPrefix function (also in internal/parser/types.go) maps session IDs back to their originating agents by stripping any host prefix (host~id) and matching the remaining identifier against known prefixes. For Claude, where the prefix is empty, the match succeeds only if the ID contains no colon, effectively disambiguating it from all prefixed agents.
Watch Strategies: File-Based vs. Database Agents
The FileBased boolean field distinguishes between two fundamentally different agent types:
File-Based Agents (FileBased: true):
- Register with the file watcher (
fsnotify/recursive) - Support real-time updates via
DiscoverFunc - May use
ShallowWatch: trueto avoid recursive inotify registration (used by high-volume agents like Aider), relying instead on a periodic 15-minute scan
Database-Backed Agents (FileBased: false):
- Include
Claude.ai,ChatGPT,Forge, andPiebald - Do not set up file watchers
- Query session data directly via PostgreSQL sync code in
internal/postgres - Still populate the same
ParsedSessionstruct, but from DB queries rather than files
Some agents like Codex and Antigravity need to watch additional metadata directories (e.g., session_index.jsonl). These provide ShallowWatchRootsFunc that the watcher merges with normal WatchRootsFunc returns.
Complete Sync Workflow
The agentsview CLI orchestrates format management through a six-stage pipeline defined across internal/sync/engine.go and related modules:
- Load configuration (
internal/config/config.go): Resolve environment overrides and TOML settings - Build watch list: Iterate
parser.Registry, skipping non-file-based agents - Discover: Execute each agent's
DiscoverFuncto find existing sessions - Parse: Call agent-specific
Parse*Sessionfunctions to normalize data - Store: Persist normalized
ParsedSessionobjects to SQLite (internal/db/sessions.go) - Serve: Expose data through the HTTP API and SSE endpoints (
internal/server/*)
Summary
-
Centralized Registry: The
AgentDefstruct ininternal/parser/types.godefines metadata, discovery functions, and parsing logic for each supported agent. -
Uniform Interface: All parsers return a standardized
ParseResult, allowing the sync engine and API layers to remain agnostic of original file formats. -
Flexible Discovery: Each agent implements a custom
DiscoverFunc(e.g.,DiscoverClaudeSessions) to handle its specific directory layout and file patterns. -
ID Namespacing: Session IDs use agent-specific prefixes (e.g.,
codex:) except for Claude Code, enabling unambiguous cross-agent identification. -
Dual Storage Models: File-based agents use recursive or shallow file watching, while database-backed agents query remote PostgreSQL instances, both feeding the same normalized schema.
Frequently Asked Questions
How does agentsview distinguish between different agent session files?
The CLI uses the IDPrefix field in each AgentDef to namespace session identifiers. When processing a session ID, the AgentByPrefix function strips any host prefix and matches the remainder against registered prefixes like codex: or cursor:. Claude Code uses an empty prefix and is identified by the absence of a colon in the UUID, ensuring unambiguous routing to the correct parser.
What is the difference between file-based and database-backed agents in agentsview?
File-based agents (FileBased: true) store sessions as files on disk and are monitored via fsnotify watchers or periodic scans, while database-backed agents (FileBased: false) such as Claude.ai and ChatGPT store data in remote PostgreSQL databases. The CLI queries the latter directly via internal/postgres rather than watching directories, though both types ultimately populate the same ParsedSession struct in SQLite.
How can I configure a custom directory for a specific agent in agentsview?
Set the environment variable specified in the agent's AgentDef.EnvVar field before running the CLI. For example, export COPILOT_DIR=$HOME/my-copilot-sessions overrides the default directory for Copilot sessions. When agentsview sync --agent copilot executes, it resolves the custom path through internal/config/config.go and watches the specified location instead of the default.
Why does agentsview use shallow watching for some agents like Aider?
Agents that generate a high volume of files, such as Aider, set ShallowWatch: true in their AgentDef to avoid the performance cost of recursive inotify registration. Instead of watching the entire directory tree, the CLI watches only the root directory and relies on a periodic 15-minute scan to discover new session files, balancing real-time responsiveness with system resource efficiency.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →