cc

package
v0.19.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 10, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package cc reads Claude Code session transcripts (the JSONL files under ~/.claude/projects/<encoded-path>/<session-id>.jsonl) and turns them into compact, TOON-friendly digests. It is a Context Provider: a single 2-4 MB transcript costs ~hundreds of thousands of tokens to read raw, while a `sf cc show` digest is a few hundred — the per-session intent, tool histogram, real token usage, files touched, and token-heavy results.

Two views are exposed:

  • `sf cc ls` — an index of sessions across all projects.
  • `sf cc show` — a one-screen digest of a single session.

Unlike `sf history` (which reads sofia's *own* call log), cc reads the agent's transcripts, so the two are siblings: one measures the tools, the other measures the sessions that drove them.

quota.go implements `sf cc value --quota`: a "subscription quota stretcher" report. Unlike the rest of this file (which reads Claude Code session transcripts and converts to $), the quota report reads sf's OWN telemetry — calllog.Read(), the same calls.jsonl `sf history` reads — and asks a different question: on a Claude subscription plan there's no $ to save (it's a flat fee), the thing that actually runs out is the rolling 5-hour usage window, so what matters is how many output tokens sf handed back instead of the agent paying full price for a raw read/grep/diff.

Index

Constants

View Source
const (
	CatSearch = "search" // grep/rg/find/fd — locating things
	CatRead   = "read"   // cat/head/tail/less — reading file content
	CatGit    = "git"    // version control
	CatTest   = "test"   // running test suites
	CatBuild  = "build"  // compile / install / bundle
	CatDB     = "db"     // database & migrations
	CatFS     = "fs"     // create/move/delete/inspect files
	CatOther  = "other"
)

Category labels for bash commands. They answer "what was the agent doing at the shell" — a classifier for commands instead of file paths.

View Source
const ProjectsDirKey = "CC_PROJECTS_DIR"

ProjectsDirKey is the env/.env key holding the Claude Code projects root.

View Source
const QuotaWindow = 5 * time.Hour

QuotaWindow is the busiest-window span the report scans for: 5 hours is the Claude subscription's own rolling quota window, so "which 5h span burned the most tokens sf just saved you" is the direct answer to "where did --quota actually stretch my usage."

Variables

This section is empty.

Functions

func Categorize

func Categorize(cmd string) string

Categorize classifies a single shell command. Compound commands (`cd x && grep ...`) are matched against the whole string, so the most specific rule still wins.

func NewCommand

func NewCommand() *cobra.Command

NewCommand returns the `cc` command group (ls, show), wired into the root command tree the same way every other tool group is in internal/cli.

func ProjectsDir

func ProjectsDir(flagValue string) (string, error)

ProjectsDir resolves the Claude Code projects root: flag, then $CC_PROJECTS_DIR (.env or process env), then ~/.claude/projects. The default is correct on virtually every install, so cc never prompts.

func ResolveSelector

func ResolveSelector(projectsDir, sel string) (string, error)

ResolveSelector maps a human selector to a single transcript path:

""/"last"      → most recently modified session anywhere
*.jsonl / path → that file directly
<uuid-prefix>  → newest session whose file name starts with the selector
<project>      → newest session whose project dir name contains the selector

Resolution mirrors how xref resolves constant names: try the precise interpretation first, fall back to the fuzzy one.

func RunBash

func RunBash(w io.Writer, projectsDir, selector, category string, minCount, limit int, full bool, format string) error

RunBash is the `sf cc bash` entry point used by the MCP server.

func RunCandidates

func RunCandidates(w io.Writer, projectsDir, selector, project, since string, minCount, limit int, format string) error

RunCandidates is the `sf cc candidates` entry point used by the MCP server. With a selector it scans one session; without, it scans a project/time window like the CLI does.

func RunLs

func RunLs(w io.Writer, projectsDir, project, since string, limit int, format string) error

RunLs is the `sf cc ls` entry point used by the MCP server.

func RunPrompts

func RunPrompts(w io.Writer, projectsDir, selector, format string) error

RunPrompts is the `sf cc prompts` entry point used by the MCP server.

func RunResume

func RunResume(w io.Writer, projectsDir, selector, format string) error

RunResume is the `sf cc resume` entry point used by the MCP server.

func RunShow

func RunShow(w io.Writer, projectsDir, selector, format string) error

RunShow is the `sf cc show` entry point used by the MCP server.

Types

type BashCmd

type BashCmd struct {
	Count    int    `json:"count"`
	Category string `json:"category"`
	Command  string `json:"command"`
}

BashCmd is one deduplicated command with its frequency and category.

type Brief

type Brief struct {
	Project  string      `json:"project"`
	Branch   string      `json:"branch"`
	Session  string      `json:"session"`
	Age      string      `json:"age,omitempty"`
	Messages int         `json:"messages"`
	Goal     string      `json:"goal,omitempty"`
	Now      string      `json:"now,omitempty"`
	Next     string      `json:"next,omitempty"`
	Files    []FileTouch `json:"files,omitempty"`
}

Brief is the compact resume payload — a handful of fields, each capped, so the whole thing is a few hundred tokens regardless of session size.

type Candidates

type Candidates struct {
	Scanned          int            `json:"scanned_sessions"`
	HeavyTools       []HeavyTool    `json:"heavy_tools"`
	RepeatedCommands []RepeatedCmd  `json:"repeated_commands"`
	RepeatedReads    []RepeatedRead `json:"repeated_reads"`
}

Candidates is the full result of a scan.

type CategoryCount

type CategoryCount struct {
	Category string `json:"category"`
	Calls    int    `json:"calls"`
	Unique   int    `json:"unique,omitempty"`
}

CategoryCount is one row of the bash-category breakdown. Unique counts distinct commands in the category (set by `bash`; 0/omitted in `show`).

type FatResult

type FatResult struct {
	Tokens int64  `json:"tokens"`
	Tool   string `json:"tool"`
	Brief  string `json:"brief"`
}

FatResult is a single token-heavy tool result — a compaction candidate.

type FileTouch

type FileTouch struct {
	Path   string `json:"path"`
	Reads  int    `json:"reads"`
	Edits  int    `json:"edits"`
	Writes int    `json:"writes"`
}

FileTouch counts how a path was accessed within a session.

type HeavyTool

type HeavyTool struct {
	Tool         string `json:"tool"`
	Calls        int    `json:"calls"`
	ResultTokens int64  `json:"result_tokens"`
	Suggestion   string `json:"suggestion,omitempty"`
}

HeavyTool aggregates one tool's footprint across the scanned sessions.

type LsRow

type LsRow struct {
	ID        string    `json:"id"`
	Project   string    `json:"project"`
	Title     string    `json:"title"`
	Updated   time.Time `json:"updated"`
	Messages  int       `json:"messages"`
	Prompts   int       `json:"prompts"`
	OutTokens int64     `json:"out_tokens"`
	CacheRead int64     `json:"cache_read"`
	Branch    string    `json:"branch"`
	PRs       int       `json:"prs"`
	SizeBytes int64     `json:"size_bytes"`
}

LsRow is one line of the session index.

type ModelPrice

type ModelPrice struct {
	Input      float64 // $ / 1M base (uncached) input tokens
	Output     float64 // $ / 1M output tokens
	CacheWrite float64 // $ / 1M cache-creation tokens (5-minute TTL)
	CacheRead  float64 // $ / 1M cache-read tokens
}

ModelPrice is USD price per 1,000,000 tokens, by token type, for one Claude model.

type ModelUsage

type ModelUsage struct {
	Model    string  `json:"model"`
	Sessions int     `json:"sessions"`
	Tokens   int64   `json:"tokens"`
	CostUSD  float64 `json:"cost_usd"`
	Priced   bool    `json:"priced"`
}

ModelUsage aggregates one model's sessions/tokens/cost within the current window.

type PR

type PR struct {
	Number int    `json:"number"`
	URL    string `json:"url"`
}

PR is a pull request surfaced in the transcript.

type Period

type Period struct {
	Since          time.Time       `json:"since"`
	Until          time.Time       `json:"until"`
	Sessions       int             `json:"sessions"`
	CostUSD        float64         `json:"cost_usd"`
	ByType         []TokenTypeCost `json:"by_type"`
	UnpricedTokens int64           `json:"unpriced_tokens,omitempty"`
}

Period is one time window's aggregate: $ cost and a token-type breakdown. UnpricedTokens is the token volume from sessions whose model isn't in modelPrices — real usage, just not converted to $.

type Quota added in v0.3.0

type Quota struct {
	Days           int       `json:"days"`
	Since          time.Time `json:"since"`
	Until          time.Time `json:"until"`
	Calls          int       `json:"calls"`
	WithBaseline   int       `json:"with_baseline"` // calls whose summary carries tok_raw or tok_rep
	DedupStubs     int       `json:"dedup_stubs"`
	EmittedTokens  int64     `json:"emitted_tokens"`  // Σ out_tokens across Calls
	BaselineTokens int64     `json:"baseline_tokens"` // Σ tok_raw/tok_rep across WithBaseline
	SavedTokens    int64     `json:"saved_tokens"`    // Σ max(baseline-emitted, 0)
	SavedPct       float64   `json:"saved_pct"`       // SavedTokens / BaselineTokens * 100
	BusiestStart   time.Time `json:"busiest_start,omitempty"`
	BusiestSaved   int64     `json:"busiest_saved,omitempty"` // saved tokens inside that QuotaWindow
}

Quota is the aggregate `sf cc value --quota` renders. Pure data — built by buildQuota, independent of how it's read or rendered.

type RepeatedCmd

type RepeatedCmd struct {
	Count    int    `json:"count"`
	Sessions int    `json:"sessions"`
	Category string `json:"category"`
	Command  string `json:"command"`
}

RepeatedCmd is an identical shell command seen more than once.

type RepeatedRead

type RepeatedRead struct {
	Reads    int    `json:"reads"`
	Sessions int    `json:"sessions"`
	Path     string `json:"path"`
}

RepeatedRead is a file read more than once.

type Session

type Session struct {
	Path      string    `json:"path"`
	ID        string    `json:"id"`      // short id (uuid prefix)
	FullID    string    `json:"full_id"` // full session UUID
	Project   string    `json:"project"` // basename of cwd
	Cwd       string    `json:"cwd"`
	Branch    string    `json:"branch"`
	Model     string    `json:"model"`
	Version   string    `json:"version"`
	Title     string    `json:"title"`
	Start     time.Time `json:"-"` // surfaced as RFC3339 strings by the json renderer
	End       time.Time `json:"-"`
	Messages  int       `json:"messages"`
	SizeBytes int64     `json:"size_bytes"`

	UserPrompts []string `json:"user_prompts"`
	LastText    string   `json:"last_text,omitempty"` // last assistant narrative — the "next step"

	ToolCalls        map[string]int   `json:"tool_calls"`
	ToolResultTokens map[string]int64 `json:"tool_result_tokens"`
	Bash             []string         `json:"-"`
	Files            []FileTouch      `json:"files"`
	FatResults       []FatResult      `json:"fat_results"`

	OutputTokens      int64 `json:"output_tokens"`
	InputTokens       int64 `json:"input_tokens"`
	CacheReadTokens   int64 `json:"cache_read_tokens"`
	CacheCreateTokens int64 `json:"cache_create_tokens"`
	DurationMs        int64 `json:"duration_ms"`

	PRs []PR `json:"prs"`
}

Session is the parsed digest of one transcript.

func Parse

func Parse(path string, collectDetail bool) (*Session, error)

Parse reads a transcript and builds a Session. When collectDetail is false the heavy per-call slices (Bash, Files, FatResults) are skipped — `sf cc ls` only needs the aggregate counters and usage totals.

func (*Session) BashCategories

func (s *Session) BashCategories() []CategoryCount

BashCategories returns counts of bash commands per category, desc.

func (*Session) SortedTools

func (s *Session) SortedTools() []ToolCount

SortedTools returns the tool histogram ordered by call count desc.

func (*Session) Span

func (s *Session) Span() time.Duration

Span returns the wall-clock duration of the session.

type SessionFile

type SessionFile struct {
	Path    string    // absolute path to the .jsonl
	Stem    string    // file name without .jsonl (the session UUID)
	DirName string    // encoded project dir name, e.g. -home-user-www-myapp
	ModTime time.Time // file mtime — cheap recency signal
	Size    int64
}

SessionFile is a discovered transcript on disk, before parsing.

type TokenTypeCost

type TokenTypeCost struct {
	Type    string  `json:"type"`
	Tokens  int64   `json:"tokens"`
	CostUSD float64 `json:"cost_usd"`
}

TokenTypeCost is one token type's aggregate volume and priced $ within a period.

type ToolCount

type ToolCount struct {
	Tool         string `json:"tool"`
	Calls        int    `json:"calls"`
	ResultTokens int64  `json:"result_tokens"`
}

ToolCount is one row of the tool histogram, sorted for rendering.

type Value

type Value struct {
	Current  Period       `json:"current"`
	Previous Period       `json:"previous"`
	DeltaUSD float64      `json:"delta_usd"`
	DeltaPct float64      `json:"delta_pct,omitempty"`
	ByModel  []ModelUsage `json:"by_model"`
}

Value is the full result of `sf cc value`: the current window vs the preceding window of equal length, the $ delta between them, and a per-model breakdown of the current window.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL