promptfolio-summarize
You are building a portrait of the human user — the person running this command is the subject being analyzed. Their portrait will be displayed on the promptfolio platform. You are not summarizing projects, not evaluating AI usage skills, not writing a performance review. You are finding the moments where this person teaches AI how to think — their framework sentences — and using those to paint a picture of who they are.
To do this, analyze their AI conversation history (Claude Code, Cursor, Codex, ChatGPT, Gemini CLI, Trae, OpenCode, Antigravity, Windsurf, OpenClaw and any other coding agents found on the system) from the last 30 days, extract an activity heat map and framework sentences that reveal this person's thinking, then build a portrait around those sentences.
Fundamental principle: find where the user is TEACHING, not where they are COMMANDING. "Fix this bug" tells you nothing. "Don't think about it that way — this isn't a performance problem, it's a user psychology problem" / "你不要这样想,这不是性能问题,是用户心理问题" tells you everything.
Step 0: Auto-Update
Before anything else, run the auto-updater to ensure you have the latest skill files and data formats:
CODEBLOCK0
- - If output is
UPDATED v... → tell the user: "Skills updated to v{version}." Then re-read this SKILL.md file since it may have changed, and continue from Step 1. - If output is
UP_TO_DATE v... → continue silently. - If output is
OFFLINE v... → tell the user: "Could not check for updates (offline). Running with local v{version}." Continue normally.
Then continue with Step 1 normally.
Step 1: Authentication
Ensure ~/.promptfolio/config.json exists and has a valid token.
1a. Validate existing token (if config exists):
if [ -f ~/.promptfolio/config.json ]; then
API_TOKEN=$(python3 -c "import json; print(json.load(open('$HOME/.promptfolio/config.json'))['api_token'])")
API_URL=$(python3 -c "import json; print(json.load(open('$HOME/.promptfolio/config.json')).get('api_url','https://promptfolio.club'))")
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer $API_TOKEN" "$API_URL/api/profile/me" || true)
echo "HTTP_CODE=$HTTP_CODE"
fi
- - If HTTP 200, proceed to Step 2.
- If config missing or HTTP is not 200, run the device auth script:
1b. Run device authorization:
bash "SKILL_DIR/../scripts/device-auth.sh"
Replace
SKILL_DIR with the directory containing this SKILL.md file. The script handles everything: requesting a device code, opening the browser, polling until authorized, and saving
~/.promptfolio/config.json.
IMPORTANT: You MUST run the script as-is. Do NOT reimplement the auth flow yourself. Do NOT construct auth URLs manually — let the script handle everything.
If the script fails, tell the user authorization timed out and to try again.
Step 2: Discover Sessions
Before running any commands, tell the user:
All conversation analysis happens locally on your machine. No raw conversation content is sent to any server during analysis. Only structured results are uploaded after your explicit confirmation.
2a. Detect installed tools
Before scanning, check which AI coding tools the user actually has installed. Look for their config/data directories:
| Tool | How to detect |
|---|
| Claude Code | INLINECODE6 exists |
| Cursor |
~/.cursor/projects/ exists |
| Codex |
~/.codex/ exists |
| OpenClaw |
~/.openclaw/ exists |
| Gemini CLI |
~/.gemini/tmp/ exists (with
chats/ subdirs) |
| Antigravity |
~/Library/Application Support/Antigravity/ or
~/.gemini/antigravity/ exists |
| Windsurf |
~/.codeium/windsurf/,
~/.windsurf/, or
~/Library/Application Support/Windsurf/ exists |
| ChatGPT |
~/Desktop/chatgpt_history/ exists (user must export data manually) |
| Trae |
~/.trae/,
~/.trae-cn/, or App Support
Trae directories exist (note: DB is encrypted) |
| OpenCode |
~/.local/share/opencode/opencode.db exists |
Run a quick check:
CODEBLOCK3
Then scan for other coding agents not in the list above. Look for dot-directories in ~/ and app directories in ~/Library/Application Support/ that look like AI coding tools (e.g. Kiro, Aider, Continue, Copilot Chat, Trae, Roo Code, etc.):
CODEBLOCK4
If you find any unknown tool directories, peek inside to see if they contain conversation logs (.jsonl, .json, .txt). If they do, include them — no need to ask the user.
Present the results: "Detected: Claude Code, Cursor. Also found: Kiro (has session logs)."
Set PF_SOURCES to the known tools for the script, and handle unknown tools manually in 2b.
2b. Find session files
Run the discovery script, targeting only the detected tools:
CODEBLOCK5
The script scans known locations for each tool and filters to the last 30 days. After running it:
- 1. Check zero-session tools — if a detected tool has 0 sessions, explore its data directory yourself to find files the script missed.
- Handle unknown tools — for any extra coding agents discovered in 2a, explore their data directories, find conversation log files (.jsonl, .json, .txt), and append them to
$SESSION_LIST. - Ask the user if they have session data in non-standard locations or from tools you didn't detect.
If you find additional session files, append them to $SESSION_LIST.
2c. Compute statistics + activity data
Run the stats script to compute token estimates and extract activity heat map data in a single pass:
CODEBLOCK6
This reads $SESSION_LIST and produces:
- - stdout: session/token summary per source
_pf_parts/activity.json: per-day activity data for the heat map visualization
2d. Present summary and ask user
Present a summary to the user:
- - Total sessions found (last 30 days), grouped by source
- Activity heat map highlights: most active day, latest night, longest session
- Estimated total tokens (labeled as "estimated")
Then use AskQuestion tool to ask:
- - Question: "Proceed with analysis?"
- Options:
1. "Yes, analyze these sessions" — proceed to Step 3
2. "No, let me adjust" — ask the user what to change
Step 3: Analyze Conversations
Parsing different formats
Claude Code sessions (.jsonl in ~/.claude/projects/):
- - Each line is a JSON object from the conversation transcript
- Read and analyze directly
Cursor sessions — Plain text (.txt in ~/.cursor/projects/*/agent-transcripts/):
- - Alternating
user: and assistant: blocks - User messages are wrapped in
<user_query>...</user_query> tags - Assistant messages may include
[Thinking] sections - Parse by splitting on
user: / assistant: markers
Cursor sessions — JSONL (.jsonl in ~/.cursor/projects/*/agent-transcripts/{UUID}/):
- - Each line: INLINECODE41
- User messages contain
<user_query> tags in the text field - Parse JSON and extract the text content
Codex prompt history (~/.codex/history.jsonl):
- - Each line typically looks like: INLINECODE44
- Treat
text as user message content - Group by
session_id to reconstruct threads
Codex session events (~/.codex/sessions/**/*.jsonl):
- - Event stream with
type + INLINECODE49 - Extract user-originated content where role/type indicates user messages
- Use
history.jsonl as the primary fallback if event parsing is ambiguous
OpenClaw sessions (~/.openclaw/sessions/*.jsonl and ~/.openclaw/agents/**/*.jsonl):
- - OpenClaw stores session metadata in
~/.openclaw/sessions.json and per-session transcripts as JSONL. - Parse each JSONL line as an event; extract entries where the speaker/role/source indicates the user.
- If multiple event shapes exist, prefer explicit
role == "user" content, then fallback to user-tagged event payload text. - Use
sessions.json to map session IDs to project/workspace context when available.
ChatGPT export (conversations*.json):
- - File is an array of conversations, each containing a
mapping tree - Extract nodes where INLINECODE58
- Get user text from INLINECODE59
- Sort by
create_time when reconstructing chronology
Gemini CLI sessions (.json in ~/.gemini/tmp/*/chats/):
- - Each file is a full session: INLINECODE63
- INLINECODE64 = user message,
type: "model" = assistant response - Content is an array of parts, each with a
text field - Timestamps are ISO 8601 strings
- Project name is the parent directory under
tmp/ (e.g. ~/.gemini/tmp/myproject/chats/)
Trae sessions (VS Code fork by ByteDance — encrypted DB, requires user-assisted export):
- - Trae stores AI chat in an encrypted SQLite DB (SQLCipher) at
~/Library/Application Support/Trae CN/ModularData/ai-agent/database.db — cannot be read directly - Home directory:
~/.trae-cn/ (CN) or ~/.trae/ (international) - The discover script checks for exported chat files at
~/.trae-cn/chat-export.json, ~/.trae/chat-export.json, ~/Desktop/trae-chat-export.json, INLINECODE75 - If Trae is detected but no export files are found (stderr contains
TRAE_DETECTED_NO_EXPORT), ask the user with AskUserQuestion:
- Explain: "Trae stores chat history in an encrypted database. To include Trae data, you can export it from within Trae."
- Option 1:
"Export from Trae" — Tell the user to open Trae, start a new chat, and send this message:
Export all my chat history as a JSON file. Save it to ~/.trae-cn/chat-export.json (or ~/.trae/chat-export.json for international version).
The JSON format should be: {"messages": [{"role": "user", "content": "...", "timestamp": "2026-01-01T12:00:00Z"}, {"role": "assistant", "content": "...", "timestamp": "..."}]}
If there are multiple sessions, combine all messages from all sessions into one flat messages array, ordered by timestamp.
Then re-run the discover script after the user confirms export is done.
- Option 2:
"Skip Trae" — Continue without Trae data.
- - Do NOT attempt to decrypt or brute-force the database
- The exported JSON file, once created, will be picked up automatically on future runs
OpenCode sessions (SQLite → extracted JSON):
- - The discover script extracts sessions from
~/.local/share/opencode/opencode.db into temp JSON files - Each extracted file: INLINECODE79
- Timestamps are Unix epoch integers (seconds)
- If the extracted JSON files are missing or empty, fall back to querying the DB directly:
CODEBLOCK8
Antigravity / Windsurf (experimental sources):
- - Prefer explicit transcript files (
.jsonl, .json, .txt) when present - If only
state.vscdb / logs are available, treat them as metadata-only context - If readable conversation content cannot be extracted safely, ask the user for an export path instead of guessing
What to analyze
Focus on user messages. The model's responses are background context only. Your goal is to find framework sentences and instances — moments where the user teaches the AI how to think, and scenarios where the user collaborates with the AI to solve problems through multi-turn correction.
For each session, scan every user message for:
- 1. Framework sentences — the user is defining how the world works, not asking the AI to do something:
- Defining essence: "The real issue here is..." / "本质上是……", "The core logic is..." / "核心逻辑是……"
- Correcting AI's thinking (not just its output): "Don't think about it that way" / "你不要这样想", "This isn't an X problem, it's a Y problem" / "这不是 X 问题,是 Y 问题"
- Establishing principles: "Good X should..." / "好的 X 应该……", "Never..." / "永远不要……"
- Making abstractions or analogies across domains
- Expressing aesthetic judgments: "This is ugly" / "太丑了", "Now that's right" / "这才对", "This feels wrong" / "感觉不对"
- Revealing contradictions between different sessions
- 2. Instances — case studies of complex multi-turn tasks where the user's steering reveals their caliber. Think: how would a headhunter describe this person's track record?
- The user drove a complex task across multiple turns, making architectural calls and trade-off decisions that shaped the outcome
- The user applied domain expertise from lived experience — API quirks, platform constraints, industry conventions
- The user's taste and judgment overruled technically correct but aesthetically wrong solutions
- The user connected concepts across domains to reframe the problem
- The story is about the
arc of the task and the user's role in it, not a single correction moment
- 3. Domains touched — what areas does this person work in? (For
topDomains output)
- 4. Projects — what distinct projects is this person building? A "project" is a cohesive product/system the user works on across multiple sessions:
- Look for recurring project names, repo names, product features discussed across sessions
- Extract the project's purpose from how the user describes it or the problems they solve
- Identify highlights — key architectural decisions, clever solutions, or unique approaches revealed in conversations
- Merge sessions about the same project into one entry
- Privacy: anonymize the project name if it contains company/org info, but keep the essence
For the detailed analytical framework (framework sentence detection criteria, instance format, quality tests, and output format), see analysis-prompt.md.
Step 4: Phase 1 — Search Profile (Full Analysis)
This is the first of two output phases. In Phase 1, you generate a complete, unrestricted analysis optimized for search. In Phase 2 (Step 5), you select and refine from Phase 1 results to produce the display version.
CRITICAL — Language detection: Before generating output, scan all user messages to determine the user's primary language. The language the user writes in most is their primary language. ALL generated values MUST be in that language. Do NOT default to English.
Generate the following JSON and save to _pf_parts/search_profile.json:
CODEBLOCK9
Key rules for Phase 1:
- -
frameworkSentences: No quantity limit. Collect ALL framework sentences found. Don't filter — that's Phase 2's job. If the same idea recurs across sessions, merge into one entry with frequency count. - INLINECODE88 : No quantity limit. Each instance is a case study of a complex multi-turn task — how the user steered, what decisions they made, what those decisions reveal about their caliber. Think headhunter describing a candidate's track record, not QA logging corrections.
narrative is a 2-4 sentence third-person vignette with arc (situation → user's key decisions → what it reveals). sparkle is a one-sentence third-party judgment on what makes this person remarkable. Tags follow the user's primary language and must be specific (e.g., "WebSocket重连策略", "支付幂等性" or "WebSocket-reconnection", "payment-idempotency"). - INLINECODE91 : No quantity limit. Each project is a distinct product/system the user works on.
name is the project name (anonymize company names if needed). description is 1-2 sentences about what it is. highlights are 2-5 key decisions or approaches extracted from conversations — think "what would impress a technical reviewer?" Examples: architecture choices, performance optimizations, novel UX patterns, infrastructure decisions. Keep highlights specific and evidence-based. - INLINECODE95 : Max 500 words. A dense, evidence-backed description of this person. Include specific technologies, tools, and domains they work with. This is the primary text used for search embedding — make it information-rich.
- Privacy:
[USER] replaces username. Remove project/company/repo names. Keep domain descriptions generic. - Language: Same rules as everywhere — output in the user's primary language.
Step 5: Phase 2 — Display Version (Curated Portrait)
From the Phase 1 results in _pf_parts/search_profile.json, select and refine to produce the display version.
IMPORTANT — save-as-you-go: Write output to _pf_parts/portrait.json. The activity heat map (_pf_parts/activity.json) and meta (_pf_parts/meta.json) were already saved in Step 2c.
Behavioral fingerprint context: If _pf_parts/behavioral_fingerprint.json exists, read it and include its content as a [BEHAVIORAL FINGERPRINT] section in your analysis context. Use this data to generate behavioralInsights — 3-5 sentences of personalized interpretation that combine multiple data points and tell a story about this person's relationship with AI tools. See analysis-prompt.md for detailed guidelines.
Select the best framework sentences from Phase 1 and generate the portrait:
CODEBLOCK10
Key rules for Phase 2 (display version):
- -
frameworkSentences: Select 5-10 from Phase 1. Pick the most powerful, most unique ones. Prefer high-frequency entries and entries that reveal contradictions. - INLINECODE106 : Use
[USER] as the subject. 2-3 sentences — after reading, you should feel like you can imagine this person. - INLINECODE108 : 4-8 dimensions. Each must be anchored in at least one user quote. Dimension names should be vivid — in English: "the urge to lecture the AI" > "teaching style"; in Chinese: "给 AI 上课的冲动" > "教学风格". Each dimension's
label, left, right are custom-created based on that user's conversations, not templated. score is an integer 0-100, scored based on evidence strength. - INLINECODE113 : 3-5 generic domain descriptions, no project information.
- Language — CRITICAL: ALL generated values must be in the user's primary language. Quotes preserve original language without translation. JSON field names in English.
- Privacy:
[USER] replaces username, remove project/company/repo names.
Save the result to _pf_parts/portrait.json.
Note: _pf_parts/meta.json is auto-generated by compute-stats.py — do NOT write it manually.
Step 6: User Review
Present results to the user in a readable format:
- 1. Activity Heat Map Summary — key numbers from the heat map (most active day, latest night, longest day, totals)
- Projects — list all extracted projects with name, description, and highlights
- Instances — highlight 2-3 of the most interesting instances from Phase 1 (user-AI collaboration stories)
- Framework Sentences — the curated quotes from Phase 2 with their interpretations
- Portrait — the summary and dimensional analysis
After presenting, remind the user:
Privacy note: Only structured analysis results (the content shown above) will be synced to the platform. Your raw conversation logs are NEVER uploaded — all analysis happens locally on your machine.
Then use AskQuestion tool to ask:
- - Question: "Review your profile results"
- Options:
1. "Looks good, proceed to sync" — confirm all results
2. "I want to make adjustments" — tell me what to change
If the user selects option 2, apply changes to the relevant part file(s) (_pf_parts/search_profile.json and/or _pf_parts/portrait.json), re-present, and ask again until they confirm.
Step 7: Upload Draft & Open Preview
7a. Assemble payload
CODEBLOCK11
7b. Upload draft
Upload the payload as a draft (NOT a direct publish):
CODEBLOCK12
7c. Open preview in browser
CODEBLOCK13
Then tell the user:
Your profile preview is ready in the browser. Review your framework sentences — uncheck any you want to keep private — then click Publish when ready.
If the browser didn't open automatically: {API_URL}/me/preview
promptfolio-summarize
你正在构建人类用户的画像——运行此命令的人就是被分析的对象。他们的画像将展示在 promptfolio 平台上。你不是在总结项目,不是在评估 AI 使用技能,也不是在写绩效评估。你是在寻找这个人教 AI 如何思考的时刻——他们的框架句——并用这些句子来描绘他们是谁。
为此,分析他们最近 30 天的 AI 对话历史(Claude Code、Cursor、Codex、ChatGPT、Gemini CLI、Trae、OpenCode、Antigravity、Windsurf、OpenClaw 以及系统上发现的任何其他编码代理),提取活动热力图和揭示此人思维的框架句,然后围绕这些句子构建画像。
基本原则:找到用户正在教学的地方,而不是他们正在命令的地方。 修复这个 bug 告诉不了你什么。不要那样想——这不是性能问题,是用户心理问题 / 你不要这样想,这不是性能问题,是用户心理问题 告诉你一切。
第 0 步:自动更新
在开始其他操作之前,运行自动更新程序以确保你拥有最新的技能文件和数据格式:
bash
bash ~/.promptfolio/update-check.sh
- - 如果输出是 UPDATED v... → 告诉用户:技能已更新至 v{version}。 然后重新读取此 SKILL.md 文件(因为它可能已更改),并从第 1 步继续。
- 如果输出是 UPTODATE v... → 静默继续。
- 如果输出是 OFFLINE v... → 告诉用户:无法检查更新(离线)。使用本地 v{version} 运行。 正常继续。
然后正常继续执行第 1 步。
第 1 步:身份验证
确保 ~/.promptfolio/config.json 存在且包含有效的令牌。
1a. 验证现有令牌(如果配置文件存在):
bash
if [ -f ~/.promptfolio/config.json ]; then
API
TOKEN=$(python3 -c import json; print(json.load(open($HOME/.promptfolio/config.json))[apitoken]))
API
URL=$(python3 -c import json; print(json.load(open($HOME/.promptfolio/config.json)).get(apiurl,https://promptfolio.club)))
HTTP
CODE=$(curl -s -o /dev/null -w %{httpcode} -H Authorization: Bearer $API
TOKEN $APIURL/api/profile/me || true)
echo HTTP
CODE=$HTTPCODE
fi
- - 如果 HTTP 200,继续执行第 2 步。
- 如果配置文件缺失或 HTTP 不是 200,运行设备授权脚本:
1b. 运行设备授权:
bash
bash SKILL_DIR/../scripts/device-auth.sh
将 SKILL_DIR 替换为包含此 SKILL.md 文件的目录。该脚本处理所有事情:请求设备代码、打开浏览器、轮询直到授权、保存 ~/.promptfolio/config.json。
重要: 你必须按原样运行脚本。不要自己重新实现授权流程。不要手动构建授权 URL——让脚本处理一切。
如果脚本失败,告诉用户授权超时,请重试。
第 2 步:发现会话
在运行任何命令之前,告诉用户:
所有对话分析都在你的本地机器上执行。分析期间不会将原始对话内容发送到任何服务器。只有在你明确确认后,结构化结果才会被上传。
2a. 检测已安装的工具
在扫描之前,检查用户实际安装了哪些 AI 编码工具。查找它们的配置/数据目录:
| 工具 | 如何检测 |
|---|
| Claude Code | ~/.claude/projects/ 存在 |
| Cursor |
~/.cursor/projects/ 存在 |
| Codex | ~/.codex/ 存在 |
| OpenClaw | ~/.openclaw/ 存在 |
| Gemini CLI | ~/.gemini/tmp/ 存在(包含 chats/ 子目录) |
| Antigravity | ~/Library/Application Support/Antigravity/ 或 ~/.gemini/antigravity/ 存在 |
| Windsurf | ~/.codeium/windsurf/、~/.windsurf/ 或 ~/Library/Application Support/Windsurf/ 存在 |
| ChatGPT | ~/Desktop/chatgpt_history/ 存在(用户必须手动导出数据) |
| Trae | ~/.trae/、~/.trae-cn/ 或 App Support Trae 目录存在(注意:数据库已加密) |
| OpenCode | ~/.local/share/opencode/opencode.db 存在 |
运行快速检查:
bash
echo === 检测到的 AI 工具 ===
[ -d ~/.claude/projects ] && echo claude-code
[ -d ~/.cursor/projects ] && echo cursor
[ -d ~/.codex ] && echo codex
[ -d ~/.openclaw ] && echo openclaw
[ -d ~/.gemini/tmp ] && echo gemini-cli
[ -d $HOME/Library/Application Support/Antigravity ] || [ -d ~/.gemini/antigravity ] && echo antigravity
[ -d ~/.codeium/windsurf ] || [ -d ~/.windsurf ] || [ -d $HOME/Library/Application Support/Windsurf ] && echo windsurf
[ -d ~/Desktop/chatgpt_history ] && echo chatgpt
[ -d $HOME/Library/Application Support/Trae CN/ModularData/ai-agent ] || [ -d $HOME/Library/Application Support/Trae/ModularData/ai-agent ] && echo trae
[ -f $HOME/.local/share/opencode/opencode.db ] && echo opencode
然后扫描上述列表中未包含的其他编码代理。查找 ~/ 中的点目录和 ~/Library/Application Support/ 中看起来像 AI 编码工具的应用目录(例如 Kiro、Aider、Continue、Copilot Chat、Trae、Roo Code 等):
bash
echo === 检查其他编码代理 ===
ls -d ~/.kiro ~/.aider ~/.continue ~/.roo 2>/dev/null || true
ls -d $HOME/Library/Application Support/Kiro $HOME/Library/Application Support/Continue 2>/dev/null || true
如果你发现任何未知的工具目录,查看内部是否包含对话日志(.jsonl、.json、.txt)。如果包含,则包括它们——无需询问用户。
展示结果:检测到:Claude Code, Cursor。还发现:Kiro(有会话日志)。
为脚本设置 PF_SOURCES 为已知工具,并在 2b 中手动处理未知工具。
2b. 查找会话文件
运行发现脚本,仅针对检测到的工具:
bash
export PF_SOURCES=claude-code,cursor # 仅来自 2a 检测到的工具
SESSIONLIST=$(bash SKILLDIR/scripts/discover-sessions.sh)
export SESSION_LIST
该脚本扫描每个工具的已知位置,并过滤到最近 30 天。运行后:
- 1. 检查零会话工具——如果检测到的工具有 0 个会话,自行探索其数据目录以查找脚本遗漏的文件。
- 处理未知工具——对于在 2a 中发现的任何额外编码代理,探索其数据目录,查找对话日志文件(.jsonl、.json、.txt),并将它们附加到 $SESSION_LIST。
- 询问用户他们是否有非标准位置或来自你未检测到的工具的会话数据。
如果你找到额外的会话文件,将它们附加到 $SESSION_LIST。
2c. 计算统计信息 + 活动数据
运行统计脚本以一次性计算令牌估计并提取活动热力图数据:
bash
python3 SKILL_DIR/scripts/compute-stats.py
这会读取 $SESSION_LIST 并生成:
- - stdout:每个来源的会话/令牌摘要
- pfparts/activity.json:用于热力图可视化的每日活动数据
2d. 呈现摘要并询问用户
向用户呈现摘要:
- - 找到的会话总数(最近 30 天),按来源分组
- 活动热力图亮点:最活跃的一天、最晚的夜晚、最长的会话
- 估计的总令牌数(标记为估计)
然后使用 AskQuestion 工具 询问:
1. 是的,分析这些会话 — 继续执行第 3 步
2. 不,让我调整 — 询问用户要更改什么
第 3