Skip to content

Instantly share code, notes, and snippets.

@jlmalone
Last active September 20, 2025 06:46
Show Gist options
  • Select an option

  • Save jlmalone/9568f3cc7989f1c0cf0e3c9a0a267a98 to your computer and use it in GitHub Desktop.

Select an option

Save jlmalone/9568f3cc7989f1c0cf0e3c9a0a267a98 to your computer and use it in GitHub Desktop.
Claude Code Response Logger - Automatic session logging with archival

Claude Code Response Logger

A reliable solution to automatically log Claude Code interactions to project-specific markdown files.

Problem Solved

Claude Code only stores your inputs (messages, files) in .claude.json, not AI responses. This solution creates persistent logs of when interactions occurred, organized by project directory with automatic archival.

What This Does

  • Automatic Logging: Creates CLAUDE_SESSION_LOG.md in each project directory
  • Per-Project Logs: Each directory gets its own interaction history
  • Archive System: Monthly archives when logs get large (preserves all data)
  • Reliable: Built with failure-safe design - won't break Claude if logging fails
  • Chronological: Complete timeline of when you used Claude in each project

Quick Setup

1. Install the Logger Script

# Download and install the script
curl -o ~/.local/bin/claude_response_logger.sh https://gist.githubusercontent.com/[GIST_URL]/claude_response_logger.sh
chmod +x ~/.local/bin/claude_response_logger.sh

2. Configure Claude Code Hook

Add this to your ~/.claude/settings.json:

{
  "model": "sonnet",
  "hooks": {
    "stop": {
      "command": "/Users/[USERNAME]/.local/bin/claude_response_logger.sh",
      "timeout": 5000,
      "continueOnFailure": true
    }
  }
}

Replace [USERNAME] with your actual username.

File Structure Created

your-project/
├── CLAUDE_SESSION_LOG.md              # Recent interactions (500 entries max)
├── CLAUDE_SESSION_LOG_ARCHIVE_2025-08.md   # August 2025 archive  
├── CLAUDE_SESSION_LOG_ARCHIVE_2025-09.md   # September 2025 archive
└── (your project files...)

Log Format Example

# Claude Session Log

This file contains summaries of Claude Code interactions for this project.

---

## Session: 2025-08-25 15:30:42

- **Project:** my-awesome-app
- **Directory:** /Users/john/projects/my-awesome-app
- **User:** john
- **Action:** Claude interaction completed

---

## Session: 2025-08-25 16:15:23

- **Project:** my-awesome-app
- **Directory:** /Users/john/projects/my-awesome-app
- **User:** john
- **Action:** Claude interaction completed

---

Features

✅ Reliable

  • Failure-safe: Uses continueOnFailure: true - won't break Claude
  • Timeout protection: 5-second limit prevents hanging
  • Error handling: Built with set -e for proper error handling

✅ Data Preservation

  • No data loss: Archives old entries instead of deleting them
  • Monthly archives: Organized by year-month for easy browsing
  • Chronological order: Maintains timeline across archives

✅ Project-Aware

  • Per-directory logs: Each project gets its own history
  • Automatic creation: Creates log files as needed
  • Path-based: Works from any directory you run Claude from

Customization Options

Change Archive Threshold

Edit the script and modify:

if [[ $(wc -l < "$LOG_FILE") -gt 1000 ]]; then  # Change 1000 to your preference

Change Archive Size

Edit the script and modify:

head -500 "$LOG_FILE" >> "$ARCHIVE_FILE"  # Change 500 to your preference
tail -500 "$LOG_FILE" > "${LOG_FILE}.tmp" # Change 500 to your preference

Custom Log Format

Modify the section that writes to $LOG_FILE to include different information.

Troubleshooting

Hook Not Triggering

  1. Check your ~/.claude/settings.json syntax with cat ~/.claude/settings.json
  2. Verify script path: ls -la ~/.local/bin/claude_response_logger.sh
  3. Test script manually: ~/.local/bin/claude_response_logger.sh

Permission Issues

# Make sure script is executable
chmod +x ~/.local/bin/claude_response_logger.sh

# Make sure ~/.local/bin directory exists
mkdir -p ~/.local/bin

Script Path Issues

  • Linux/Mac: Use /home/[username]/.local/bin/claude_response_logger.sh
  • Mac alternative: Use /Users/[username]/.local/bin/claude_response_logger.sh
  • Custom path: Put script anywhere and update the path in settings.json

Testing the Setup

  1. Save settings and restart Claude Code
  2. Have a conversation in any directory
  3. Check for CLAUDE_SESSION_LOG.md file creation
  4. Verify timestamps match your interaction time

Advanced Usage

Multiple Log Formats

You can modify the script to create different log formats or additional files:

  • Add JSON logs for programmatic analysis
  • Include git commit information
  • Add project type detection
  • Include tool usage summaries

Integration with Other Tools

  • Use with git hooks to commit logs
  • Parse logs for productivity analysis
  • Generate daily/weekly summaries
  • Export to other formats (JSON, CSV)

Why This Approach

This solution uses Claude Code's built-in hooks system rather than trying to modify Claude itself. Benefits:

  • Official API: Uses documented Claude Code functionality
  • Reliable: Doesn't depend on undocumented behavior
  • Safe: Won't break when Claude Code updates
  • Flexible: Easy to customize for your needs

Contributing

Feel free to fork and modify this script for your needs. Common improvements:

  • Better log formatting
  • Integration with version control
  • Summary generation
  • Tool usage tracking

Created for the Claude Code community. Share and modify freely!

Claude Code Response Logger v2 - Session-Based

A reliable solution to automatically log Claude Code interactions to unique session files with race-condition safety.

What's New in v2

  • Session-Based Logging - Each Claude session gets its own unique file
  • Race Condition Safe - Multiple Claude instances can run simultaneously
  • Complete Session Tracking - Full conversation timeline per session
  • Single Archive Folder - Clean organization of old sessions
  • Zero Data Loss - All sessions preserved, nothing deleted

Problem Solved

Claude Code only stores your inputs (messages, files) in .claude.json, not AI responses. This solution creates persistent logs of when interactions occurred, organized by unique session with automatic archival.

File Structure Created

your-project/
├── CLAUDE_SESSION_20250826_091542_12345_a1b2.md    # Active session 1
├── CLAUDE_SESSION_20250826_092130_12346_c3d4.md    # Active session 2  
├── CLAUDE_SESSION_20250826_093005_12347_e5f6.md    # Active session 3
└── CLAUDE_SESSIONS_ARCHIVE/                        # Single archive folder
    ├── CLAUDE_SESSION_20250820_143022_11234_f8e7.md
    ├── CLAUDE_SESSION_20250821_091155_11456_d2c1.md
    └── CLAUDE_SESSION_20250822_164433_11789_b9a8.md

Quick Setup

1. Install the Logger Script

# Download and install the script
curl -o ~/.local/bin/claude_response_logger.sh https://gist.githubusercontent.com/jlmalone/9568f3cc7989f1c0cf0e3c9a0a267a98/raw/claude_response_logger_v2.sh
chmod +x ~/.local/bin/claude_response_logger.sh

2. Configure Claude Code Hook

Add this to your ~/.claude/settings.json:

{
  "model": "sonnet",
  "hooks": {
    "stop": {
      "command": "/Users/[USERNAME]/.local/bin/claude_response_logger.sh",
      "timeout": 5000,
      "continueOnFailure": true
    }
  }
}

Replace [USERNAME] with your actual username.

Session File Format Example

# Claude Session Log - 2025-08-26 09:15:42

**Session ID:** 20250826_091542_12345_a1b2  
**Project:** my-awesome-app  
**Directory:** /Users/john/projects/my-awesome-app  
**User:** john  

---

## Interaction: 2025-08-26 09:15:45

Claude response completed.

## Interaction: 2025-08-26 09:16:23

Claude response completed.

## Interaction: 2025-08-26 09:18:07

Claude response completed.

Key Features

✅ Session-Based Design

  • Unique Session IDs: YYYYMMDD_HHMMSS_PID_HEX format ensures uniqueness
  • Per-Session Files: Each Claude conversation gets its own file
  • Session Persistence: Same session ID used throughout entire conversation

✅ Race Condition Safe

  • Multiple Instances: Run several Claude sessions in same directory safely
  • No File Conflicts: Each session writes to its own unique file
  • No Corruption Risk: Eliminates file locking and collision issues

✅ Automatic Archival

  • 20 File Limit: Main directory keeps only recent 20 sessions visible
  • Archive on Overflow: Oldest 10 sessions moved to CLAUDE_SESSIONS_ARCHIVE/
  • Single Archive Folder: All old sessions in one organized location
  • Chronological Order: Sessions archived by date (oldest first)

✅ Complete Data Preservation

  • Nothing Deleted: All sessions preserved forever
  • Easy Retrieval: Find any session by date in filename
  • Clean Organization: Recent sessions easily accessible, old ones archived

Advanced Features

Session ID Components

20250826_091542_12345_a1b2
├─ 20250826_091542  # Timestamp (YYYYMMDD_HHMMSS)
├─ 12345           # Process ID (unique per session)  
└─ a1b2           # Random hex (collision protection)

Archival Logic

  • Trigger: When directory has >20 session files
  • Action: Move oldest 10 sessions to archive folder
  • Result: Main directory stays clean with recent sessions
  • Preservation: All archived sessions remain accessible

Customization Options

Change Archive Threshold

Edit the script and modify:

if [[ $SESSION_COUNT -gt 20 ]]; then  # Change 20 to your preference

Change Archive Count

Edit the script and modify:

ls -1t "$PROJECT_DIR"/CLAUDE_SESSION_*.md | tail -10  # Change 10 to your preference

Custom Session Format

Modify the session file creation section to include different information:

cat > "$SESSION_LOG" << EOF
# Your custom header format here
EOF

Migration from v1

If you're upgrading from the single-file logging approach:

  1. Backup existing logs: Your CLAUDE_SESSION_LOG.md files are preserved
  2. Install new script: Replace with session-based version
  3. New sessions: Will use new format automatically
  4. Old logs: Remain accessible alongside new session files

Benefits Over v1

Feature v1 (Single File) v2 (Session-Based)
Race Conditions ❌ Possible corruption ✅ Completely safe
Multiple Claude Instances ❌ File conflicts ✅ Full support
Session Tracking ❌ Mixed conversations ✅ Complete isolation
Debugging ❌ Hard to trace issues ✅ Easy session analysis
Organization ❌ Chronological only ✅ By session + archive

Troubleshooting

Hook Not Triggering

  1. Check your ~/.claude/settings.json syntax with cat ~/.claude/settings.json
  2. Verify script path: ls -la ~/.local/bin/claude_response_logger.sh
  3. Test script manually: ~/.local/bin/claude_response_logger.sh

No Session Files Created

  1. Check directory permissions: ls -la $(pwd)
  2. Test session ID generation: echo $CLAUDE_SESSION_ID
  3. Verify script has execute permission: ls -la ~/.local/bin/claude_response_logger.sh

Archive Not Working

  1. Check if 20+ session files exist: ls -1 CLAUDE_SESSION_*.md | wc -l
  2. Verify archive directory creation: ls -la CLAUDE_SESSIONS_ARCHIVE/
  3. Test archival manually by creating 21+ dummy session files

Script Path Issues

  • Linux/Mac: Use /home/[username]/.local/bin/claude_response_logger.sh
  • Mac alternative: Use /Users/[username]/.local/bin/claude_response_logger.sh
  • Custom path: Put script anywhere and update the path in settings.json

Testing the Setup

  1. Save settings and restart Claude Code
  2. Have a conversation in any directory
  3. Check for CLAUDE_SESSION_YYYYMMDD_*.md file creation
  4. Have multiple conversations, verify separate files created
  5. Create 21+ session files, verify archival triggers

Advanced Usage

Session Analysis

# Find all sessions from specific date
ls CLAUDE_SESSION_20250826_*.md

# Count total interactions across all sessions
grep -c "## Interaction:" CLAUDE_SESSION_*.md

# Find longest session
wc -l CLAUDE_SESSION_*.md | sort -n

Archive Management

# List all archived sessions
ls CLAUDE_SESSIONS_ARCHIVE/

# Find sessions from specific month
ls CLAUDE_SESSIONS_ARCHIVE/CLAUDE_SESSION_202508*.md

# Total archived sessions count
ls -1 CLAUDE_SESSIONS_ARCHIVE/ | wc -l

Integration with Other Tools

  • Git Integration: Commit session files for project history
  • Analysis Scripts: Parse session files for productivity metrics
  • Backup Systems: Include session files in project backups
  • Search Tools: Use grep to find specific interactions across sessions

Why Session-Based Approach

This v2 design solves fundamental issues with shared file logging:

  • Concurrency: Multiple Claude instances can't interfere with each other
  • Debugging: Easy to trace issues to specific conversation sessions
  • Organization: Natural separation of different conversation threads
  • Performance: No file locking overhead or race condition handling needed
  • Scalability: Handles any number of concurrent Claude sessions

Contributing

