Skip to content

mpagot/llm_log_digest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

llm_log_digest

A CLI tool for parsing, browsing, and analysing the history of LLM coding-agent sessions. Supports two providers out of the box:

Provider Storage location
Gemini CLI ~/.gemini/tmp/<project>/chats/*.json
OpenCode ~/.local/share/opencode/opencode.db (SQLite)

Requirements

Python 3.10+ (uses the X | Y union-type syntax). No third-party dependencies.

python3 main.py <subcommand> [options]

Recommended workflow

The subcommands form a natural drill-down:

list-projects                    # discover all projects and their Project IDs
  └─ list-sessions <project-id>  # list sessions for one project
       └─ show-session <project-id> <session-id>  # read a single conversation
            └─ stats / search / daily-digest       # aggregate or search

The Project ID column from list-projects is the exact token you pass to every other subcommand. The Session File / Session ID column from list-sessions is the token you pass to show-session and stats --session.


Project ID reference

Every subcommand that targets a specific project or session expects the exact Project ID string as shown in list-projects.

Provider Format Example
Gemini gemini:<dir-name> gemini:nostromo
OpenCode opencode:<hex-id> opencode:deadbeefcafe0042deadbeefcafe0042deadbeefcafe

The global OpenCode project (not tied to any directory) appears as opencode:global.


Subcommands

list-projects

Discover all projects that have history, sorted by number of sessions (descending).

python3 main.py list-projects [--additional-folders DIR [DIR ...]]

Options

Option Description
--additional-folders DIR … Extra directories to scan (2 levels deep) to resolve Gemini hash-named project dirs whose path cannot be found in ~/.gemini/projects.json. Pass your usual workspace roots here.

Output columns

Name                                Sessions   Project ID                                              Path
------------------------------------------------------------
gemini:nostromo                     172        gemini:nostromo                                         /home/ripley/projects/nostromo
opencode:nostromo                    18        opencode:deadbeefcafe0042deadbeefcafe0042deadbeefcafe   /home/ripley/projects/nostromo
gemini:b4d455c0ffee1337b4d4…        206        gemini:b4d455c0ffee1337b4d455c0ffee1337b4d455c0ffee13  Unknown
Column Meaning
Name Human-readable label: <provider>:<folder-name>. Use this for display only.
Sessions Number of unique sessions for this project (deduplicated across any merged storage dirs).
Project ID The opaque identifier to pass to all other subcommands. For Gemini this is gemini:<dir-name>; for OpenCode this is opencode:<hex-id>.
Path Absolute path of the project on disk (Unknown when a hash-named dir cannot be resolved).

Note on Gemini hash dirs — Gemini CLI stores new sessions under a SHA-256 hash of the project path. Older sessions may live under a human-readable dir name. list-projects merges both into one row and deduplicates session filenames, so the count and all subsequent commands cover the full history. If Path shows Unknown, run again with --additional-folders ~/your/workspace to help resolve the hash.


list-sessions

List all sessions for a project, sorted by start time (newest first).

python3 main.py list-sessions <Project ID>

Example

python3 main.py list-sessions "gemini:nostromo"
python3 main.py list-sessions "opencode:deadbeefcafe0042deadbeefcafe0042deadbeefcafe"

Output columns

Session File                                    Messages   Tools      Started                   Last Updated
------------------------------------------------------------------------------------------------------------------------
session-2294-10-26T13-34-c0ffee42.json          24         23         2294-10-26 14:01:03+00:00 2294-10-26 14:48:09+00:00
ses_faceb00c0000c0dec0dec0de0000000000000000    31         47         2294-10-25 08:30:11+00:00 2294-10-25 11:45:22+00:00
Column Meaning
Session File For Gemini: the JSON filename (e.g. session-2294-10-26T13-34-c0ffee42.json). For OpenCode: the session UUID (e.g. ses_faceb00c…). This is the value to pass to show-session and stats --session.
Messages Total number of messages in the session (user + assistant turns).
Tools Total number of tool calls made during the session.
Started UTC timestamp of the first message.
Last Updated UTC timestamp of the last message.

show-session

Print the full conversation of a single session to stdout.

python3 main.py show-session <Project ID> <Session File> [--show-tools]

Options

Option Description
--show-tools Also print each tool call (name + status) after the assistant turn that triggered it. Only applies to Gemini sessions where tool calls are recorded per-message.

Output format

Project: gemini:nostromo
Session: session-2294-10-26T13-34-c0ffee42.json
====================================================================================================

[2294-10-26T14:01:03.923Z] USER:
--------------------
<user message text>

[2294-10-26T14:02:15.100Z] GEMINI:
--------------------
<assistant response text>

  Tool Calls:          ← only with --show-tools, Gemini only
  > Tool: read_file (Status: success)
  > Tool: run_shell_command (Status: success)
  • The role label is USER, GEMINI (Gemini CLI), or ASSISTANT (OpenCode).
  • For Gemini sessions the timestamp is an ISO-8601 string; for OpenCode it is a Unix millisecond integer rendered as a UTC datetime.
  • Gemini GEMINI turns also print Thoughts when the model recorded its internal reasoning subjects/descriptions.

stats

Aggregate token usage, tool-call counts, and error counts. Scopes from broad to narrow: all projects → one project → one session.

python3 main.py stats [--project <Project ID>] [--session <Session File>]

Output

Statistics for Project gemini:nostromo
============================================================
Total Sessions:  42
Total Messages:  3100
Total Time Spent: 12 days, 4:30:00
Total Errors:    18

Token Usage:
  Input Tokens        : 120,000,000
  Output Tokens       :   3,500,000
  Cached Tokens       :  95,000,000
  Thought Tokens      :     800,000
  Tool Tokens         :           0
  Grand Total         : 124,300,000

Built-in Tool Usage:
  replace                  : 540
  glob                     :  12

MCP Tool Usage:
  run_shell_command        : 820
  read_file                : 610
  …
Section Meaning
Total Time Spent Sum of (lastUpdated − startTime) per session.
Total Errors Tool calls whose status is not success, plus tool results that set isError or return a non-zero exit_code.
Token Usage Cumulative across all turns: input, output, cache-hit, thought (Gemini extended thinking), tool, and the provider-reported grand total. Only present when the provider records token data (Gemini always does; OpenCode depends on the model).
Built-in Tool Usage Tools whose name contains no underscore (e.g. replace, glob). Sorted by frequency.
MCP Tool Usage Tools whose name contains an underscore (e.g. run_shell_command, read_file). Sorted by frequency.

The built-in / MCP split is a heuristic: Gemini CLI names built-in tools without underscores and MCP tools with underscores.


search

Full-text search across all session messages using a Python regex.

python3 main.py search <query> [--project <Project ID>]
  • <query> is a Python regular expression, matched case-insensitively.
  • Without --project, searches across every project (Gemini + OpenCode).

Output

Search results for 'hyperdrive':
================================================================================
[2294-01-11 20:26:39+00:00] gemini:nostromo / session-2294-01-11T20-13-c0ffee42.json (user)
  > Can you wire up the hyperdrive controller and make sure the jump sequence ...
----------------------------------------
[2293-12-18 00:55:28+00:00] gemini:nostromo / session-2293-12-18T00-39-cafebabe.json (gemini)
  > Here is a minimal hyperdrive bootstrap that satisfies the jump requirements ...
----------------------------------------
Found 37 matches.

Each match line shows:

  • UTC timestamp of the message
  • <provider>:<project-name> / <session-file> (<role>)
  • The first 100 characters of the message content (newlines collapsed)

The count at the end is the number of messages that matched, not the number of sessions or projects.


daily-digest

Summarise all LLM activity that occurred on a given calendar day.

python3 main.py daily-digest [YYYY-MM-DD]

Defaults to today when the date argument is omitted.

Output sections

DAILY DIGEST - 2294-10-26
================================================================================
First Activity: 09:15:00
Last Activity:  17:42:10
Work Day Span:  8:27:10
Total Sessions: 4
Cumulative Project Time: 9:10:05
Total Errors: 12
Total Tool Calls: 95

Metrics per Project:
Project ID                               Sessions   Tools      Duration
--------------------------------------------------------------------------------
opencode:nostromo                        2          61         7:30:00
gemini:sulaco                            2          34         1:40:05

Daily Tool Usage Breakdown:
  opencode:bash                           : 28
  opencode:read                           : 18
  gemini:run_shell_command                : 14
  …

Total Invoiced Tokens (Cumulative across all turns):
  Input Tokens        : 500,000
  Output Tokens       :  20,000
  …

PROJECT: gemini:nostromo
----------------------------------------
Topics discussed:
  * Please review the navigation subroutines and flag any anomalies...
  * Can you add unit tests for the new hyperdrive module...

Full Stream:
USER: <first user message text>
GEMINI: <first assistant response>
…
================================================================================
Section Meaning
First / Last Activity Wall-clock time (local, from the machine's perspective of UTC) of the first and last message of the day.
Work Day Span Last − First — the span of the active coding day.
Total Sessions Number of sessions that had at least one message on this date.
Cumulative Project Time Sum of (last-message-time − first-message-time) within each session that was active today. Can exceed Work Day Span when multiple projects ran concurrently.
Total Errors Same counting logic as stats.
Total Tool Calls All tool invocations across all sessions on this date.
Metrics per Project Per-project breakdown sorted by Duration descending. Project IDs are shown as <provider>:<name> for readability.
Daily Tool Usage Breakdown Tool calls prefixed with <provider>: (e.g. opencode:bash, gemini:run_shell_command), sorted by frequency descending.
Total Invoiced Tokens Cumulative token counts for today only (same labels as stats). Only present when token data is available.
PROJECT sections One section per project that was active today. Lists the first line of each user message as "Topics discussed", then prints the full chronological message stream (USER / GEMINI / ASSISTANT roles only; tool output is not reprinted).

opencode-metrics

Show per-model token and cost aggregates from the OpenCode database across all time, all projects.

python3 main.py opencode-metrics

Output

OpenCode Token & Cost Metrics
============================================================
Model                          Input      Output     Total      Cost
---------------------------------------------------------------------------
claude-sonnet-4-5-weyland      1200000    85000      3500000    $1.2500
gemini-2-pro-yutani             950000    42000      2100000    $0.0000
mother-7b-local                  80000     5000        85000    $0.0000
---------------------------------------------------------------------------
GRAND TOTAL                                          5685000    $1.2500
  • Total is the value stored by OpenCode (may include cache-read tokens and therefore exceed Input + Output).
  • Cost is populated only when OpenCode records pricing data for the model; local/self-hosted models typically show $0.0000.

Easter eggmother-7b-local costs $0.0000 because MOTHER runs on Weyland-Yutani's own hardware. Company policy: crew expendable, compute free.


Typical session

# 1. Discover all projects
python3 main.py list-projects

# 2. Browse sessions for one project (copy Project ID from step 1)
python3 main.py list-sessions "gemini:nostromo"

# 3. Read a specific session (copy Session File from step 2)
python3 main.py show-session "gemini:nostromo" \
    "session-2294-10-26T13-34-c0ffee42.json" --show-tools

# 4. Token and tool stats for that project
python3 main.py stats --project "gemini:nostromo"

# 5. Zoom in to a single session
python3 main.py stats \
    --project "gemini:nostromo" \
    --session "session-2294-10-26T13-34-c0ffee42.json"

# 6. Find all sessions where a topic came up
python3 main.py search "hyperdrive" --project "gemini:nostromo"

# 7. End-of-day review
python3 main.py daily-digest
python3 main.py daily-digest 2294-10-25   # a previous date

# 8. OpenCode cost overview
python3 main.py opencode-metrics

# 9. Resolve an unknown Gemini hash-project
python3 main.py list-projects --additional-folders ~/projects ~/work

"Final report of the commercial starship Nostromo. Crew: seven. Cargo: refinery processing 20,000,000 tokens of raw ore. Contact with LLM: achieved. — Ripley"

About

Analyze logs from a local gemini-cli and opencode installation

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages