diff --git a/README.md b/README.md index 99226d2..fa35398 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ccview -A terminal-based explorer and renderer for [Claude Code](https://docs.anthropic.com/en/docs/claude-code) and [OpenCode](https://github.com/opencode-ai/opencode) conversation histories. Browse projects, view conversations with markdown rendering, inspect sub-agents, search across sessions, and export to HTML/Markdown/JSONL. +A terminal-based explorer and renderer for [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [OpenCode](https://github.com/opencode-ai/opencode), and Codex CLI conversation histories. Browse projects, view conversations with markdown rendering, inspect sub-agents, search across sessions, and export to HTML/Markdown/JSONL. Built with [Bubble Tea](https://github.com/charmbracelet/bubbletea), [Lip Gloss](https://github.com/charmbracelet/lipgloss), and [Glamour](https://github.com/charmbracelet/glamour). @@ -85,7 +85,7 @@ ccview Split-pane interactive explorer. Left pane shows the project tree with conversations, plans, and memory files. Right pane renders conversation content with syntax-highlighted markdown. -- **Multi-provider support** - Claude Code (`~/.claude/`) and OpenCode (`~/.local/share/opencode/opencode.db`) side by side. Tabbed UI when both are available; tabs hidden with only one provider. +- **Multi-provider support** - Claude Code (`~/.claude/`), OpenCode (`~/.local/share/opencode/opencode.db`), and Codex (`~/.codex/`) side by side. Tabbed UI when multiple providers are available; tabs hidden with only one provider. - Conversations sorted newest-first with smart timestamps - Sub-agents collapsed by default, expand on selection - Global plans shown in sidebar @@ -141,7 +141,7 @@ For full conversations with sub-agents, HTML export creates a directory with `in | Key | Action | |-----|--------| -| `1` / `2` | Switch provider tab | +| `1`-`9` | Switch provider tab | | `/` | Open session search (global) | ### Viewer @@ -193,6 +193,21 @@ ccview reads from multiple sources: | Sessions | Grouped by project (worktree path) | | Message parts | Text, tool calls, reasoning, patches, and file references | +#### Codex CLI (`~/.codex/`) + +| Source | Description | +|--------|-------------| +| `~/.codex/sessions/YYYY/MM/DD/*.jsonl` | JSONL rollout session logs | +| `~/.codex/state_*.sqlite` | Thread index with cwd, title, git metadata, model, source, token totals, and subagent edges | +| `session_meta` records | Session ID, cwd, originator, CLI version, model provider | +| `response_item` records | User/assistant messages, reasoning summaries, function calls, tool outputs | +| `turn_context` records | Runtime context such as model, sandbox, approval policy, timezone | +| `event_msg` records | Token usage, task lifecycle, patch/file-edit, web search, and image-generation metadata | +| `~/.codex/session_index.jsonl` | Session titles and updated timestamps | +| `~/.codex/shell_snapshots/*.sh` | Shell environment snapshots linked back to sessions when available | +| `~/.codex/goals_*.sqlite` | Thread goals and token budgets (available for future UI surfacing) | +| `~/.codex/history.jsonl` | Prompt history by session (available for future fallback titles/search) | + ### Message types rendered - **User messages** - with markdown rendering @@ -208,6 +223,7 @@ main.go CLI entry point, flag parsing provider.go Provider interface (abstracts data sources) provider_claude.go Claude Code provider (filesystem/JSONL) provider_opencode.go OpenCode provider (SQLite) +provider_codex.go Codex provider (filesystem/JSONL rollouts) data.go Tree types, project scanning, filesystem loading parse.go JSONL parsing, glamour rendering, formatting helpers ui.go Bubble Tea TUI with split-pane layout, search diff --git a/data.go b/data.go index 4f6f6a9..abd4fa6 100644 --- a/data.go +++ b/data.go @@ -21,9 +21,10 @@ type TreeData struct { } type TreeStats struct { - TotalProjects int `json:"totalProjects"` - TotalConversations int `json:"totalConversations"` - TotalMessages int `json:"totalMessages"` + TotalProjects int `json:"totalProjects"` + TotalConversations int `json:"totalConversations"` + TotalMessages int `json:"totalMessages"` + TotalTokens int64 `json:"totalTokens,omitempty"` } type TreeFileRef struct { @@ -41,24 +42,29 @@ type TreeProject struct { LastActive string `json:"lastActive"` ConvCount int `json:"convCount"` MsgCount int `json:"msgCount"` - Source string `json:"source,omitempty"` // "claude" or "opencode" + TokenCount int64 `json:"tokenCount,omitempty"` + Source string `json:"source,omitempty"` // "claude", "opencode", or "codex" } type TreeConversation struct { - SessionID string `json:"sessionId"` - Path string `json:"path"` - ModTime string `json:"modTime"` - Title string `json:"title"` - Preview string `json:"preview"` - MsgCount int `json:"msgCount"` - CWD string `json:"cwd,omitempty"` - Version string `json:"version,omitempty"` - GitBranch string `json:"gitBranch,omitempty"` - Slug string `json:"slug,omitempty"` - SubAgents []TreeSubAgent `json:"subAgents,omitempty"` - FileEditCount int `json:"fileEditCount,omitempty"` - ToolResults int `json:"toolResults,omitempty"` - Source string `json:"source,omitempty"` // "claude" or "opencode" + SessionID string `json:"sessionId"` + Path string `json:"path"` + ModTime string `json:"modTime"` + Title string `json:"title"` + Preview string `json:"preview"` + MsgCount int `json:"msgCount"` + TokenCount int64 `json:"tokenCount,omitempty"` + Model string `json:"model,omitempty"` + Reasoning string `json:"reasoning,omitempty"` + CWD string `json:"cwd,omitempty"` + Version string `json:"version,omitempty"` + GitBranch string `json:"gitBranch,omitempty"` + Slug string `json:"slug,omitempty"` + SubAgents []TreeSubAgent `json:"subAgents,omitempty"` + ShellSnapshots []TreeFileRef `json:"shellSnapshots,omitempty"` + FileEditCount int `json:"fileEditCount,omitempty"` + ToolResults int `json:"toolResults,omitempty"` + Source string `json:"source,omitempty"` // "claude", "opencode", or "codex" } type TreeSubAgent struct { diff --git a/export.go b/export.go index 29eaf50..e40a627 100644 --- a/export.go +++ b/export.go @@ -19,7 +19,7 @@ const exportHTMLHeader = ` -Claude Code Conversation +AI Conversation