Feel free to fork and modify this script for your needs. Common improvements:

  • Enhanced session metadata (git branch, project type, etc.)
  • Integration with productivity tracking tools
  • Custom archival strategies (by date, size, etc.)
  • Session summary generation
  • Export to other formats (JSON, CSV, database)

Created for the Claude Code community. v2 adds session-based logging for better concurrency and organization. Share and modify freely!

#!/bin/bash
# Claude Response Logger
# Logs summaries of Claude interactions to project-specific files
# Author: Created for Claude Code users who want persistent session logs
# Usage: Add as a "stop" hook in Claude Code settings
set -e
# Get current working directory (project root)
PROJECT_DIR=$(pwd)
LOG_FILE="$PROJECT_DIR/CLAUDE_SESSION_LOG.md"
# Create log file if it doesn't exist
if [[ ! -f "$LOG_FILE" ]]; then
cat > "$LOG_FILE" << 'EOF'
# Claude Session Log
This file contains summaries of Claude Code interactions for this project.
---
EOF
fi
# Get current timestamp
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
# Extract basic session info
# Note: Hook limitations mean we can't access full conversation context
# So we log basic interaction metadata
cat >> "$LOG_FILE" << EOF
## Session: $TIMESTAMP
- **Project:** $(basename "$PROJECT_DIR")
- **Directory:** $PROJECT_DIR
- **User:** $USER
- **Action:** Claude interaction completed
---
EOF
# Keep log file reasonable size by archiving old entries
if [[ $(wc -l < "$LOG_FILE") -gt 1000 ]]; then
# Create archive filename with current date
ARCHIVE_DATE=$(date '+%Y-%m')
ARCHIVE_FILE="${LOG_FILE%/*}/CLAUDE_SESSION_LOG_ARCHIVE_${ARCHIVE_DATE}.md"
# If archive for this month doesn't exist, create it with header
if [[ ! -f "$ARCHIVE_FILE" ]]; then
cat > "$ARCHIVE_FILE" << EOF
# Claude Session Log Archive - $ARCHIVE_DATE
This file contains archived Claude Code interactions from $ARCHIVE_DATE.
---
EOF
fi
# Move first 500 lines to archive (preserve chronological order)
head -500 "$LOG_FILE" >> "$ARCHIVE_FILE"
# Keep last 500 lines in main log
tail -500 "$LOG_FILE" > "${LOG_FILE}.tmp" && mv "${LOG_FILE}.tmp" "$LOG_FILE"
fi
#!/bin/bash
# Claude Response Logger - Session-Based Version
# Logs summaries of Claude interactions to unique session files
# Author: Created for Claude Code users who want persistent session logs
# Usage: Add as a "stop" hook in Claude Code settings
set -e
# Get current working directory (project root)
PROJECT_DIR=$(pwd)
ARCHIVE_DIR="$PROJECT_DIR/CLAUDE_SESSIONS_ARCHIVE"
# Generate unique session ID (timestamp + process ID + random hex)
if [[ -z "$CLAUDE_SESSION_ID" ]]; then
export CLAUDE_SESSION_ID=$(date '+%Y%m%d_%H%M%S')_$$_$(od -An -N2 -tx1 /dev/urandom | tr -d ' ')
fi
SESSION_LOG="$PROJECT_DIR/CLAUDE_SESSION_${CLAUDE_SESSION_ID}.md"
# Create session log file if it doesn't exist
if [[ ! -f "$SESSION_LOG" ]]; then
cat > "$SESSION_LOG" << EOF
# Claude Session Log - $(date '+%Y-%m-%d %H:%M:%S')
**Session ID:** $CLAUDE_SESSION_ID
**Project:** $(basename "$PROJECT_DIR")
**Directory:** $PROJECT_DIR
**User:** $USER
---
EOF
fi
# Get current timestamp
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
# Log this interaction
cat >> "$SESSION_LOG" << EOF
## Interaction: $TIMESTAMP
Claude response completed.
EOF
# Archive old sessions if we have too many active session files
SESSION_COUNT=$(ls -1 "$PROJECT_DIR"/CLAUDE_SESSION_*.md 2>/dev/null | wc -l)
if [[ $SESSION_COUNT -gt 20 ]]; then
# Create archive directory if it doesn't exist
mkdir -p "$ARCHIVE_DIR"
# Move oldest 10 session files to archive
ls -1t "$PROJECT_DIR"/CLAUDE_SESSION_*.md | tail -10 | while read -r old_session; do
mv "$old_session" "$ARCHIVE_DIR/"
done
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment