Class: Agent::Sessions::Adapters::Claude

Inherits:
Base
  • Object
show all
Defined in:
lib/agent/sessions/adapters/claude.rb

Constant Summary collapse

DEFAULT_CLEANUP_PERIOD_DAYS =
30

Constants inherited from Base

Base::FIDELITIES

Constants included from Enumeration

Enumeration::MAX_LINE_BYTES

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#base_dir, fidelity_value, homedir_config, #initialize, #locate, store_configs, #verify

Methods included from Enumeration

#project_dir_name, #project_paths, #session_id_from, #sessions, #sessions_for_project, #started_at_for, #updated_at_for

Constructor Details

This class inherits a constructor from Agent::Sessions::Adapters::Base

Class Method Details

.reader_classObject



18
# File 'lib/agent/sessions/adapters/claude.rb', line 18

def self.reader_class = Readers::Claude

Instance Method Details

#bytes_for(path, stat) ⇒ Object

Claude Code writes a directory beside each transcript, named after the session id with the extension dropped: subagents/ holds the transcripts of agents this session spawned, tool-results/ holds tool output too large to inline. Those bytes are this session's, and until they were counted du reported 122.1 MB for a store audit reported 173.0 MB for — 71% — because audit sums the store directory whole while du sums sessions. Two commands, one directory, a 29% disagreement.

Measured over 128 real sessions on 2026-08-10: 0.002 ms per session when there is no sidecar (one stat, the common case on a fresh install) and 0.080 ms when there is. That is under half what project_path's content read costs, and unlike project_path this cannot be deferred — bytes is eager, and a lazily-corrected byte total would leave list printing one number while du summed another.



81
82
83
# File 'lib/agent/sessions/adapters/claude.rb', line 81

def bytes_for(path, stat)
  stat.size + sidecar_bytes(path)
end

#encode_project(dir) ⇒ Object

Every non-alphanumeric character becomes "-" (design doc section 7). dir must already be absolute and expanded — sessions_for_project guarantees that; a direct caller passing "app", "~/app", or a trailing slash gets a nonsense encoding (see Base#encode_project). Verified against real project directories on 2026-08-05: /Users/dev/.local -> -Users-dev--local



44
45
46
# File 'lib/agent/sessions/adapters/claude.rb', line 44

def encode_project(dir)
  dir.gsub(/[^a-zA-Z0-9]/, "-")
end

#project_path_for(path) ⇒ Object

cwd is NOT on line 1. Real sessions open with a kebab-case preamble (ai-title, agent-name, mode, permission-mode) followed by a variable-length run of file-history-snapshot records — that run is what pushes the first cwd-bearing record out further on some files, and nothing bounds its length. Observed on this machine on 2026-08-05: line 3 (19 files), line 4 (48 files), line 9 (1 file, a longer snapshot run). limit: 25 is ~2.8x that observed maximum — headroom for the variable-length run, not a tight fit to the common case — and keeps this a few-KB read even on multi-GB files.

The block guards against a record that carries "cwd" but not usably: null shadows a later valid record, and a wrong type (Integer, Hash) would otherwise reach project_paths' .uniq.sort and raise there. scan_jsonl_for_key already guarantees the key is present once the block accepts, so a plain fetch (no default) is safe.



63
64
65
# File 'lib/agent/sessions/adapters/claude.rb', line 63

def project_path_for(path)
  scan_jsonl_for_key(path, "cwd", limit: 25) { |record| record["cwd"].is_a?(String) }&.fetch("cwd")
end

#retentionObject



22
23
24
# File 'lib/agent/sessions/adapters/claude.rb', line 22

def retention
  configured_retention || DEFAULT_CLEANUP_PERIOD_DAYS
end

#retention_sourceObject



26
27
28
# File 'lib/agent/sessions/adapters/claude.rb', line 26

def retention_source
  configured_retention ? :setting : :default
end

#warningsObject



30
31
32
33
34
35
36
# File 'lib/agent/sessions/adapters/claude.rb', line 30

def warnings
  list = super
  if env_active?("CLAUDE_CODE_SKIP_PROMPT_HISTORY")
    list << "CLAUDE_CODE_SKIP_PROMPT_HISTORY is set: history.jsonl is not being written"
  end
  list
end