Documentation
¶
Index ¶
- func FormatUSD(microdollars int64) string
- func Recompute(ctx context.Context, store *Store, pricer *Pricer, dryRun bool) (updated, skipped int, err error)
- func RenderCostLine(template string, vars map[string]int64, hideWhenZero bool) string
- type BudgetAction
- type BudgetChecker
- type BudgetConfig
- type BudgetResult
- type ClaudeHookParser
- type Collector
- type CostEvent
- type CostEventWatcher
- type CostPoller
- type CostSummary
- type DailyCost
- type Fetcher
- type GeminiOutputParser
- type MiniMaxOutputParser
- type ModelPrice
- type OpenAIOutputParser
- type Parser
- type PriceOverride
- type Pricer
- type PricerConfig
- type RawCostEvent
- type SessionCost
- type Store
- func (s *Store) ApplyCostUpdates(ctx context.Context, updates map[string]int64) error
- func (s *Store) CostByModel() (map[string]int64, error)
- func (s *Store) CostByModelForSession(sessionID string) (map[string]int64, error)
- func (s *Store) DB() *sql.DB
- func (s *Store) DailyBySession(sessionID string, from, to time.Time) ([]DailyCost, error)
- func (s *Store) GlobalRunningTotal(tx *sql.Tx, since time.Time) (int64, error)
- func (s *Store) GroupRunningTotal(tx *sql.Tx, sessionIDs []string, since time.Time) (int64, error)
- func (s *Store) PageEventsAfter(afterRowID int64, limit int) ([]CostEvent, int64, error)
- func (s *Store) ProjectedMonthly() (int64, error)
- func (s *Store) PurgeOlderThan(days int) (int64, error)
- func (s *Store) RunningTotal(tx *sql.Tx, sessionID string, since time.Time) (int64, error)
- func (s *Store) TopSessionsByCost(limit int) ([]SessionCost, error)
- func (s *Store) TotalByDateRange(from, to time.Time) ([]DailyCost, error)
- func (s *Store) TotalBySession(sessionID string) (CostSummary, error)
- func (s *Store) TotalLastMonth() (CostSummary, error)
- func (s *Store) TotalLastWeek() (CostSummary, error)
- func (s *Store) TotalThisMonth() (CostSummary, error)
- func (s *Store) TotalThisWeek() (CostSummary, error)
- func (s *Store) TotalToday() (CostSummary, error)
- func (s *Store) TotalYesterday() (CostSummary, error)
- func (s *Store) WriteCostEvent(ev CostEvent) error
- func (s *Store) WriteCostEventTx(tx *sql.Tx, ev CostEvent) error
- type SyncResult
- type SyncSession
- type TranscriptEntry
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Recompute ¶ added in v1.7.73
func Recompute(ctx context.Context, store *Store, pricer *Pricer, dryRun bool) (updated, skipped int, err error)
Recompute walks every cost_events row in `store`, recalculates cost_microdollars using `pricer`, and writes any differences back. It is idempotent: a second run with no pricing data changes returns updated=0.
Rows whose `model` is unknown to the pricer are left untouched and counted as skipped (writing 0 over an existing positive cost would lose data).
When dryRun is true no UPDATE is executed; the returned counts describe what would change.
func RenderCostLine ¶ added in v1.7.75
RenderCostLine substitutes {name} placeholders in template with values drawn from vars and formatted as USD via FormatUSD. Recognized placeholders whose value is non-zero count toward "non-empty"; unknown placeholders pass through literally so typos are visible.
When hideWhenZero is true and zero recognized placeholders rendered to a non-zero value (either none were recognized at all, or all recognized values were zero), the empty string is returned. This preserves the "no events, no segment" behavior of the legacy hardcoded status-bar.
The walker is left-to-right and never iterates the vars map, so output is deterministic regardless of map iteration order.
Types ¶
type BudgetAction ¶
type BudgetAction int
const ( BudgetActionNone BudgetAction = iota BudgetActionWarn BudgetActionStop )
type BudgetChecker ¶
type BudgetChecker struct {
// contains filtered or unexported fields
}
func NewBudgetChecker ¶
func NewBudgetChecker(cfg BudgetConfig, store *Store) *BudgetChecker
func (*BudgetChecker) Check ¶
func (b *BudgetChecker) Check(sessionID, groupName string) BudgetResult
Check is a convenience for non-transactional checks (e.g., TUI display).
func (*BudgetChecker) CheckTx ¶
func (b *BudgetChecker) CheckTx(tx *sql.Tx, sessionID, groupName string, groupSessionIDs []string) (BudgetResult, error)
CheckTx evaluates all budget limits within a transaction. This must be called within the same transaction as the cost event INSERT.
type BudgetConfig ¶
type BudgetConfig struct {
DailyLimit int64
WeeklyLimit int64
MonthlyLimit int64
GroupLimits map[string]int64 // group name -> daily limit in microdollars
SessionLimits map[string]int64 // session ID -> total lifetime limit in microdollars
Timezone *time.Location // for determining day/week/month boundaries
}
BudgetConfig holds budget limits in microdollars.
type BudgetResult ¶
type BudgetResult struct {
Action BudgetAction
Reason string
UsedMicro int64
LimitMicro int64
Percentage float64
}
type ClaudeHookParser ¶
type ClaudeHookParser struct {
// contains filtered or unexported fields
}
ClaudeHookParser parses Claude Code Stop hook JSON payloads.
func (*ClaudeHookParser) CanParse ¶
func (p *ClaudeHookParser) CanParse(toolType string) bool
func (*ClaudeHookParser) Name ¶
func (p *ClaudeHookParser) Name() string
type Collector ¶
type Collector struct {
// contains filtered or unexported fields
}
Collector routes tool output to the appropriate parser and applies pricing.
func NewCollector ¶
NewCollector creates a Collector with all registered parsers.
type CostEvent ¶
type CostEvent struct {
ID string
SessionID string
Timestamp time.Time
Model string
InputTokens int64
OutputTokens int64
CacheReadTokens int64
CacheWriteTokens int64
CostMicrodollars int64 // 1 USD = 1,000,000 microdollars
}
CostEvent represents a single token usage and cost record.
type CostEventWatcher ¶
type CostEventWatcher struct {
// contains filtered or unexported fields
}
CostEventWatcher watches a directory for new cost event JSON files.
func NewCostEventWatcher ¶
func NewCostEventWatcher(dir string) (*CostEventWatcher, error)
NewCostEventWatcher creates a watcher for the given directory.
func (*CostEventWatcher) EventCh ¶
func (w *CostEventWatcher) EventCh() <-chan RawCostEvent
EventCh returns the channel that emits parsed cost events.
func (*CostEventWatcher) Start ¶
func (w *CostEventWatcher) Start()
Start begins watching for file events. Blocks until stopped.
func (*CostEventWatcher) Stop ¶
func (w *CostEventWatcher) Stop()
Stop cancels the watcher and closes resources.
type CostPoller ¶
type CostPoller struct {
// contains filtered or unexported fields
}
CostPoller polls tmux capture-pane for non-hook tools and extracts cost events.
func NewCostPoller ¶
func NewCostPoller(collector *Collector) *CostPoller
NewCostPoller creates a poller with deduplication.
type CostSummary ¶
type CostSummary struct {
TotalCostMicrodollars int64
TotalInputTokens int64
TotalOutputTokens int64
TotalCacheReadTokens int64
TotalCacheWriteTokens int64
EventCount int
}
CostSummary aggregates cost data.
type Fetcher ¶
func (*Fetcher) FetchAndCache ¶
FetchAndCache writes current known prices to cache. Real HTML scraping is deferred — for now, writes hardcoded defaults.
func (*Fetcher) StartDaily ¶
StartDaily runs the fetch loop. Blocks until context is cancelled.
type GeminiOutputParser ¶
type GeminiOutputParser struct {
// contains filtered or unexported fields
}
GeminiOutputParser parses Gemini CLI token usage output.
func (*GeminiOutputParser) CanParse ¶
func (p *GeminiOutputParser) CanParse(toolType string) bool
func (*GeminiOutputParser) Name ¶
func (p *GeminiOutputParser) Name() string
type MiniMaxOutputParser ¶ added in v1.3.1
type MiniMaxOutputParser struct {
// contains filtered or unexported fields
}
MiniMaxOutputParser parses MiniMax CLI/tool token usage output.
func (*MiniMaxOutputParser) CanParse ¶ added in v1.3.1
func (p *MiniMaxOutputParser) CanParse(toolType string) bool
func (*MiniMaxOutputParser) Name ¶ added in v1.3.1
func (p *MiniMaxOutputParser) Name() string
type ModelPrice ¶
type ModelPrice struct {
InputPerMtokMicro int64
OutputPerMtokMicro int64
CacheReadPerMtokMicro int64
CacheWritePerMtokMicro int64
}
ModelPrice holds per-model pricing in microdollars per million tokens.
type OpenAIOutputParser ¶
type OpenAIOutputParser struct {
// contains filtered or unexported fields
}
OpenAIOutputParser parses OpenAI/Codex CLI token usage output.
func (*OpenAIOutputParser) CanParse ¶
func (p *OpenAIOutputParser) CanParse(toolType string) bool
func (*OpenAIOutputParser) Name ¶
func (p *OpenAIOutputParser) Name() string
type Parser ¶
type Parser interface {
Name() string
CanParse(toolType string) bool
Parse(input string) ([]CostEvent, error)
}
Parser parses tool output into cost events.
type PriceOverride ¶
type PriceOverride struct {
InputPerMtok float64 `toml:"input_per_mtok"`
OutputPerMtok float64 `toml:"output_per_mtok"`
CacheReadPerMtok float64 `toml:"cache_read_per_mtok"`
CacheWritePerMtok float64 `toml:"cache_write_per_mtok"`
}
PriceOverride holds user-configured pricing in USD per million tokens.
type Pricer ¶
type Pricer struct {
// contains filtered or unexported fields
}
Pricer resolves model pricing with fallback: override > cache > hardcoded.
func NewPricer ¶
func NewPricer(cfg PricerConfig) *Pricer
NewPricer creates a Pricer with hardcoded defaults and optional overrides.
func (*Pricer) ComputeCost ¶
ComputeCost calculates cost in microdollars for token usage on a model.
func (*Pricer) GetPrice ¶
func (p *Pricer) GetPrice(model string) (ModelPrice, bool)
GetPrice returns the price for a model with fallback: override > cache > hardcoded.
type PricerConfig ¶
type PricerConfig struct {
CachePath string
Overrides map[string]PriceOverride
}
PricerConfig configures the Pricer.
type RawCostEvent ¶
type RawCostEvent struct {
InstanceID string `json:"instance_id"`
Model string `json:"model"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
CacheReadTokens int64 `json:"cache_read_tokens"`
CacheWriteTokens int64 `json:"cache_write_tokens"`
Timestamp int64 `json:"ts"`
}
RawCostEvent is the JSON structure written by hook_handler.
type SessionCost ¶
type SessionCost struct {
SessionID string
SessionTitle string
Group string
CostMicrodollars int64
EventCount int
}
SessionCost represents per-session cost totals.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store persists and queries cost events in SQLite.
func (*Store) ApplyCostUpdates ¶ added in v1.7.73
ApplyCostUpdates writes a batch of cost_microdollars updates within a single transaction. The map key is cost_event id. Returns an error and rolls back on any failure; on success commits and returns nil.
func (*Store) CostByModel ¶
CostByModel returns total cost per model.
func (*Store) CostByModelForSession ¶
CostByModelForSession returns cost per model for a specific session.
func (*Store) DailyBySession ¶
DailyBySession returns daily costs for a specific session.
func (*Store) GlobalRunningTotal ¶
GlobalRunningTotal returns the sum of all costs within a time window (for use in a transaction).
func (*Store) GroupRunningTotal ¶
GroupRunningTotal returns the sum of costs for a set of sessions within a time window.
func (*Store) PageEventsAfter ¶ added in v1.7.73
PageEventsAfter returns up to `limit` cost_events with rowid > afterRowID, ordered by rowid ascending, plus the rowid of the last returned row (or afterRowID itself if no rows were returned). Use 0 as the initial afterRowID. Cursor-based pagination is stable under concurrent inserts.
func (*Store) ProjectedMonthly ¶
ProjectedMonthly estimates monthly spend based on rolling 7-day average.
func (*Store) PurgeOlderThan ¶
PurgeOlderThan deletes events older than the given number of days. Returns count deleted.
func (*Store) RunningTotal ¶
RunningTotal returns the sum of costs for a session within a time window (for use in a transaction).
func (*Store) TopSessionsByCost ¶
func (s *Store) TopSessionsByCost(limit int) ([]SessionCost, error)
TopSessionsByCost returns the top N sessions by total cost. Joins with instances table to get session titles and groups.
func (*Store) TotalByDateRange ¶
TotalByDateRange returns daily costs within a date range.
func (*Store) TotalBySession ¶
func (s *Store) TotalBySession(sessionID string) (CostSummary, error)
TotalBySession returns aggregated costs for a session.
func (*Store) TotalLastMonth ¶ added in v1.7.75
func (s *Store) TotalLastMonth() (CostSummary, error)
TotalLastMonth returns the prior calendar month's total costs.
func (*Store) TotalLastWeek ¶ added in v1.7.75
func (s *Store) TotalLastWeek() (CostSummary, error)
TotalLastWeek returns the prior ISO-week's total costs (Monday start), mirroring the boundary semantics of TotalThisWeek.
func (*Store) TotalThisMonth ¶
func (s *Store) TotalThisMonth() (CostSummary, error)
TotalThisMonth returns this month's total costs.
func (*Store) TotalThisWeek ¶
func (s *Store) TotalThisWeek() (CostSummary, error)
TotalThisWeek returns this week's total costs (Monday start).
func (*Store) TotalToday ¶
func (s *Store) TotalToday() (CostSummary, error)
TotalToday returns today's total costs.
func (*Store) TotalYesterday ¶ added in v1.7.75
func (s *Store) TotalYesterday() (CostSummary, error)
TotalYesterday returns the prior day's total costs (00:00:00 UTC of yesterday inclusive to 00:00:00 UTC of today exclusive).
func (*Store) WriteCostEvent ¶
WriteCostEvent inserts a cost event.
type SyncResult ¶
SyncResult holds the result of a historical sync operation.
func SyncFromTranscripts ¶
func SyncFromTranscripts(store *Store, pricer *Pricer, sessions []SyncSession) SyncResult
SyncFromTranscripts reads historical usage from Claude transcript files and backfills cost_events for managed sessions.
type SyncSession ¶
SyncSession holds the info needed to locate a session's transcript.
type TranscriptEntry ¶
type TranscriptEntry struct {
Type string `json:"type"`
UUID string `json:"uuid"`
Message struct {
Model string `json:"model"`
Usage struct {
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
CacheCreationInputTokens int64 `json:"cache_creation_input_tokens"`
CacheReadInputTokens int64 `json:"cache_read_input_tokens"`
} `json:"usage"`
} `json:"message"`
// Progress entries nest usage inside data.message.message
Data *progressData `json:"data,omitempty"`
Timestamp string `json:"timestamp"` // ISO 8601
}
TranscriptEntry represents one line of a Claude transcript JSONL file. Handles both "assistant" entries (direct usage) and "progress" entries (subagent usage).