PromptLens
Scan local AI-agent history, extract only user-authored messages, and render a PNG word cloud that supports both Chinese and English.
Quick Start
Run from the skill directory:
When invoked by an Agent, scan only that Agent's own history by default. Use the source matching the invoking harness, for example --sources codex for Codex, --sources claude for Claude Code, --sources opencode for OpenCode, --sources openclaw for OpenClaw, or --sources hermes for Hermes Agent.
uv run --with jieba --with wordcloud --with matplotlib --with pillow \
scripts/promptlens.py \
--sources codex \
--days 90 \
-o outputs/wordcloud.png \
--report-json outputs/wordcloud.json
Use --path to add arbitrary JSONL/JSON files or directories:
uv run --with jieba --with wordcloud --with matplotlib --with pillow \
scripts/promptlens.py \
--path ~/.some-tool/history --sources custom \
-o outputs/wordcloud.png
Filter by project and time range:
uv run --with jieba --with wordcloud --with matplotlib --with pillow \
scripts/promptlens.py \
--sources codex \
--project SpotAsk --exclude-project worktrees \
--since 2026-01-01 --until 2026-06-30 \
-o outputs/wordcloud.png
Source Coverage
codex: scans$CODEX_HOME/sessions,$CODEX_HOME/archived_sessions, and falls back tohistory.jsonl. Subagent threads are skipped.claude: scans$CLAUDE_CONFIG_DIR/history.jsonland direct CLI user messages inprojects/*/*.jsonl. Subagent, memory, tool-result, and SDK delegation records are skipped.opencode: reads the SQLiteopencode.dbunder~/.opencode,~/.config/opencode, orOPENCODE_DATA_DIR.openclaw: reads~/.openclaw/agents/*/agent/openclaw-agent.sqliteand legacy session JSONL, orOPENCLAW_STATE_DIR.hermes: reads~/.hermes/state.db, orHERMES_HOME.custom: scans files/directories passed with--path, including raw OpenCode/OpenClaw/Hermes SQLite fixtures.
The scan is local-only and does not call any network service.
Output Modes
The default output is a promotional bordered image with the agent label, time range, message count, and session count. Add --plain to render only the cloud. Use --frame-label "My Agent" to override the label.
Weighting
The default scoring is conversation-relative and non-linear:
- Clean the raw input by removing fenced code, inline code, URLs/paths, pasted-text markers, and slash commands.
- Compute
raw = 1 / (1 + (effective_length / 120) ** 1.5), so short inputs keep high weight and long inputs decay sharply. - Normalize raw weights within each conversation, then scale that conversation by
sqrt(number_of_user_messages). - Multiply paste-heavy messages by
0.35. - Give each message a fixed term budget; words inside it share that budget by token share.
This stops long pasted code, error logs, and generated delegation prompts from dominating the cloud. See references/scoring.md for the formula, examples, and tuning knobs.
Useful Options
--days N/--since YYYY-MM-DD: restrict the time range.--until YYYY-MM-DD(alias--to): set an upper time bound.--project SUBSTRING: keep only projects whose path contains the substring; repeatable.--exclude-project SUBSTRING: remove matching projects; repeatable.--list-projects: list discovered projects and message counts, then exit. It honors--project,--exclude-project, and time filters.--max-words N: control cloud density.--length-scale,--exponent,--paste-penalty: adjust the non-linear decay.--font PATH: use a specific CJK-capable font.--stopwords-file PATH: add user-specific stopwords, one per line.--report-json PATH: write a reproducible JSON report with scan stats and top terms.--verbose: print source counts and top terms.--plain: render only the word cloud, without the promotional border.--frame-label TEXT: override the agent label shown in the default border.