Skip to content

dizzikim-dev/claude-conversation-logger

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

claude-conversation-logger

A hook-based conversation logging package for Claude Code.

It captures Telegram-first conversations and tool-driven replies, writes raw JSONL logs, generates per-session summaries, and keeps a lightweight context file that Claude can use in the next session.

Designed for macOS environments using bash 3.2 and jq, with a focus on safe installation, merge-friendly hook setup, and local-first data ownership.

What It Does

  • Logs all inbound and outbound messages across channels (Telegram, terminal, Slack)
  • Generates a per-session markdown summary with git diffs of files changed during the session
  • Writes a latest.md context brief that Claude reads at the start of each new session
  • Tracks only session-specific file changes by comparing against a git baseline snapshot
  • Stores raw JSONL logs permanently under ~/.claude/logs/

Quick Start

Requirements

  • macOS (tested) or Linux
  • Bash 3.2+
  • jq (brew install jq)
  • Git (optional, for file change tracking)
  • Claude Code v2.1.80+ (hooks support required)

Install

git clone https://github.com/dizzikim-dev/claude-conversation-logger.git
cd claude-conversation-logger
bash install.sh

Activate

Important

You must restart your Claude Code session after installation. Hooks are loaded at session start, so logging will NOT work until you quit and reopen Claude Code.

Verify

Run the smoke tests:

bash tests/smoke-test.sh

Then do a real-world check:

  1. Start a fresh Claude Code session
  2. Send a Telegram message to Claude
  3. Make Claude reply on Telegram
  4. End the session
  5. Confirm logs and summaries exist under ~/.claude/logs/

Uninstall

bash uninstall.sh                 # Keep log data
bash uninstall.sh --remove-data   # Delete everything

The uninstaller removes only logger-managed hooks. Existing user hooks in settings.local.json are preserved.

How It Works

Three Hooks

Hook Event What it does
on-session-start.sh SessionStart Snapshots git state (HEAD ref + per-file content hashes)
on-tool-use.sh PostToolUse Logs outbound channel messages in real-time
on-session-end.sh SessionEnd Extracts inbound messages from transcript, computes session git diff, generates summary

Data Flow

Session Start
  └─ git snapshot saved (HEAD + dirty file hashes)

During Session
  └─ outbound replies logged to raw/*.jsonl in real-time

Session End
  ├─ transcript parsed for inbound messages (dedup against existing logs)
  ├─ git diff computed against session-start snapshot
  ├─ session summary written to sessions/*.md
  ├─ context/latest.md updated (brief for next session)
  └─ context/index.jsonl entry appended

Storage Layout

All data is stored locally under ~/.claude/logs/:

~/.claude/logs/
├── raw/              # JSONL logs, one file per day (single source of truth)
│   └── errors/       # Malformed JSON dumps
├── sessions/         # Per-session markdown summaries
├── context/
│   ├── latest.md     # Most recent session brief (auto-loaded by Claude)
│   ├── recent/       # Last 10 session summaries (FIFO rotation)
│   └── index.jsonl   # Session metadata index
├── snapshots/        # Git state snapshots (cleaned up per session)
├── scripts/          # Hook scripts (installed by install.sh)
└── config/           # Channel mappings + phase gate

Context Restoration

New sessions reference context in this order:

  1. latest.md — last session brief (10-15 lines)
  2. context/recent/ — last 10 session summaries
  3. context/index.jsonl — session metadata for targeted lookup
  4. raw/*.jsonl — full raw logs

To enable auto-restore, add the snippet from templates/claude-md-snippet.md to your project's CLAUDE.md.

Project Structure

claude-conversation-logger/
├── scripts/           # Hook scripts (copied to ~/.claude/logs/scripts/)
├── config/            # Default config files (copied if not present)
├── templates/         # CLAUDE.md context restore snippet
├── tests/
│   ├── smoke-test.sh  # 13 automated tests
│   └── fixtures/      # Sample transcript for testing
├── install.sh         # Merge-safe installer
├── uninstall.sh       # Idempotent uninstaller
├── README.md
├── LICENSE            # MIT
└── .gitignore

Configuration

Adding a New Channel

Edit ~/.claude/logs/config/outbound_tools.json to map outbound tool names:

{
  "telegram": [
    "mcp__plugin_telegram_telegram__reply",
    "mcp__plugin_telegram_telegram__edit_message"
  ],
  "slack": [
    "mcp__plugin_slack_slack__send_message"
  ]
}

Edit ~/.claude/logs/config/channel_sources.json to map inbound transcript sources:

{
  "telegram": ["plugin:telegram:telegram", "telegram"],
  "slack": ["plugin:slack:slack", "slack"]
}

Phase Gate

~/.claude/logs/config/capture_mode.json controls the capture mechanism:

  • "hook" — default, hooks capture everything
  • "parallel" — both hooks and MCP server run (for future migration testing)
  • "mcp" — hooks disabled, MCP server handles capture

Installation Details

  • install.sh merges hook entries into ~/.claude/settings.local.json using jq. Existing hooks and settings are preserved.
  • Config files (outbound_tools.json, channel_sources.json, capture_mode.json) are only written if they do not already exist.
  • Scripts are always overwritten on install to ensure the latest version.
  • Running install.sh multiple times is safe — hooks are not duplicated.

JSONL Entry Format

{
  "ts": "2026-03-22T10:00:00.000Z",
  "session_id": "uuid",
  "seq": 1,
  "event_type": "message",
  "channel": "telegram",
  "direction": "in",
  "chat_id": "12345",
  "message_id": "66",
  "sender_id": "12345",
  "sender_name": "user",
  "content": "message text",
  "_source": "hook"
}

Current Scope and Limitations

  • Telegram is the primary target. Slack channel mappings are included in config but have not been validated end-to-end. Treat Slack support as experimental.
  • Inbound messages are captured at session end, not in real-time, due to Claude Code hook constraints. Outbound messages are captured in real-time.
  • Hooks activate after a session restart. They are not live until the next SessionStart event fires.
  • SessionEnd hook has a 120-second timeout. Very large transcripts may exceed this.
  • Git diff tracking assumes the session starts and ends in the same git repository. Multi-repo sessions only capture the CWD's repo.
  • Data stays local. All logs are stored under ~/.claude/logs/ and never transmitted externally.

License

MIT

About

Telegram-first conversation logger for Claude Code with hook-based capture, session summaries, and context restore.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages