Session logging for Claude Code
Project description
agentlog
session logging for Claude Code.
agentlog captures the context behind your code -- prompts, tool calls, and file changes made by Claude Code -- and stores them in your project as a permanent record.
Core concept
Every agent session writes a structured log file to .agentlog/sessions/ in your repo root. Logs are append-only JSONL (one JSON object per line), one file per session. Each file captures:
- User messages -- the prompts you gave the agent
- Assistant responses -- what the agent said and reasoned
- Tool calls -- what the agent did (file writes, shell commands, searches)
- File changes -- which files were created, modified, or deleted, with line deltas
- Session metadata -- timestamp
Security note. Session logs can capture sensitive content: credentials in prompts, secrets in tool output, private code, and internal queries.
log_tool_resultsis off by default for this reason. Review what you commit before sharing.agentlog/with others, and consider keeping it in.gitignorefor private or regulated repos.
.agentlog/
README.md ← explains the folder to any newcomer
config.json ← local config
sessions/
2025-03-10_143022123456_def456ab.jsonl ← one file per agent conversation
2025-03-10_091455887032_abc123de.jsonl
Filenames are <timestamp>_<session-id>.jsonl where the timestamp includes microseconds (YYYY-MM-DD_HHMMSSffffff) to prevent collisions between rapid hook calls, and the session ID is the first 8 characters of the agent's native conversation ID. Each new conversation — including after /clear — creates a new file.
Session file format
{"v":1,"type":"session_start","t":"2025-03-10T14:30:22Z","agent":"claude","session":"def456ab"}
{"v":1,"type":"user_msg","t":"2025-03-10T14:30:45Z","content":"refactor the auth module to use JWT"}
{"v":1,"type":"assistant_msg","t":"2025-03-10T14:30:52Z","content":"I'll refactor the auth module to use JWT. Let me start by reading the current implementation."}
{"v":1,"type":"tool_call","t":"2025-03-10T14:31:02Z","tool":"write_file","file":"src/auth.ts","op":"modified","lines_delta":42}
{"v":1,"type":"tool_call","t":"2025-03-10T14:31:10Z","tool":"write_file","file":"src/auth.test.ts","op":"created","lines_delta":80}
{"v":1,"type":"assistant_msg","t":"2025-03-10T14:34:58Z","content":"Done. I've replaced the session-based auth with JWT. The token is signed with RS256 and expires in 1 hour. Tests updated."}
{"v":1,"type":"session_end","t":"2025-03-10T14:35:00Z"}
Key design decisions
-
Shard files by session. Each session gets its own file named by timestamp and session ID. Each new conversation — including after
/clear-- creates a new file automatically. -
Agent hooks registered on
agentlog init. Runningagentlog initin a folder writes Claude Code hook configuration scoped to that directory. Hooks are calls back into theagentlogCLI -- no separate packages to install, no global configuration changed.
Features
For solo developers
agentlog log --days 3-- show all logs from last 3 daysagentlog log --file src/auth.ts-- see every agent session that touched a file
Installation & setup
1. Install the CLI
pipx install agentlog
Requires Python 3.9+. pipx installs the CLI into an isolated environment and puts agentlog on your PATH. If you don't have pipx: pip install --user pipx.
2. Configure global defaults (optional)
agentlog reads global defaults from ~/.agentlog/config.json. Create it once and every new repo will inherit these settings:
agentlog config init # writes ~/.agentlog/config.json with defaults
// ~/.agentlog/config.json
{
"log_tool_calls": true,
"log_tool_results": false, // off by default -- output can be large and may contain sensitive data
"log_assistant_messages": true,
"log_user_messages": true,
"content_max_chars": -1, // -1 = no cap; set to a positive integer to truncate at write time
"gitignore": true // add .agentlog/ to .gitignore on init by default
}
3. Initialize a repo
cd your-repo
agentlog init
This registers Claude Code hooks scoped to this directory, creates .agentlog/sessions/, copies your global config into .agentlog/config.json, and adds a README.md inside .agentlog/ explaining the folder to newcomers.
$ agentlog init
✓ Detected: claude
✓ Hooks registered (directory-scoped)
✓ Initialized .agentlog/
✓ Added .agentlog/ to .gitignore
Per-repo config in .agentlog/config.json takes precedence over the global config.
Usage
# View recent sessions
agentlog log
agentlog log --today
agentlog log --days 3
# View sessions for a specific file
agentlog log --file src/auth.ts
# View a specific session in full -- prompts, responses, tool calls
agentlog show <session-id>
# Search across all session content
agentlog search "JWT refactor"
agentlog search "auth" --file src/auth.ts
# Check logging status for the current directory
agentlog status
# Show storage stats
agentlog stats
# Delete old session files
agentlog prune --days 90
agentlog prune --before 2025-01-01
agentlog prune --preview # preview what would be deleted
# Export sessions
agentlog export <session-id>
agentlog export <session-id> --format markdown
agentlog export --all --format json > archive.jsonl
# Remove hooks for the current directory (does not delete .agentlog/)
agentlog stop
Example output
$ agentlog log --days 3
2025-03-10 14:30 def456ab claude 4 tools src/auth.ts src/auth.test.ts
2025-03-10 09:14 abc123de claude 2 tools src/main.ts
2025-03-09 16:45 xyz789fa claude 7 tools src/api.ts src/types.ts src/routes.ts
$ agentlog show def456ab
Session def456ab -- 2025-03-10 14:30 -- agent: claude
────────────────────────────────────────────────────────────────────────
[14:30:45] USER
refactor the auth module to use JWT
[14:30:52] ASSISTANT
I'll refactor the auth module to use JWT. Let me start by reading the
current implementation.
[14:31:02] TOOL write_file src/auth.ts modified +42 lines
[14:31:10] TOOL write_file src/auth.test.ts created +80 lines
[14:34:58] ASSISTANT
Done. I've replaced the session-based auth with JWT. The token is
signed with RS256 and expires in 1 hour. Tests updated.
────────────────────────────────────────────────────────────────────────
$ agentlog status
agentlog initialized: yes
hooks active:
claude ✓ (.claude/settings.json)
sessions: 14 (2.1 MB)
config: .agentlog/config.json
gitignore: yes
Implementation
Architecture
agentlog/
agentlog/
__main__.py -- CLI entry point
repo.py -- walk up from cwd to find .agentlog/ root
session.py -- JSONL writing, file locking, path normalisation
config.py -- load and merge global + local config.json
utils/
time.py -- shared timestamp helpers (now_utc_iso, now_timestamp, parse_*)
session_io.py -- shared read_session() and find_session_file()
hooks/
claude.py -- extract assistant turns from Claude Code transcripts
commands/
hook.py -- user-prompt, pre-tool, post-tool, stop
init.py
stop.py
log.py
show.py
search.py
status.py
stats.py
prune.py
export.py
config.py
The CLI is a Python package installed via pipx. Hook registration writes to .claude/settings.json pointing back to the agentlog CLI -- no separate packages required.
Record capture
| Record | Source |
|---|---|
user_msg |
UserPromptSubmit hook — prompt field passed directly in payload |
tool_call |
PreToolUse hook — file path normalised to repo-root-relative at write time |
tool_result |
PostToolUse hook — only written when log_tool_results: true; linked to its tool_call via call_id |
assistant_msg |
Stop hook — read from transcript_path provided in the payload |
See CLAUDE.md for the full hook integration spec.
File locking
append_record holds an exclusive lock for each write to guard against concurrent hook calls from multiple agent windows in the same repo:
- POSIX (macOS / Linux):
fcntl.flock(LOCK_EX) - Windows:
msvcrt.locking(LK_LOCK)— retries automatically for up to 10 seconds
Content truncation
content_max_chars is applied at write time inside the hooks, not just at display time. This keeps session files small when a cap is configured. The default is -1 (no cap). Set it to a positive integer in config.json to truncate prompts and assistant messages before they are stored.
agentlog prune
Scans .agentlog/sessions/ and deletes JSONL files whose timestamp (parsed from the filename) is older than the specified threshold. --preview prints what would be deleted without removing anything. No daemon or cron required -- prune is a manual, explicit operation.
agentlog export
Reads one or more session JSONL files and writes them to stdout in the requested format:
- json (default) -- re-emits the raw JSONL, suitable for piping or archiving
- markdown -- renders each event as a readable document with headings, code blocks for tool calls, and quoted assistant messages; useful for pasting into docs or issue comments
- text -- plain text, same as
agentlog showbut written to stdout for redirection
--all exports every session in .agentlog/sessions/ in chronological order.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file coding_agent_log-0.1.3.tar.gz.
File metadata
- Download URL: coding_agent_log-0.1.3.tar.gz
- Upload date:
- Size: 30.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3768ce6fc2de14d59a282f208ffcbb600c1c6df4b525577ad37da5e94e056fc
|
|
| MD5 |
0eea3622d0429e86606e21f138260591
|
|
| BLAKE2b-256 |
edaa25e07227e4d9001b6e029a875d5ab72a1075b6926671397c5eaea382a1a2
|
Provenance
The following attestation bundles were made for coding_agent_log-0.1.3.tar.gz:
Publisher:
publish.yml on minghanminghan/agent-log
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
coding_agent_log-0.1.3.tar.gz -
Subject digest:
b3768ce6fc2de14d59a282f208ffcbb600c1c6df4b525577ad37da5e94e056fc - Sigstore transparency entry: 1082553208
- Sigstore integration time:
-
Permalink:
minghanminghan/agent-log@a819525c97aa15c0e1433d0637a3b4011f637b5d -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/minghanminghan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a819525c97aa15c0e1433d0637a3b4011f637b5d -
Trigger Event:
push
-
Statement type:
File details
Details for the file coding_agent_log-0.1.3-py3-none-any.whl.
File metadata
- Download URL: coding_agent_log-0.1.3-py3-none-any.whl
- Upload date:
- Size: 27.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
734e7207b4fcce909e7e94f8e797b72627b7fd923dcab99e70d9598d5ff3ec46
|
|
| MD5 |
2377cef1ee3f40d86c11f05bcd5b8b92
|
|
| BLAKE2b-256 |
2a1605dc70ed09d76420b4a624b334c109cf067ca1bd5e0b7e059297cd89766f
|
Provenance
The following attestation bundles were made for coding_agent_log-0.1.3-py3-none-any.whl:
Publisher:
publish.yml on minghanminghan/agent-log
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
coding_agent_log-0.1.3-py3-none-any.whl -
Subject digest:
734e7207b4fcce909e7e94f8e797b72627b7fd923dcab99e70d9598d5ff3ec46 - Sigstore transparency entry: 1082553264
- Sigstore integration time:
-
Permalink:
minghanminghan/agent-log@a819525c97aa15c0e1433d0637a3b4011f637b5d -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/minghanminghan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a819525c97aa15c0e1433d0637a3b4011f637b5d -
Trigger Event:
push
-
Statement type: