Last active
February 22, 2026 18:41
-
-
Save coccoinomane/0c5260e3223cc4649c5a327214ad458c to your computer and use it in GitHub Desktop.
Browse past Claude Code invocations from OpenClaw session transcripts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Usage: | |
| # claude-history Show the last prompt | |
| # claude-history 1 Show the last prompt | |
| # claude-history 3 Show the 3rd-to-last prompt | |
| # claude-history --last 5 Show the last 5 prompts | |
| set -euo pipefail | |
| if ! command -v jq &> /dev/null; then | |
| echo "Error: 'jq' is not installed." >&2 | |
| echo "This script requires jq to parse JSON logs." >&2 | |
| echo "" >&2 | |
| echo "Installation instructions:" >&2 | |
| echo " - macOS: brew install jq" >&2 | |
| echo " - Linux (Debian/Ubuntu): sudo apt-get install jq" >&2 | |
| echo " - Windows (Chocolatey): choco install jq" >&2 | |
| echo "For other platforms, please visit: https://jqlang.org/download/" >&2 | |
| exit 1 | |
| fi | |
| DIR="$HOME/.openclaw/agents/main/sessions" | |
| MODE="single" | |
| N=1 | |
| ON_DATE="" | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| --last|-l) | |
| MODE="list" | |
| if [[ $# -ge 2 && "$2" != -* ]]; then | |
| N="$2" | |
| shift 2 | |
| else | |
| N=5 | |
| shift | |
| fi | |
| ;; | |
| --on) | |
| MODE="date" | |
| if [[ $# -ge 2 && "$2" != -* ]]; then | |
| ON_DATE="$2" | |
| shift 2 | |
| else | |
| echo "Error: --on requires a date in YYYY-MM-DD format" >&2 | |
| exit 1 | |
| fi | |
| if [[ ! "$ON_DATE" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then | |
| echo "Error: --on requires a date in YYYY-MM-DD format" >&2 | |
| exit 1 | |
| fi | |
| ;; | |
| --help|-h) | |
| cat <<'EOF' | |
| claude-history — Browse past Claude Code invocations from OpenClaw session transcripts. | |
| Extracts all Claude Code calls made by the OpenClaw agent and displays them | |
| with timestamps. Reads from ~/.openclaw/agents/main/sessions/*.jsonl. | |
| Usage: | |
| claude-history Show the most recent invocation | |
| claude-history N Show the Nth-to-last invocation (1=last, 2=second-to-last, ...) | |
| claude-history --last N Show the last N invocations | |
| claude-history --on DATE Show all invocations on a specific date (YYYY-MM-DD) | |
| claude-history --help Show this help | |
| Examples: | |
| claude-history # last prompt | |
| claude-history 3 # 3rd-to-last prompt | |
| claude-history --last 10 # last 10 prompts | |
| claude-history --on 2026-02-22 # all prompts from that day | |
| EOF | |
| exit 0 | |
| ;; | |
| -*) | |
| echo "Unknown option: $1. Try claude-history --help" >&2 | |
| exit 1 | |
| ;; | |
| *) | |
| N="$1" | |
| shift | |
| ;; | |
| esac | |
| done | |
| if ! [[ "$N" =~ ^[0-9]+$ ]]; then | |
| echo "Error: N must be an integer, got $N" >&2 | |
| exit 1 | |
| fi | |
| shopt -s nullglob | |
| files=("$DIR"/*.jsonl) | |
| if [[ ${#files[@]} -eq 0 ]]; then | |
| echo "No session files found in $DIR" >&2 | |
| exit 0 | |
| fi | |
| jq -r -n --arg mode "$MODE" --arg n "$N" --arg on_date "$ON_DATE" ' | |
| [ | |
| inputs | | |
| select(.type == "message") | | |
| .message.timestamp as $ts | | |
| (.message.content // [])[]? | | |
| select(.name == "exec") | | |
| .arguments.command as $cmd | | |
| select($cmd != null) | | |
| select( | |
| ($cmd | contains("claude --dangerously")) or | |
| ($cmd | contains("claude -p")) or | |
| ($cmd | contains("claude '\''")) or | |
| ($cmd | contains("claude \"")) | |
| ) | | |
| select( | |
| ($cmd | contains("--version") | not) and | |
| ($cmd | contains("--help") | not) | |
| ) | | |
| {ts: ($ts/1000|floor), cmd: $cmd} | |
| ] | | |
| if $mode == "date" then | |
| map(select((.ts | strflocaltime("%Y-%m-%d")) == $on_date)) | | |
| if length == 0 then | |
| "No invocations found on \($on_date)." | halt_error(1) | |
| else | |
| .[] | "\u001b[36m[\(.ts | strflocaltime("%Y-%m-%d %H:%M"))]\u001b[0m \(.cmd)\n" | |
| end | |
| elif $mode == "single" then | |
| if length < ($n|tonumber) then | |
| "Only \(length) invocations found." | halt_error(1) | |
| else | |
| .[-($n|tonumber)] | "\u001b[36m[\(.ts | strflocaltime("%Y-%m-%d %H:%M"))]\u001b[0m \(.cmd)" | |
| end | |
| else | |
| .[-($n|tonumber):] | .[] | "\u001b[36m[\(.ts | strflocaltime("%Y-%m-%d %H:%M"))]\u001b[0m \(.cmd)\n" | |
| end | |
| ' "${files[@]}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment