Documentation
¶
Overview ¶
Package sessions lists the agents' recent sessions from their own session files — Claude Code's projects/*/<id>.jsonl (and Qoder's, the same kind), Codex's rollout files, OpenCode's database (or its older JSON files) and ZCode's, Pi's session files and omp's, DeepSeek Harness's, Cline's, Grok Build's, WorkBuddy's and Cursor CLI's chat stores — with the tokens each spent, what that cost at the effective price, and the command that resumes it. It only ever reads the agents' folders.
The files grow long (hundreds of MB), so each one's parse is kept by path, size and time, and a file that only grew is read on from where it was left. The parses are kept on disk too, in magpie's cache folder.
Index ¶
- Constants
- Variables
- func CachePath() string
- func ClaudeDir() string
- func ClineSessionDir() string
- func CodexDir() string
- func CodexTitles(ids []string) map[string]string
- func CursorDir() string
- func Deletable(agent string) bool
- func DesktopDataDirs() []string
- func Dirs() []string
- func DshDir() string
- func Duration(sec int64) string
- func GrokDir() string
- func HermesDir() string
- func HermesDirs() []string
- func OmpDir() string
- func OpenCodeDir() string
- func PiDir() string
- func Purge(key string) error
- func QoderDir(id string) string
- func Reset()
- func ResumeCommand(agent, id, cwd string) string
- func Saved()
- func SessionGlob(pattern string) ([]string, error)
- func ToolCategory(name string) string
- func TraceAgent(agent string) bool
- func TraceID(parts ...string) string
- func TraceSessionVisible(agent, id string) bool
- func TrashDir() string
- func WorkBuddyDir() string
- func ZCodeDir() string
- type Active
- type AgentCount
- type Call
- type CallSource
- type Content
- type Day
- type DayTotal
- type Managed
- type Model
- type Overview
- type Part
- type Progress
- type Rollup
- type Session
- type Shape
- type Share
- type Skill
- type SkillUse
- type Stats
- type Summary
- type Tokens
- type ToolStat
- type ToolUse
- type ToolWeek
- type TraceReader
- type TraceSession
- type TraceSessionIndex
- type TraceSpan
- type Trashed
- type Usage
Constants ¶
const ActiveWindow = time.Minute
ActiveWindow is how recently a session's file may have been written for it to count as in use, and not be deleted.
const Limit = 200
Limit is how many sessions, the latest by last activity, List reads.
Variables ¶
var ErrActive = errors.New("the session was written to in the last minute; it may still be running")
ErrActive is a session still being written: its agent may be running it.
var PriceOf = priceOf
PriceOf is the effective price of a model as a session names it, at the settings given. Tests swap it; the settings are the ones the listing read, so a swapped one prices against the same copy as the default does.
Functions ¶
func ClaudeDir ¶
func ClaudeDir() string
ClaudeDir is Claude Code's folder: $CLAUDE_CONFIG_DIR, else ~/.claude.
func ClineSessionDir ¶ added in v0.1.310
func ClineSessionDir() string
ClineSessionDir is Cline's sessions folder: $CLINE_SESSION_DATA_DIR, else sessions in $CLINE_DATA_DIR, else in data in $CLINE_DIR, else in ~/.cline/data.
func CodexTitles ¶ added in v0.1.591
CodexTitles reads Codex's append-only name index, never its configuration or conversation contents. Later entries replace earlier names after a rename. The result contains only the requested IDs; missing names remain unknown.
func CursorDir ¶ added in v0.1.661
func CursorDir() string
CursorDir is Cursor's CLI config folder: $CURSOR_CONFIG_DIR, else cursor in $XDG_CONFIG_HOME, else ~/.cursor.
func Deletable ¶ added in v0.1.593
Deletable says whether magpie can move an agent's sessions to its trash: those kept as files of their own, in a layout magpie knows whole.
func DesktopDataDirs ¶ added in v0.1.579
func DesktopDataDirs() []string
DesktopDataDirs are the folders whose session metadata belongs to this index.
func Dirs ¶ added in v0.1.289
func Dirs() []string
Dirs are the folders the sessions are read from: Claude Code's and Codex's, and the other agents' where they keep sessions on this computer.
func DshDir ¶ added in v0.1.310
func DshDir() string
DshDir is dsh's folder: $DSH_HOME, else ~/.dsh.
func Duration ¶ added in v0.1.265
Duration is active seconds in hours and minutes: 3h 12m, 40m, <1m; — when not kept.
func GrokDir ¶ added in v0.1.313
func GrokDir() string
GrokDir is Grok Build's folder: $GROK_HOME, else ~/.grok.
func HermesDir ¶ added in v0.1.669
func HermesDir() string
Hermes stores canonical, non-overlapping input/cache buckets. Reasoning is already included in output. session_model_usage includes auxiliary tasks and multiple billing routes; sessions supplies only unattributed main-loop usage. These tables contain aggregates, not individual API request usage.
func HermesDirs ¶ added in v0.1.669
func HermesDirs() []string
HermesDirs includes the default store and live named profiles. A selected profile home resolves back to its root, as Hermes's profile resolver does.
func OmpDir ¶ added in v0.1.490
func OmpDir() string
OmpDir is omp's agent folder, ~/.omp/agent, as magpie's omp agent has it.
func OpenCodeDir ¶ added in v0.1.289
func OpenCodeDir() string
OpenCodeDir is OpenCode's data folder: $XDG_DATA_HOME/opencode, else ~/.local/share/opencode — on Windows too, where OpenCode keeps it there.
func PiDir ¶ added in v0.1.289
func PiDir() string
PiDir is Pi's agent folder: $PI_CODING_AGENT_DIR, else ~/.pi/agent.
func Purge ¶ added in v0.1.615
Purge erases a trashed session for good: its folder in magpie's trash, files and note. Only when the reader asks for it (#487); nothing is ever erased by itself. A key that isn't a trashed session's, or whose folder (or its agent's) is a link that could lead out of the trash, is refused.
func QoderDir ¶ added in v0.1.310
QoderDir is the folder of Qoder's build of this id: $QODER_CONFIG_DIR, else ~/.qoder, for qoder; $QODERCN_CONFIG_DIR, else ~/.qoder-cn, for qoder-cn.
func ResumeCommand ¶
ResumeCommand is the shell line that picks a session up again in its folder, or "" for an id that isn't plain.
func Saved ¶ added in v0.1.417
func Saved()
Saved waits for the index being saved, so a process about to end leaves it on disk.
func SessionGlob ¶ added in v0.1.579
SessionGlob is filepath.Glob for session discovery, with directory listings cached by metadata. It never caches file contents or suppresses new entries.
func ToolCategory ¶ added in v0.1.410
ToolCategory is the kind of tool a name is, Claude Code's and Codex's alike: Bash, Edit, Read, Write, Glob, Grep, Task (subagents and plans), Tool (an MCP server's) or Other.
func TraceAgent ¶ added in v0.1.679
TraceAgent lists formats with an interaction and tool-aware trace adapter.
func TraceSessionVisible ¶ added in v0.1.701
TraceSessionVisible resolves a first request before the next reader tick. Only formats with an authoritative header are eligible; filenames alone cannot establish that a usable local transcript exists.
func TrashDir ¶ added in v0.1.593
func TrashDir() string
TrashDir is where deleted sessions are kept: <magpie dir>/trash/sessions.
func WorkBuddyDir ¶ added in v0.1.313
func WorkBuddyDir() string
WorkBuddyDir is WorkBuddy's folder: $WORKBUDDY_CONFIG_DIR, else ~/.workbuddy.
Types ¶
type Active ¶ added in v0.1.239
type Active struct {
Agent string `json:"agent"`
Cwd string `json:"cwd"`
Seconds int64 `json:"seconds"`
// Hours is Seconds again by the local hour of the day (24, or none)
Hours []int64 `json:"hours,omitempty"`
}
Active is the time an agent's sessions in one folder were at work on a day, in seconds (see day.Active for how it is told).
type AgentCount ¶ added in v0.1.593
type AgentCount struct {
Agent string `json:"agent"`
Count int `json:"count"`
Deletable bool `json:"deletable"`
}
AgentCount is an agent with sessions on this computer, and how many.
func Agents ¶ added in v0.1.593
func Agents() []AgentCount
Agents are the agents with sessions on this computer, by how many.
type Call ¶ added in v0.1.579
type Call struct {
Time time.Time `json:"t"`
Agent string `json:"agent"` // claude (Claude Code's CLI), claude-desktop (Desktop's Code tab and Cowork), codex
Session string `json:"session"` // the id the agent sends the gateway as its session header
Model string `json:"model"` // the model the file names: for Claude, the one the vendor answered
// Requested: the model Claude Code was running as (its identity note) when it made
// the call, as it was asked for: claude-opus-5[1m] for claude-opus-5 with the long context
Requested string `json:"requested,omitempty"`
Tokens
Reasoning int `json:"reasoning,omitempty"` // Codex: inside Output already
Effort string `json:"effort,omitempty"` // the thinking effort: Codex's, of the turn; Claude's, of the line
RequestID string `json:"request_id,omitempty"` // Claude's
// Codex's session metadata identifies its configured provider and creator.
// These identify the historical session, not whichever account is signed in now.
Upstream string `json:"upstream,omitempty"`
AccountID string `json:"account_id,omitempty"`
UserID string `json:"user_id,omitempty"`
Error string `json:"error,omitempty"` // Claude: the API error's kind (rate_limit, server_error …); such a call has no tokens
ErrorText string `json:"error_text,omitempty"` // its message, the first 400 characters
// Codex: the turn's own figures, set only when the turn made just this call
TTFT int64 `json:"ttft_ms,omitempty"`
// Millis: how long the call took. Codex's, of a turn that made this call alone, is what
// it says; the rest are told from the file's times, the call's last line less the line
// that asked for it (a prompt, a tool's result), and so a little more or less than it was
Millis int64 `json:"ms,omitempty"`
Cwd string `json:"cwd,omitempty"`
// Where the call is in its file, for reading what was said in it (ContentOf): the file,
// from where what it was asked began — after the reply before it — to where it ended,
// and for Claude Code the id of its message
File string `json:"file,omitempty"`
From int64 `json:"from,omitempty"`
To int64 `json:"to,omitempty"`
Msg string `json:"msg,omitempty"`
}
Call is one model call as an agent's own session file records it.
func Calls ¶ added in v0.1.579
Calls reads per-file request shards, separately from the session summaries. Only changed files are scanned, and only a bounded number of parses stay in memory. Conversation text is read by ContentOf when a detail is opened.
func FindCall ¶ added in v0.1.579
FindCall is the call of a session made between two times that ended nearest at (a call's Time is its last line's), if the session files have one. A gateway request's window can hold the next calls of a quick tool loop too; the newest of them would be another request's.
func ReadCallSource ¶ added in v0.1.579
func ReadCallSource(s CallSource) []Call
ReadCallSource returns immutable calls for one source. Independent files can be read concurrently; disk IO never holds callsMu.
type CallSource ¶ added in v0.1.579
CallSource identifies a raw local request log without reading its contents.
func CallSources ¶ added in v0.1.579
func CallSources() []CallSource
type Content ¶ added in v0.1.579
type Content struct {
Input []Part `json:"input"`
Output []Part `json:"output"`
Cut bool `json:"cut,omitempty"` // there was more than is kept here
}
Content is what a call was given and what it said, in the order of the file.
type Day ¶ added in v0.1.239
type Day struct {
Date string `json:"date"`
Usage []Usage `json:"usage"` // by agent, folder and model
Active []Active `json:"active"` // by agent and folder
}
Day is one local date's usage, cut fine enough for the page to filter it by agent, model and folder itself.
type DayTotal ¶ added in v0.1.265
type DayTotal struct {
Date string `json:"date"`
Tokens
Cost float64 `json:"cost"`
Active int64 `json:"active"` // seconds; -1 under a model
}
DayTotal is one date's usage under a Rollup's filters.
type Managed ¶ added in v0.1.593
type Managed struct {
Session
Size int64 `json:"size"`
Messages int `json:"messages"`
Files int `json:"files"`
Deletable bool `json:"deletable"`
}
Managed is a session as the management page lists it: what List has, and how big its files are, how many messages it has, and whether it can be deleted.
type Model ¶
type Model struct {
Model string `json:"model"`
Tokens
Cost float64 `json:"cost"`
Priced bool `json:"priced"`
}
Model is one model's share of a session.
type Overview ¶ added in v0.1.410
type Overview struct {
Count int `json:"count"`
Median int `json:"median"` // tokens (in and out) of the middle session
P90 int `json:"p90"` // … of the one nine in ten spent no more than
Days []int `json:"days"` // sessions at work each day, from Stats.From to To
// Top are the sessions that spent the most, by tokens, cost and
// active time, n of each
Top map[string][]Summary `json:"top"`
// Messages and Output are the messages and output tokens each day,
// as Days
Messages []int `json:"messages"`
Output []int `json:"output"`
// Shape is how many sessions came to how much: by messages, by
// minutes at work and by tool calls a prompt (autonomy)
Shape map[string]Shape `json:"shape"`
Tools ToolUse `json:"tools"`
Skills SkillUse `json:"skills"`
}
Overview is what the sessions of a range come to under the page's filters.
type Part ¶ added in v0.1.579
type Part struct {
Role string `json:"role"` // user, assistant or tool
Kind string `json:"kind"` // text, thinking, tool_use, tool_result, context or image
Name string `json:"name,omitempty"` // the tool's, of its call
Text string `json:"text"`
Cut int `json:"cut,omitempty"` // the characters left off its end
}
Part is one thing said in a call.
type Progress ¶ added in v0.1.410
type Progress struct {
Indexing bool `json:"indexing"`
Files int64 `json:"files"`
Done int64 `json:"done"`
Bytes int64 `json:"bytes"`
Read int64 `json:"read"`
}
Progress is how far the sessions being read have got; Indexing is false when none are.
type Rollup ¶ added in v0.1.265
type Rollup struct {
From string `json:"from"`
To string `json:"to"`
Model string `json:"model,omitempty"`
Folder string `json:"folder,omitempty"`
Tokens
Cost float64 `json:"cost"` // USD at the effective price, of the priced models
Unpriced []string `json:"unpriced"` // models that spent tokens and have no known price
// Active is the seconds the sessions were at work; -1 under a model,
// as active time isn't kept by model.
Active int64 `json:"active"`
DaysUsed int `json:"days_used"` // dates with usage
Days []DayTotal `json:"days"` // every date From…To, empty ones too
Models []Share `json:"models"` // under the folder, the most tokens first
Folders []Share `json:"folders"` // under the model, the most tokens first
}
Rollup is Stats summed under a model and a folder ("" for every one), as the app's Sessions view sums them: for the CLI and the TUI.
type Session ¶
type Session struct {
ReadOnly bool `json:"read_only,omitempty"`
Agent string `json:"agent"` // magpie agent id: claude, codex, opencode, pi, omp, zcode, dsh, cline, qoder, qoder-cn, grok, workbuddy, cursor, hermes
ID string `json:"id"`
Cwd string `json:"cwd"`
Title string `json:"title"` // the first prompt, else the agent's own title
Start time.Time `json:"start"`
Last time.Time `json:"last"`
Models []Model `json:"models"`
Tokens
Cost float64 `json:"cost"` // USD at the effective price, for the priced models
Unpriced int `json:"unpriced"` // models that spent tokens but have no known price
Resume string `json:"resume"` // the command that picks the session up again
Path string `json:"path"` // its (main) file
}
Session is one agent session.
type Shape ¶ added in v0.1.410
type Shape struct {
Edges []int `json:"edges"`
Counts []int `json:"counts"`
Total int `json:"total"`
}
Shape counts sessions into buckets: Counts[i] those from Edges[i] up to the next edge, the last one open.
type Share ¶ added in v0.1.265
type Share struct {
}
Share is one model's or folder's part of a Rollup.
type Skill ¶ added in v0.1.410
type Skill struct {
Name string `json:"name"`
Calls int `json:"calls"`
Sessions int `json:"sessions"`
Last string `json:"last"` // the date it was last called
Agents map[string]int `json:"agents"` // calls by agent
Projects []ToolStat `json:"projects"` // the folders that called it most, by name
}
Skill is one skill's calls.
type SkillUse ¶ added in v0.1.410
type SkillUse struct {
Calls int `json:"calls"`
Top []Skill `json:"top"`
Count int `json:"count"` // skills called at all
}
SkillUse is the skills the sessions called up.
type Stats ¶ added in v0.1.239
type Stats struct {
From string `json:"from"` // the first date, local: the range's, or for all time the first with anything
To string `json:"to"` // today
Days []Day `json:"days"` // the dates with anything, in order
// Sessions are the sessions at work in the range, each with what it
// spent in it, the most recently active first. Too many to send the
// page over a long range: Overview sums them up.
Sessions []Summary `json:"-"`
}
Stats is what every session spent, day by day: all of them, not only the latest List reads.
func StatsFor ¶ added in v0.1.239
StatsFor reads the usage of the last days days up to today, today included (every day when 0), from every session file there is. Only the files written to since the range began are looked at; what is read is kept, as List's is.
type Summary ¶ added in v0.1.410
type Summary struct {
Key string `json:"key"` // agent:id as its files are grouped, for Get
Agent string `json:"agent"`
ID string `json:"id"`
Cwd string `json:"cwd"`
Title string `json:"title"`
Last time.Time `json:"last"`
Tokens
Cost float64 `json:"cost"`
Priced bool `json:"priced"` // every model it used has a price
Active int64 `json:"active"` // seconds
Models []string `json:"models"` // the models it used in the range, the most used first
Days []int `json:"days"` // the dates it was at work on, as days after From
// Prompts and Replies are the messages each way, ToolCalls the tools
// it called, in the range (Claude Code's, Codex's, Pi's and omp's sessions)
Prompts int `json:"prompts"`
Replies int `json:"replies"`
ToolCalls int `json:"tool_calls"`
// contains filtered or unexported fields
}
Summary is one session's share of a range.
type Tokens ¶
type Tokens struct {
Input int `json:"input"`
Output int `json:"output"`
CacheRead int `json:"cache_read"`
CacheWrite int `json:"cache_write"`
}
Tokens is a count of tokens. Input excludes what was read from cache.
type ToolStat ¶ added in v0.1.410
type ToolStat struct {
Name string `json:"name"`
Category string `json:"category,omitempty"`
Calls int `json:"calls"`
Sessions int `json:"sessions"`
}
ToolStat is one tool's (or category's) calls.
type ToolUse ¶ added in v0.1.410
type ToolUse struct {
Calls int `json:"calls"`
Sessions int `json:"sessions"`
Top []ToolStat `json:"top"` // the most called
Categories []ToolStat `json:"categories"` // by category, the most called first
// Weeks are the calls week by week, from Monday, by category
Weeks []ToolWeek `json:"weeks"`
}
ToolUse is what the sessions called their tools for.
type ToolWeek ¶ added in v0.1.410
type ToolWeek struct {
Start string `json:"start"` // its Monday
Calls map[string]int `json:"calls"`
}
ToolWeek is one week's calls by category.
type TraceReader ¶ added in v0.1.679
TraceReader follows supported local agent stores modified since activation. Existing lines establish ancestry, but events older than Since aren't emitted. Deterministic IDs make resumed rollouts and copied session branches idempotent.
func NewTraceReader ¶ added in v0.1.679
func NewTraceReader(since time.Time) *TraceReader
func (*TraceReader) Poll ¶ added in v0.1.679
func (r *TraceReader) Poll(bodies bool) []TraceSpan
Poll reads appended complete lines only. It limits watched files to the most recent sessions; a partial last line remains for the following poll.
func (*TraceReader) SetSessionIndex ¶ added in v0.1.701
func (r *TraceReader) SetSessionIndex(index *TraceSessionIndex)
Share request-side discovery with this reader's regular polling.
func (*TraceReader) VisibleSessions ¶ added in v0.1.701
func (r *TraceReader) VisibleSessions() []TraceSession
VisibleSessions is refreshed on Poll; old transcripts only contribute their identity, not completed historical operations.
type TraceSession ¶ added in v0.1.701
type TraceSession struct{ Agent, ID string }
TraceSession names a readable local transcript, independently of whether it has produced any observations. Header inspection never emits history/bodies.
type TraceSessionIndex ¶ added in v0.1.701
type TraceSessionIndex struct {
// contains filtered or unexported fields
}
TraceSessionIndex shares one discovery snapshot across all request IDs and polling. The caller that wins refresh performs directory I/O; other concurrent requests use the snapshot without waiting for that scan. Its zero value is usable; no state is shared between exporters or stores.
func (*TraceSessionIndex) Visible ¶ added in v0.1.701
func (x *TraceSessionIndex) Visible(agent, id string) bool
type TraceSpan ¶ added in v0.1.679
type TraceSpan struct {
Agent, Session, Turn, ID, Parent, Name, Kind, Model, Provider, Served string
Start, End time.Time
Input, Output string
Tokens Tokens
Reasoning int
Error, Inferred bool
Update bool
}
TraceSpan is a recorded agent operation, model response, or tool execution.
type Trashed ¶ added in v0.1.593
type Trashed struct {
Key string `json:"key"` // its folder in the trash, <agent>/<name>
Agent string `json:"agent"`
ID string `json:"id"`
Title string `json:"title"`
Cwd string `json:"cwd"`
Last time.Time `json:"last"`
Deleted time.Time `json:"deleted"`
Size int64 `json:"size"`
Items []moved `json:"items"`
}
Trashed is a deleted session in magpie's trash.
func Delete ¶ added in v0.1.593
Delete moves a session's files to magpie's trash: its own file, the folder of its subagents and tool results beside it, its other files (a Codex session's later segments, its subagents' elsewhere) and, for Claude Code, the file history, todos and environment it keeps by the session's id. A session any file of which was written in the last minute is not touched (ErrActive).
type Usage ¶ added in v0.1.239
type Usage struct {
Agent string `json:"agent"`
Cwd string `json:"cwd"`
Model string `json:"model"`
Tokens
Cost float64 `json:"cost"` // USD at the effective price, when priced
Priced bool `json:"priced"`
}
Usage is what one model spent for one agent in one folder on a day.
Source Files
¶
- call_cache.go
- calls.go
- claude.go
- cline.go
- codex.go
- codex_titles.go
- content.go
- cursor.go
- discovery.go
- dsh.go
- grok.go
- hermes.go
- hermes_display.go
- manage.go
- omp.go
- opencode.go
- pi.go
- qoder.go
- rollup.go
- sessions.go
- stats.go
- traces.go
- traces_claude.go
- traces_gemini.go
- traces_identity.go
- traces_opencode.go
- traces_opencode_db.go
- traces_snapshot.go
- workbuddy.go
- zcode.go