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 CodeBuddy Code's, Droid's, Cursor CLI's and Alma'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 AgyDir() string
- func AlmaDir() string
- func Ask() (done func())
- func CachePath() string
- func ClaudeDir() string
- func ClineSessionDir() string
- func CodeBuddyDir() string
- func CodexDir() string
- func CodexIdentities() map[string]CodexIdentity
- func CodexPromptDigest(prompt string) string
- func CodexProviderIn(home string) string
- func CodexThreadProviders(home string) []string
- func CodexTitleDigest(name string) string
- func CodexTitleRecipients(digests []string) map[string][]TitleApplication
- func CodexTitles(ids []string) map[string]string
- func CursorDir() string
- func Deletable(agent string) bool
- func DesktopDataDirs() []string
- func DesktopTitles(ids []string) map[string]string
- func Dirs() []string
- func DshDir() string
- func Duration(sec int64) string
- func FactoryDir() string
- func GatewayHidden() func(agent, id string, last time.Time) bool
- func GatewayRecordingGeneration() uint64
- func GatewaySizes() func(agent, id string) int64
- func GatewayTitle(agent, id string) string
- func GrokDir() string
- func HasGatewayConversations() bool
- func HasTranscript(agent string) bool
- func HermesDir() string
- func HermesDirs() []string
- func KimiCodeDir() string
- func MiniMaxDir() string
- func NativeIDs(agents map[string]bool) map[string]map[string]bool
- func NeedleOf(q string) string
- func OmpDir() string
- func OpenCodeDir() string
- func PIDesktopDir() string
- func PIDesktopTitles(ids []string) map[string]string
- func PiDir() string
- func PruneGatewayConversations(now time.Time) error
- func Purge(key string) error
- func QoderDir(id string) string
- func Reset()
- func ResumeCommand(agent, id, cwd string) string
- func SaveGatewayTurn(turn GatewayTurn) error
- func SaveGatewayTurnGeneration(turn GatewayTurn, generation uint64) error
- func Saved()
- func SessionGlob(pattern string) ([]string, error)
- func SetGatewayRecording(on, clear bool) error
- func SubagentOf(p string) string
- func SubagentParent(p string) string
- func Titles(keys []string) map[string]string
- 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 Warm(fn func())
- func WorkBuddyDir() string
- func WriteGatewayMarkdown(w io.Writer, s Session, name string, t Transcript) error
- func WriteMarkdown(w io.Writer, s Session, name string) error
- func ZCodeDir() string
- type Active
- type AgentCount
- type Call
- type CallSource
- type Carry
- type ClaudeRelocation
- type ClaudeRelocationResult
- type CodexIdentity
- type CodexMove
- type CodexPort
- type Content
- type Day
- type DayTotal
- type ExternalDayUsage
- type ExternalModel
- type ExternalSession
- type GatewayTurn
- type Hit
- type ManageView
- type Managed
- type Model
- type ModelEffort
- type Overview
- type Part
- type Progress
- type Rollup
- type Session
- type Shape
- type Share
- type Skill
- type SkillUse
- type Stats
- type Subagent
- type Summary
- type TitleApplication
- type Tokens
- type ToolStat
- type ToolUse
- type ToolWeek
- type TraceReader
- type TraceSession
- type TraceSessionIndex
- type TraceSpan
- type Transcript
- type Trashed
- type Usage
- type WSLHome
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 All = 5000
All is what a listing that means every session asks List for: the count a page or a command shows beside the list is taken from every session, so the list has to be as long as the count, and this is long past any history a computer has. Limit stays what it is because traceRecentFiles sizes gateway attribution by it.
const GatewayRetention = 7 * 24 * time.Hour
const Limit = 200
Limit is how many sessions, the latest by last activity, List reads when the caller asks for no particular number. traceRecentFiles sizes the window gateway attribution is judged over by it too, so it is not raised to make a listing longer: a caller that wants more asks for more.
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 ErrNoSubagent = errors.New("no such subagent in this session")
ErrNoSubagent is a subagent the session doesn't have.
var ErrNoTranscript = errors.New("this agent's conversations can't be shown")
ErrNoTranscript is a session whose conversation magpie can't read: an agent that keeps it in a database, or in a form not read here.
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.
var TraceIdentityTTL = 2 * time.Second
TraceIdentityTTL is how long Visible reuses a discovery scan, a miss included, before scanning the transcripts again. Tests that need a cached miss to stay cached for a whole request lengthen it.
var WSLHomes func() []WSLHome
WSLHomes are the WSL distros to read sessions in; nil (none) unless internal/agent sets it, which it does where there is WSL.
var WSLOff func() bool
WSLOff is whether Settings' Detect agents in WSL is off (#1264); set by internal/agent. Off, no distro's sessions are listed, not even those listed before.
var WSLRunning func(distro string) bool
WSLRunning is whether a distro runs now, as wsl.exe said a few seconds ago at most; internal/agent sets it. A listing's Running is as old as the listing (up to wslRelist and more): a distro the user stopped since (wsl --shutdown, to repair WSL) would be started again by reading its files, so a file is read only while this says it runs.
Functions ¶
func AgyDir ¶ added in v0.1.1233
func AgyDir() string
AgyDir is agy's data folder, ~/.gemini/antigravity-cli.
func Ask ¶ added in v0.1.1200
func Ask() (done func())
Ask marks a page waiting on sessions until done is called: reading goes at full speed while it waits.
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 CodeBuddyDir ¶ added in v0.1.1214
func CodeBuddyDir() string
CodeBuddyDir is CodeBuddy Code's folder: $CODEBUDDY_CONFIG_DIR, else ~/.codebuddy, as internal/agent's codebuddy.go finds it.
func CodexIdentities ¶ added in v0.1.1238
func CodexIdentities() map[string]CodexIdentity
CodexIdentities returns an independent snapshot of the native thread identities.
func CodexPromptDigest ¶ added in v0.1.840
CodexPromptDigest keeps prompt evidence comparable across restarts without publishing a guessable hash. The key stays in Magpie's local config directory.
func CodexProviderIn ¶ added in v0.1.999
CodexProviderIn is the provider the Codex of a folder uses now, whose sessions its history lists: config.toml's model_provider, its profile's when it chooses one, else "openai".
func CodexThreadProviders ¶ added in v0.1.1134
CodexThreadProviders is every provider the threads of a Codex folder were started on, as its state databases keep them: the Codex app resumes a thread on that one, whatever config.toml's model_provider is now, and fails to load its config for it when config.toml has no table of that id (#1372). A database without the threads table, or one that can't be read, says nothing.
func CodexTitleDigest ¶ added in v0.1.840
func CodexTitleRecipients ¶ added in v0.1.840
func CodexTitleRecipients(digests []string) map[string][]TitleApplication
CodexTitleRecipients includes chats whose requests never crossed Magpie. They still count as conflicting recipients of a generated title.
func CodexTitles ¶ added in v0.1.591
CodexTitles reads only the append-only name index. It caches unchanged files and reads newly appended complete lines from the previous offset.
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 DesktopTitles ¶ added in v0.1.1220
DesktopTitles reads Code and Cowork names from Desktop's local metadata, even when the CLI transcript is absent. Only IDs explicitly recorded there are named; prior CLI runs keep their own usage identity and share the name.
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 FactoryDir ¶ added in v0.1.720
func FactoryDir() string
FactoryDir is Droid's folder: $FACTORY_HOME_OVERRIDE/.factory, else ~/.factory.
func GatewayHidden ¶ added in v0.1.1151
GatewayHidden says whether a gateway session was deleted: true when it was, and had no request after its last one then.
func GatewayRecordingGeneration ¶ added in v0.1.1146
func GatewayRecordingGeneration() uint64
GatewayRecordingGeneration returns the current consent generation. A request captures it when recording starts and must present the same value when saving, so clearing and re-enabling recording cannot resurrect old data.
func GatewaySizes ¶ added in v0.1.1151
GatewaySizes is what conversation text magpie keeps of each gateway session, in bytes, read in one walk of the store.
func GatewayTitle ¶ added in v0.1.1213
GatewayTitle is what a gateway session was first asked, made one short line, from the first turns magpie recorded of it; "" when it recorded none or nothing the user wrote.
func GrokDir ¶ added in v0.1.313
func GrokDir() string
GrokDir is Grok Build's folder: $GROK_HOME, else ~/.grok.
func HasGatewayConversations ¶ added in v0.1.1150
func HasGatewayConversations() bool
HasGatewayConversations says whether any gateway conversation text is kept, so the Sessions page offers to delete it only when there is something to delete. A folder that can't be read counts as holding some: the reader can still ask to clear it.
func HasTranscript ¶ added in v0.1.940
HasTranscript says whether an agent's sessions can be read as a transcript.
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 KimiCodeDir ¶ added in v0.1.1220
func KimiCodeDir() string
KimiCodeDir is Kimi Code's folder: $KIMI_CODE_HOME, else ~/.kimi-code, as internal/agent's KimiDir finds the new Kimi Code's (which this package cannot import). The old Python kimi-cli's ~/.kimi has no usage records.
func MiniMaxDir ¶ added in v0.1.1188
func MiniMaxDir() string
MiniMaxDir is MiniMax Code's data folder: MINIMAX_DATA_DIR, or ~/.minimax (as internal/agent's MiniMaxDir, which this package cannot import).
func NativeIDs ¶ added in v0.1.1289
NativeIDs are the ids of every session the agents named keep themselves, by agent: one nothing was said in too, as ListAgent lists it. It tells a gateway session an agent keeps from one only magpie saw. Only the named agents' files are looked at, and of those only the ones whose session id is inside the file are read when they changed.
func NeedleOf ¶ added in v0.1.1213
NeedleOf is a query as it is matched: lowered, its spaces made one.
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 PIDesktopDir ¶ added in v0.1.1227
func PIDesktopDir() string
PIDesktopDir is where PI-Desktop keeps its data: $PI_DESKTOP_DATA_DIR, else ~/.pi-desktop (a packaged install's, its 04-data-storage.md).
func PIDesktopTitles ¶ added in v0.1.1227
PIDesktopTitles are the titles PI-Desktop gave the chats ids name, those it has one for. pi.sqlite is only read: opened immutable, or from a copy when its write-ahead log holds what isn't in it yet, as Cursor's store.db is (openCursorStore). A database that can't be read leaves the names last read standing: unknown, not untitled.
func PiDir ¶ added in v0.1.289
func PiDir() string
PiDir is Pi's agent folder: $PI_CODING_AGENT_DIR, else ~/.pi/agent.
func PruneGatewayConversations ¶ added in v0.1.1146
PruneGatewayConversations removes expired date buckets even while recording is off. Reads enforce the exact cutoff too, between periodic cleanup passes.
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 SaveGatewayTurn ¶ added in v0.1.1146
func SaveGatewayTurn(turn GatewayTurn) error
SaveGatewayTurn keeps a bounded, scrubbed exchange. Recording is checked again under the same lock as disable-and-clear, so in-flight requests cannot refill it.
func SaveGatewayTurnGeneration ¶ added in v0.1.1146
func SaveGatewayTurnGeneration(turn GatewayTurn, generation uint64) error
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 SetGatewayRecording ¶ added in v0.1.1146
SetGatewayRecording changes only this machine's consent. Clear disables first.
func SubagentOf ¶ added in v0.1.1165
SubagentOf is the subagent a Claude Code file is the conversation of, by its name: <agent> of <id>/subagents/agent-<agent>.jsonl or a workflow's <id>/subagents/workflows/<run>/agent-<agent>.jsonl — the agentId its lines carry, and the x-claude-code-agent-id Claude Code sends the gateway for it. "" for a session's own file, and any other agent's.
func SubagentParent ¶ added in v0.1.1165
SubagentParent is the subagent that started the one whose Claude Code file p is: the parentAgentId of its agent-<agent>.meta.json beside it, which Claude Code writes for a subagent a subagent started (spawnDepth 2 and on), the x-claude-code-parent-agent-id it sends the gateway. "" for one the conversation itself started, and for a file that is no subagent's. A meta file once read is kept; one not read is read again.
func Titles ¶ added in v0.1.1118
Titles is the title of each session named by key (agent:id, as Get takes it) that has its files on this computer: the name it was given, else the agent's own title, else its first prompt. A key with no files, or a session with no title, is left out. Desktop's local metadata can name a session without its CLI transcript. The Routing page uses this too (#1293).
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 Warm ¶ added in v0.1.1200
func Warm(fn func())
Warm runs fn, the reads nobody waits on yet, with few readers.
func WorkBuddyDir ¶ added in v0.1.313
func WorkBuddyDir() string
WorkBuddyDir is WorkBuddy's folder: $WORKBUDDY_CONFIG_DIR, else ~/.workbuddy.
func WriteGatewayMarkdown ¶ added in v0.1.1169
WriteGatewayMarkdown writes a session magpie's gateway recorded (t, from GatewayTranscript) as WriteMarkdown writes one read from the agent's own file: for a session whose agent ran on another machine, as one that reaches this magpie through a remote magpie does (akic404 on Discord), there is no file here, only what the gateway kept. It says so, and says when older turns or the end of a long part weren't kept.
func WriteMarkdown ¶ added in v0.1.1116
WriteMarkdown writes s's conversation, read whole from its file, as Markdown: a heading with what the session is, then each turn under who said it. Thinking, a tool's result and what the agent put in itself are folded (<details>); a tool's call is its name and arguments. name is the agent as the reader knows it. The file is only read.
func ZCodeDir ¶ added in v0.1.310
func ZCodeDir() string
ZCodeDir is ZCode's folder, ~/.zcode, under Go's home. Its CLI's database stays there, USERPROFILE on Windows, even where the app keeps the rest under a HOME the user set (appdir.ZCodeHome): ZCode 3.14.3 for Windows, run with both, wrote cli\db\db.sqlite under USERPROFILE and v2 under HOME.
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 {
ResponseID string `json:"response_id,omitempty"`
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
ThreadID string `json:"thread_id,omitempty"`
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"`
// Compaction is Codex's explicit marker that this response compacted the context.
Compaction bool `json:"compaction,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"`
// Compact: how long a compaction of the context kept the agent waiting, in ms.
// Codex's is on the compaction's own call (its Millis); Claude Code's is the
// durationMs its compact_boundary line says, on the first call after it
Compact int64 `json:"compact_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 AgentCalls ¶ added in v0.1.1258
AgentCalls is Calls of one agent's session files only: Codex's model and effort per thread need Codex's calls, not a read of every agent's.
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.
Over a long history a read decodes every shard (#2278: 68k of them, 415 MB), so callers asking at once share one read of the same files, and only one read of every file runs at a time: the Sessions page's requests arriving together each held a whole read's calls, and the app grew to 85 GB.
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 Carry ¶ added in v0.1.940
Carry is another agent a session can be carried on in, and the shell line that does it in the session's folder.
type ClaudeRelocation ¶ added in v0.1.1224
type ClaudeRelocation struct {
From string `json:"from"`
To string `json:"to"`
WSL string `json:"wsl,omitempty"`
Token string `json:"token,omitempty"`
}
ClaudeRelocation moves an entire project within one Claude Code config directory. Token is the preview's fingerprint; an empty token only previews.
type ClaudeRelocationResult ¶ added in v0.1.1224
type ClaudeRelocationResult struct {
From string `json:"from"`
To string `json:"to"`
WSL string `json:"wsl,omitempty"`
Sessions int `json:"sessions"`
Files int `json:"files"`
Bytes int64 `json:"bytes"`
Token string `json:"token"`
Backup string `json:"backup,omitempty"`
}
func RelocateClaudeProject ¶ added in v0.1.1224
func RelocateClaudeProject(in ClaudeRelocation) (ClaudeRelocationResult, error)
RelocateClaudeProject does not touch Desktop's stores, global history, or session-ID-keyed files (file-history, todos and session-env). IDs stay intact. Clients must be closed: the in-process lock cannot exclude Claude itself.
type CodexIdentity ¶ added in v0.1.1238
type CodexIdentity struct {
ID string `json:"id"`
Role string `json:"role"`
ParentSession string `json:"parent_session,omitempty"`
RootSession string `json:"root_session,omitempty"`
}
CodexIdentity is a Codex thread's confirmed role and parent chain.
type CodexMove ¶ added in v0.1.999
type CodexMove struct {
ID string `json:"id"`
From string `json:"from"`
To string `json:"to"`
Files []string `json:"files"`
Backup string `json:"backup"` // its files as they were
DB []string `json:"db,omitempty"`
}
CodexMove is one session moved to another provider.
func MoveCodexProvider ¶ added in v0.1.999
MoveCodexProvider moves a Codex session to the provider to: the model_provider of each session_meta in its files, and of its row in Codex's state database. A session written to in the last minute is left as it is (ErrActive), as Codex may be running it. Each file is copied to <magpie dir>/trash/codex-provider/ before it is changed, and rewritten whole into a file beside it that then takes its place, keeping its time.
func MoveCodexThreads ¶ added in v0.1.1333
MoveCodexThreads moves every thread of a Codex folder its state database keeps on the provider from to the provider to, each as MoveCodexProvider moves one: its files' session_meta and its row, a copy of the files kept in magpie's trash first. Codex lists only the threads of the provider it is on (app-server thread/list, the TUI's resume picker), so the threads started while magpie was Codex's provider were gone from Codex's lists once Codex was off magpie (kaizaoji on X: "the context doesn't exist"). A thread written to in the last minute is left for the next call, and so is one whose files can't be found; it says what it moved and the first error it met, having gone on past it.
type CodexPort ¶ added in v0.1.1303
type CodexPort struct {
Rewritten []string // rollouts written portable
Held []string // rollouts with magpie's item a Codex holds, left for a later pass
Done bool // every rollout due was looked at
}
CodexPort is what a pass did.
func PortCodexRollouts ¶ added in v0.1.1303
PortCodexRollouts makes the rollouts of the Codex home home portable, those written since the last whole pass and those it left before, until ctx ends. The first pass reads every rollout written since magpie began to compact; later ones only what changed since.
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 ExternalDayUsage ¶ added in v0.1.1146
MergeExternalStats appends external daily usage and session summaries to a Stats snapshot. It is deliberately data-only so callers can keep their own source and pricing policy.
type ExternalModel ¶ added in v0.1.1146
ExternalModel and ExternalSession are read-only session projections from a request ledger such as the gateway. They intentionally carry no file or resume capability.
type ExternalSession ¶ added in v0.1.1146
type ExternalSession struct {
Agent, ID string
Title string // what it was first asked (GatewayTitle); its id when ""
Start, Last time.Time
Models []ExternalModel
Daily []ExternalDayUsage
Tokens
Cost float64
Unpriced int
}
type GatewayTurn ¶ added in v0.1.1146
type GatewayTurn struct {
Agent string `json:"agent"`
Session string `json:"session"`
Time time.Time `json:"time"`
Model string `json:"model"`
Status int `json:"status"`
Input []Part `json:"input"`
Output []Part `json:"output"`
Cut bool `json:"cut,omitempty"`
}
GatewayTurn is one captured client-facing exchange. Input may include replayed history; Output is only this request's reply. It is not a native session.
type Hit ¶ added in v0.1.1213
type Hit struct {
Role string `json:"role"`
Kind string `json:"kind"`
Before string `json:"before"`
Match string `json:"match"`
After string `json:"after"`
}
Hit is where a session said what was searched for: a few words either side of the match, on one line.
func SearchGateway ¶ added in v0.1.1213
SearchGateway finds needle in what magpie recorded of a gateway session, the parts as its transcript shows them.
type ManageView ¶ added in v0.1.1289
type ManageView struct {
Agents []AgentCount
Native map[string]map[string]bool
Agent string
Sessions []Managed
}
ManageView is the session management page, read in one pass over every agent's files: the agents with sessions, the ids of the sessions of those asked for (as NativeIDs), and the agent shown with its sessions (as ListAgent).
func Manage ¶ added in v0.1.1289
func Manage(native map[string]bool, pick func([]AgentCount, map[string]map[string]bool) string) ManageView
Manage reads the management page. pick, given the counts and the native ids of the agents in native, names the agent to list ("" for none); it runs under the sessions lock and must not call back into this package. Only native's agents and the one picked are read: a change to another agent's sessions waits for a page that shows it (#2776).
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"`
// Codex: the provider the session was made with, and the one its Codex
// uses now, whose sessions alone its history lists (#887)
Provider string `json:"provider,omitempty"`
UsesProvider string `json:"uses_provider,omitempty"`
}
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 ModelEffort ¶ added in v0.1.1238
type ModelEffort struct {
Model string `json:"model"`
Effort string `json:"effort"`
Tokens
Reasoning int `json:"reasoning"`
Cost float64 `json:"cost"`
Priced bool `json:"priced"`
}
ModelEffort is one model and reasoning effort'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
// Model is the model an assistant part's own line names (#2253):
// Claude Code's message.model, the model the reply came back from,
// and Codex's turn_context.model, the one its turn was sent to. ""
// where the file names none; never one guessed from elsewhere.
Model string `json:"model,omitempty"`
}
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"`
// Gateway: seen only through magpie's gateway, with no file of the
// agent's on this computer (external.go)
Gateway bool `json:"gateway,omitempty"`
Agent string `json:"agent"` // magpie agent id: claude, codex, opencode, pi, omp, zcode, dsh, cline, qoder, qoder-cn, grok, workbuddy, codebuddy, droid, cursor, hermes, alma, kimi
ID string `json:"id"`
Cwd string `json:"cwd"`
Title string `json:"title"` // the name it was given, else the agent's own title, else the first prompt
Nickname string `json:"nickname,omitempty"`
Start time.Time `json:"start"`
Last time.Time `json:"last"`
Role string `json:"role,omitempty"`
ParentSession string `json:"parent_session,omitempty"`
RootSession string `json:"root_session,omitempty"`
ModelEffort []ModelEffort `json:"model_effort,omitempty"`
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
// Carry are the other agents that can carry the session on, reading its
// file as it is (carry.go)
Carry []Carry `json:"carry,omitempty"`
// Transcript says its conversation can be read (TranscriptOf)
Transcript bool `json:"transcript,omitempty"`
// Subagents are the conversations its agent started inside it, each
// read with SubagentTranscript (subagents.go)
Subagents []Subagent `json:"subagents,omitempty"`
// WSL is the WSL distro the session ran in, its files read through
// \\wsl.localhost (see wsl.go); "" for this computer's own
WSL string `json:"wsl,omitempty"`
// Convs are the ids magpie's gateway keys the session's requests by
// when they carry no session id of their own (dshConvs)
Convs []string `json:"-"`
}
Session is one agent session.
func Find ¶
Find is a session by agent and id: a listed one, else one Get finds under agent:id. One nothing was said in is found too, as ListAgent lists it: the Sessions page shows it, and its conversation, Markdown and Terminal open from it as from any other (#2273).
func Get ¶ added in v0.1.410
Get is the session whose files are grouped under key (a Summary's Key), however long ago it was at work.
func List ¶
List reads the latest sessions of every agent, the most recently active first, at most limit of them (Limit when 0).
func MergeExternal ¶ added in v0.1.1146
func MergeExternal(native []Session, external []ExternalSession) []Session
MergeExternal adds external sessions to a file-backed listing. Native sessions win on the exact Agent+ID identity and external entries are kept read-only (no file of the agent's to resume or open) with a gateway transcript reader; magpie's own record of one is deleted by DeleteGateway.
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:"-"`
// Keys are those sessions' keys, agent:id, in the same order: which of
// the sessions the page lists were at work in the range. The list is
// every session ever, so without them it guessed from each one's last
// line — and a session whose last line is a setting or a fork's seed,
// written long after its last call, was listed but not counted.
Keys []string `json:"keys"`
}
Stats is what every session spent, day by day: all of them, not only the latest List reads.
func MergeExternalStats ¶ added in v0.1.1146
func MergeExternalStats(st Stats, days []ExternalDayUsage, external []ExternalSession) Stats
func StatsAndNative ¶ added in v0.1.1289
StatsAndNative is StatsFor, and the agent|id of every session List would list, with no limit: what tells a gateway session the agent keeps too from one only magpie saw. Both come of one pass over the files, as the overview asks for both on every poll (#2776).
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 Subagent ¶ added in v0.1.1246
type Subagent struct {
ID string `json:"id"`
Title string `json:"title,omitempty"`
// Kind is the agent it ran as: Claude Code's agentType ("Explore"),
// OpenCode's agent ("general"), Kimi Code's subagentName ("coder")
Kind string `json:"kind,omitempty"`
// Parent is the subagent that started it, "" when the session did
Parent string `json:"parent,omitempty"`
Start time.Time `json:"start,omitzero"`
Last time.Time `json:"last,omitzero"`
// Path is the file its conversation is in (OpenCode's database)
Path string `json:"-"`
}
Subagent is a conversation a session's agent started inside it, which its agent keeps beside the session's own and counts in it (#2261): a Claude Code (or Qoder) subagent's agent-<id>.jsonl, an OpenCode child session, a Kimi Code agents/agent-<n>/wire.jsonl. Codex's subagents are sessions of their own, which name theirs in ParentSession instead.
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"`
Nickname string `json:"nickname,omitempty"`
Last time.Time `json:"last"`
Role string `json:"role,omitempty"`
ParentSession string `json:"parent_session,omitempty"`
RootSession string `json:"root_session,omitempty"`
ModelEffort []ModelEffort `json:"model_effort,omitempty"`
// Gateway: magpie knows the session only from the gateway's records
// (MergeExternalStats). The agent left no file magpie reads, so it has
// no folder, and no prompt unless gateway conversations were recorded
// (#2285: a Pi subagent's DeepSeek turns read as "(no prompt)").
Gateway bool `json:"gateway,omitempty"`
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 TitleApplication ¶ added in v0.1.840
TitleApplication is an actual name write, not just a chat's current name. Keeping old writes lets an association survive a later manual rename.
type Tokens ¶
type Tokens struct {
Input int `json:"input"`
Output int `json:"output"`
CacheRead int `json:"cache_read"`
CacheWrite int `json:"cache_write"`
// CacheWrite1h is how many of CacheWrite were written to be kept for an
// hour, where the agent says (Claude Code's cache_creation)
CacheWrite1h int `json:"cache_write_1h,omitempty"`
}
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
func (*TraceSessionIndex) VisibleFresh ¶ added in v0.1.776
func (x *TraceSessionIndex) VisibleFresh(agent, id string) bool
VisibleFresh bypasses the discovery TTL for the one check before exporting a request's first attempt. Join an in-progress scan rather than trusting a cached miss; normal request-start checks remain nonblocking and cached.
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
Pending bool // ancestry only; export the root when the interaction finishes
}
TraceSpan is a recorded agent operation, model response, or tool execution.
type Transcript ¶ added in v0.1.940
type Transcript struct {
Parts []Part `json:"parts"`
Cut bool `json:"cut,omitempty"` // there was more than is kept here
Source string `json:"source,omitempty"`
Captured int `json:"captured,omitempty"`
}
Transcript is what was said in a session, in the order it was said.
func GatewayTranscript ¶ added in v0.1.1146
func GatewayTranscript(agent, id string) (Transcript, error)
GatewayTranscript reads recent captured exchanges. Only a full matching previous history prefix is removed, never equal text found elsewhere in a chat.
func SubagentTranscript ¶ added in v0.1.1246
func SubagentTranscript(s Session, sub string) (Transcript, error)
SubagentTranscript is the conversation of the session's subagent sub.
func TranscriptOf ¶ added in v0.1.940
func TranscriptOf(s Session) (Transcript, error)
TranscriptOf reads a session's conversation from its (main) file.
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"`
// Gateway: a session seen only through magpie's gateway, whose items
// are the conversation text magpie recorded of it (gateway_delete.go)
Gateway bool `json:"gateway,omitempty"`
}
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). One in a WSL distro is moved out of it over \\wsl.localhost the same way, its Claude Code files from the distro's ~/.claude, and Restore puts it back there.
func DeleteGateway ¶ added in v0.1.1151
DeleteGateway deletes a gateway session as described above: last is its last request as listed. One that had a request in the last minute may still be going on, and is left (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
¶
- alias.go
- alma.go
- call_cache.go
- call_continuation.go
- calls.go
- calls_agy.go
- calls_dsh.go
- calls_kimi.go
- calls_minimax.go
- calls_opencode.go
- calls_pi.go
- calls_workbuddy.go
- calls_zcode.go
- carry.go
- claude.go
- claude_usage.go
- cline.go
- codex.go
- codex_discovery.go
- codex_fingerprint.go
- codex_portable.go
- codex_provider.go
- codex_titles.go
- codex_usage.go
- content.go
- cursor.go
- cursor_clone_other.go
- cursor_editor.go
- cursor_snapshot.go
- desktop_titles.go
- discovery.go
- droid.go
- dsh.go
- external.go
- frames.go
- gateway.go
- gateway_delete.go
- grok.go
- hermes.go
- hermes_display.go
- kimi.go
- listmemo.go
- manage.go
- manage_other.go
- markdown.go
- omp.go
- opencode.go
- pi.go
- pidesktop_titles.go
- qoder.go
- quiet.go
- relocate_claude.go
- revision_cache.go
- rollup.go
- search.go
- sessions.go
- shelf.go
- stats.go
- subagents.go
- tail.go
- traces.go
- traces_claude.go
- traces_codex.go
- traces_gemini.go
- traces_identity.go
- traces_opencode.go
- traces_opencode_db.go
- traces_snapshot.go
- transcript.go
- transcript_kimi.go
- transcript_opencode.go
- workbuddy.go
- wsl.go
- zcode.go