forked from FlorianBruniaux/claude-code-ultimate-guide
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsession-logger.sh
More file actions
executable file
·102 lines (87 loc) · 2.79 KB
/
session-logger.sh
File metadata and controls
executable file
·102 lines (87 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#!/bin/bash
# Hook: PostToolUse - Log all Claude Code operations for monitoring
# Exit 0 = allow (always)
#
# This hook logs all tool operations to JSONL files for later analysis.
# Use session-stats.sh to analyze the logs.
#
# Logs are stored in: ~/.claude/logs/activity-YYYY-MM-DD.jsonl
#
# Environment variables:
# CLAUDE_LOG_DIR - Override log directory (default: ~/.claude/logs)
# CLAUDE_LOG_TOKENS - Enable token estimation (default: true)
# CLAUDE_SESSION_ID - Session identifier (auto-generated if not set)
#
# Place in: .claude/hooks/session-logger.sh
# Register in: .claude/settings.json under PostToolUse event
set -e
# Configuration
LOG_DIR="${CLAUDE_LOG_DIR:-$HOME/.claude/logs}"
ENABLE_TOKENS="${CLAUDE_LOG_TOKENS:-true}"
SESSION_ID="${CLAUDE_SESSION_ID:-$(date +%s)-$$}"
# Ensure log directory exists
mkdir -p "$LOG_DIR"
# Log file for today
LOG_FILE="$LOG_DIR/activity-$(date +%Y-%m-%d).jsonl"
# Read JSON from stdin
INPUT=$(cat)
# Extract tool information
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // "unknown"')
TOOL_INPUT=$(echo "$INPUT" | jq -c '.tool_input // {}')
TOOL_OUTPUT=$(echo "$INPUT" | jq -r '.tool_output // ""')
# Get timestamp
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Extract relevant details based on tool type
FILE_PATH=""
COMMAND=""
case "$TOOL_NAME" in
Read|Write|Edit)
FILE_PATH=$(echo "$TOOL_INPUT" | jq -r '.file_path // .path // ""')
;;
Bash)
COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // ""' | head -c 200)
;;
Grep|Glob)
FILE_PATH=$(echo "$TOOL_INPUT" | jq -r '.path // .pattern // ""')
;;
esac
# Estimate tokens (rough heuristic: ~4 chars per token)
TOKENS_INPUT=0
TOKENS_OUTPUT=0
if [[ "$ENABLE_TOKENS" == "true" ]]; then
INPUT_LEN=${#TOOL_INPUT}
OUTPUT_LEN=${#TOOL_OUTPUT}
TOKENS_INPUT=$((INPUT_LEN / 4))
TOKENS_OUTPUT=$((OUTPUT_LEN / 4))
fi
# Get project directory (if available)
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-$(pwd)}"
PROJECT_NAME=$(basename "$PROJECT_DIR")
# Build log entry
LOG_ENTRY=$(jq -n \
--arg timestamp "$TIMESTAMP" \
--arg session_id "$SESSION_ID" \
--arg tool "$TOOL_NAME" \
--arg file "$FILE_PATH" \
--arg command "$COMMAND" \
--arg project "$PROJECT_NAME" \
--argjson tokens_in "$TOKENS_INPUT" \
--argjson tokens_out "$TOKENS_OUTPUT" \
'{
timestamp: $timestamp,
session_id: $session_id,
tool: $tool,
file: (if $file != "" then $file else null end),
command: (if $command != "" then $command else null end),
project: $project,
tokens: {
input: $tokens_in,
output: $tokens_out,
total: ($tokens_in + $tokens_out)
}
} | with_entries(select(.value != null))'
)
# Append to log file
echo "$LOG_ENTRY" >> "$LOG_FILE"
# Always allow
exit 0