Search, analyze, and export Claude Code command history from history.jsonl
Searches, analyzes, and exports Claude Code command history from history.jsonl
/plugin marketplace add melodic-software/claude-code-plugins/plugin install claude-code-observability@melodic-software<search-term> [--days N] [--stats] [--export FILE] [--clear]Search, analyze, and export Claude Code command history stored in ~/.claude/history.jsonl.
| Argument | Description |
|---|---|
<search-term> | Search history for commands/prompts containing term |
--days N | Limit search to last N days (default: all) |
--stats | Show usage statistics and patterns |
--export FILE | Export history to specified file |
--clear | Clear history (with confirmation) |
| (no args) | Show recent history summary |
~/.claude/history.jsonl contains one JSON object per line:
{"display":"/commit","pastedContents":{},"timestamp":1735570845123,"project":"D:/repos/project","sessionId":"abc123-def456"}
{"display":"Fix the login bug","pastedContents":{},"timestamp":1735570900000,"project":"D:/repos/project","sessionId":"abc123-def456"}
{"display":"/help","pastedContents":{},"timestamp":1735571000000,"project":"D:/repos/other","sessionId":"xyz789"}
| Field | Description |
|---|---|
display | The command or prompt text |
pastedContents | Any pasted content (usually empty) |
timestamp | Unix timestamp in milliseconds |
project | Project path where command was run |
sessionId | Session identifier |
Search for commands/prompts containing a term:
import json
from pathlib import Path
from datetime import datetime, timezone
history_path = Path.home() / ".claude" / "history.jsonl"
search_term = "commit" # From argument
days_limit = None # From --days argument
results = []
now = datetime.now(timezone.utc)
with open(history_path) as f:
for line in f:
entry = json.loads(line)
# Filter by days if specified
if days_limit:
entry_time = datetime.fromtimestamp(entry["timestamp"] / 1000, tz=timezone.utc)
if (now - entry_time).days > days_limit:
continue
# Search in display text
if search_term.lower() in entry.get("display", "").lower():
results.append(entry)
# Display results
for entry in results[-50:]: # Last 50 matches
ts = datetime.fromtimestamp(entry["timestamp"] / 1000, tz=timezone.utc)
project = Path(entry.get("project", "")).name
print(f"[{ts.strftime('%Y-%m-%d %H:%M')}] [{project}] {entry['display'][:80]}")
--stats)Analyze usage patterns:
import json
from pathlib import Path
from collections import Counter, defaultdict
from datetime import datetime, timezone
history_path = Path.home() / ".claude" / "history.jsonl"
# Collect statistics
commands = Counter()
projects = Counter()
daily_usage = defaultdict(int)
slash_commands = Counter()
with open(history_path) as f:
for line in f:
entry = json.loads(line)
display = entry.get("display", "")
# Count slash commands
if display.startswith("/"):
cmd = display.split()[0]
slash_commands[cmd] += 1
# Count by project
project = Path(entry.get("project", "unknown")).name
projects[project] += 1
# Count by day
ts = datetime.fromtimestamp(entry["timestamp"] / 1000, tz=timezone.utc)
day = ts.strftime("%Y-%m-%d")
daily_usage[day] += 1
print("Top Slash Commands:")
for cmd, count in slash_commands.most_common(10):
print(f" {cmd}: {count}")
print("\nTop Projects:")
for project, count in projects.most_common(5):
print(f" {project}: {count}")
print("\nDaily Usage (last 7 days):")
for day in sorted(daily_usage.keys())[-7:]:
print(f" {day}: {daily_usage[day]} commands")
--export FILE)Export history to markdown or JSON:
import json
from pathlib import Path
from datetime import datetime, timezone
history_path = Path.home() / ".claude" / "history.jsonl"
export_path = Path("history-export.md") # From argument
entries = []
with open(history_path) as f:
for line in f:
entries.append(json.loads(line))
# Export as markdown
with open(export_path, "w") as f:
f.write("# Claude Code Command History\n\n")
f.write(f"Exported: {datetime.now(timezone.utc).isoformat()}\n")
f.write(f"Total entries: {len(entries)}\n\n")
# Group by date
current_date = None
for entry in sorted(entries, key=lambda x: x["timestamp"]):
ts = datetime.fromtimestamp(entry["timestamp"] / 1000, tz=timezone.utc)
date = ts.strftime("%Y-%m-%d")
if date != current_date:
f.write(f"\n## {date}\n\n")
current_date = date
time = ts.strftime("%H:%M")
project = Path(entry.get("project", "")).name
display = entry["display"][:100]
f.write(f"- `{time}` [{project}] {display}\n")
print(f"✅ Exported {len(entries)} entries to {export_path}")
--clear)Clear history with confirmation:
from pathlib import Path
history_path = Path.home() / ".claude" / "history.jsonl"
# Count entries first
with open(history_path) as f:
count = sum(1 for _ in f)
# Use AskUserQuestion for confirmation
# If confirmed:
history_path.unlink()
history_path.touch() # Create empty file
print(f"✅ Cleared {count} history entries")
Show recent history summary:
import json
from pathlib import Path
from datetime import datetime, timezone, timedelta
history_path = Path.home() / ".claude" / "history.jsonl"
# Get entries from last 24 hours
cutoff = datetime.now(timezone.utc) - timedelta(hours=24)
recent = []
with open(history_path) as f:
for line in f:
entry = json.loads(line)
ts = datetime.fromtimestamp(entry["timestamp"] / 1000, tz=timezone.utc)
if ts > cutoff:
recent.append(entry)
print(f"Last 24 hours: {len(recent)} commands/prompts\n")
print("Recent activity:")
for entry in recent[-10:]:
ts = datetime.fromtimestamp(entry["timestamp"] / 1000, tz=timezone.utc)
print(f" [{ts.strftime('%H:%M')}] {entry['display'][:60]}")
# History Search: "commit"
Found 23 matches (last 30 days)
| Time | Project | Command/Prompt |
|------|---------|----------------|
| 2025-12-30 15:30 | claude-plugins | /commit |
| 2025-12-30 14:15 | claude-plugins | Create a commit for the new feature |
| 2025-12-29 10:00 | web-app | /commit --amend |
...
## Quick Filters
- Last 7 days: `/user-config:history commit --days 7`
- Current project only: Search includes project filter
# History Statistics
**Total entries:** 1,247
**Date range:** 2025-11-01 to 2025-12-30
**Unique projects:** 8
## Top Slash Commands
| Command | Count |
|---------|-------|
| /commit | 156 |
| /help | 89 |
| /clear | 67 |
| /compact | 45 |
| /review | 34 |
## Most Active Projects
| Project | Commands |
|---------|----------|
| claude-plugins | 523 |
| web-app | 312 |
| api-server | 189 |
## Daily Activity (Last 7 Days)
| Date | Count |
|------|-------|
| 2025-12-30 | 45 |
| 2025-12-29 | 67 |
| 2025-12-28 | 23 |
...
/user-config:status - View overall configuration status/user-config:backup - Backup history along with config/user-config:session-stats - Session-level statisticsThis command uses the user-config-management skill for: