- name
- readme-skill
- description
- 生成一份对外可分享、脱敏的 AI-Native 开发者 README。 量化展示我对 Claude Code + Codex CLI + Kiro (AWS) + Trae (ByteDance) + Gemini Antigravity (Google) + Cursor 的使用深度、AI 协作风格、 项目与领域分布、兴趣主题,以及与 GitHub 提交的产出关联。 Trigger when the user says: "生成我的 AI 档案" / "做一份 AI-native README" / "分析我的 Claude / Codex / Kiro / Trae / Antigravity / Cursor 使用情况" / "总结我的 AI 使用" / "生成 AI 月度报告" / "按月份分析我的 AI 编码" / "分析 2026-05 的 AI 使用" / "build my AI usage profile" / "build my monthly AI coding report" / "analyze my AI usage for May 2026" / "summarize my Claude / Codex / Kiro / Trae / Antigravity / Cursor history" / "生成开发者画像". 全程本地、只读、默认匿名、不上传任何数据。
- license
- MIT
# Readme.skill — AI-Native 开发者档案生成器
You (the AI agent invoking this skill) will read local Claude Code + Codex CLI
+ Kiro (AWS) + Trae (ByteDance) + Gemini Antigravity (Google) + Cursor data,
compute a fixed set of dimensions, and render both a Markdown profile and a
validated SVG poster under `./output/` in the user's requested language (Chinese
by default; English when the user asks in English or explicitly requests
English). The profile and poster can cover the default history view or an
explicit month / date range. **You do all of the work** — read the files with
`Read`, query sqlite via `Bash`, synthesize the prose yourself, then write and
validate the SVG. Do **not** write helper scripts; the skill is the recipe.
> 支持的 6 个 AI 编程工具(任一缺失都自动降级跳过):
> 1. **Claude Code** (`~/.claude/`) — Step 2
> 2. **Codex CLI** (`~/.codex/`) — Step 3
> 3. **Kiro CLI / IDE** (`~/.kiro/` + `~/.local/share/kiro-cli/`) — Step 3b
> 4. **Trae IDE** (`~/Library/Application Support/Trae/` + 项目 `.trae/`) — Step 3c
> 5. **Gemini Antigravity** (`~/.gemini/antigravity/brain/`) — Step 3d
> 6. **Cursor** (`~/Library/Application Support/Cursor/` + 项目 `.cursor/`) — Step 3e
> 默认行为:**对外分享版** —— 项目名匿名、敏感信息脱敏。
> 如果用户明确说"私人版 / 不要脱敏 / show real names",跳过匿名步骤。
---
## Step 1 — 准备
```bash
cd <repo-with-this-skill> # e.g. ~/Projects/Readme.skill
mkdir -p output
DATE=$(date +%Y%m%d)
```
Decide anonymization mode (default = on). Build an in-memory mapping
`real_path → "项目 A/B/C"` as you encounter project paths in later steps.
Use the same mapping consistently across all sections.
### 1.1 时间窗口 / 月度报告模式
If the user asks for a month, quarter, stage, date range, "月度报告",
"按月份分析", "time range", "monthly report", or similar, set a report window
before reading any data. The window is a half-open local-date interval:
`[REPORT_START, REPORT_END_EXCL)`.
Supported phrases:
- Single month: `2026-05`, `2026年5月`, `May 2026` → `REPORT_START=2026-05-01`,
`REPORT_END_EXCL=2026-06-01`, `REPORT_LABEL=2026-05`,
`REPORT_SLUG=202605`, `REPORT_MODE=monthly`
- Month range: `2026-04 到 2026-05`, `Apr-May 2026` → start at the first day of
the first month, end at the first day after the last month,
`REPORT_MODE=range`
- Explicit dates: `2026-05-03 到 2026-05-19` / `2026-05-03..2026-05-19` →
include both named dates by setting `REPORT_END_EXCL` to the day after the
final date, `REPORT_MODE=range`
- Relative range: `最近30天` / `last 30 days` → compute from today's local date,
`REPORT_MODE=range`
If no explicit time window is requested, keep the existing default profile
behavior: AI tool totals may use all available local history, while GitHub and
local git use their existing 365-day windows. Set `WINDOW_REQUESTED=0`.
If a window is requested, set:
```bash
WINDOW_REQUESTED=1
REPORT_START=<YYYY-MM-DD>
REPORT_END_EXCL=<YYYY-MM-DD> # exclusive
REPORT_LABEL=<human-readable label, e.g. "2026-05" or "2026-04..2026-05">
REPORT_SLUG=<filesystem-safe slug, e.g. "202605" or "202604-202605">
```
For every source below, include only records whose timestamp is
`>= REPORT_START 00:00:00` and `< REPORT_END_EXCL 00:00:00` in local time.
Never mix all-time counts into a windowed report unless the metric is explicitly
labeled "all-time context" or "fallback, not window-filtered".
For windowed reports, also compute a previous comparison window of the same
length when possible:
```bash
# macOS date syntax. Use equivalent date math on other systems.
window_start_ts=$(date -j -f "%Y-%m-%d" "$REPORT_START" +%s)
window_end_ts=$(date -j -f "%Y-%m-%d" "$REPORT_END_EXCL" +%s)
WINDOW_DAYS=$(( (window_end_ts - window_start_ts) / 86400 ))
PREV_END_EXCL="$REPORT_START"
PREV_START=$(date -j -v-"${WINDOW_DAYS}"d -f "%Y-%m-%d" "$REPORT_START" +%Y-%m-%d)
```
---
## Step 2 — 读取 Claude Code 数据 (`~/.claude/` + 项目 `.claude/`)
### 2.1 预聚合统计(最权威,先看这个)
Read `~/.claude/stats-cache.json`. Extract:
| 字段 | 含义 |
| --- | --- |
| `totalSessions` | session 总数 |
| `totalMessages` | 消息总数 |
| `firstSessionDate` | 首个 session ISO 时间 |
| `longestSession.{duration,messageCount,timestamp}` | 最长 session |
| `hourCounts` | `{hour: count}` 24h 热力 |
| `modelUsage[model].{inputTokens,outputTokens,cacheReadInputTokens,cacheCreationInputTokens}` | 每模型 token 细分 |
| `dailyActivity[].{date,messageCount,sessionCount,toolCallCount}` | 每日活跃 |
| `dailyModelTokens[].{date,tokensByModel}` | 每日按模型 token |
**派生量(你来算)**:
- `claude_tokens_spent = Σ (inputTokens + outputTokens + cacheCreationInputTokens)` —— 真实新付费 token
- `claude_cache_read = Σ cacheReadInputTokens` —— 缓存复用,反映 prompt-caching 熟练度
- `cache_to_spent_ratio = claude_cache_read / claude_tokens_spent` —— 比值越大越熟
**时间窗口模式**:如果 `WINDOW_REQUESTED=1`,优先从 `dailyActivity` 与
`dailyModelTokens` 中按 `REPORT_START <= date < REPORT_END_EXCL` 过滤后汇总
Claude sessions / messages / tokens / cache。`modelUsage` 是全局聚合;只有默认
profile 模式才能直接当总量使用。若某个 Claude 字段只有全局聚合、无法按日期切分,
在月度报告里写 `—` 或标注「仅有 all-time 聚合,未纳入窗口统计」,不要把全局值混进
月度值。
### 2.2 Slash-command 热度
`~/.claude/history.jsonl` —— 每行 `{display, timestamp, project, sessionId}`。
```bash
# Top 15 slash commands
jq -r 'select(.display | startswith("/")) | (.display | split(" ")[0])' \
~/.claude/history.jsonl | sort | uniq -c | sort -rn | head -15
# 总条数 vs 命令条数 vs 直接 prompt 条数
total=$(wc -l < ~/.claude/history.jsonl)
cmd=$(jq -r 'select(.display | startswith("/")) | .display' ~/.claude/history.jsonl | wc -l)
echo "total=$total cmd=$cmd plain=$((total - cmd))"
```
时间窗口模式下,所有 `history.jsonl` 统计先过滤:
```bash
jq --arg start "$REPORT_START" --arg end "$REPORT_END_EXCL" '
select((.timestamp // "")[0:10] >= $start and (.timestamp // "")[0:10] < $end)
' ~/.claude/history.jsonl
```
记录:`/effort`、`/plan`、`/skill*`、`/usage`、`/clear`、`/resume`、`/compact`、`/init` 各自次数。
### 2.3 项目分布 (`~/.claude/projects/`)
Each subdir is one project; per-project `*.jsonl` files = sessions.
The dir name encodes the absolute path with `/` → `-` (ambiguous when the
original path itself contains `-`).
```bash
# Top 15 by session-file count
for d in ~/.claude/projects/*/; do
n=$(ls "$d"*.jsonl 2>/dev/null | wc -l | tr -d ' ')
echo "$n $(basename "$d")"
done | sort -rn | head -15
```
To recover the canonical real path (so you can run `git log` later), read
the `cwd` field from the first JSONL in each dir:
```bash
head -1 ~/.claude/projects/<encoded>/*.jsonl 2>/dev/null \
| jq -r 'select(.cwd) | .cwd' | head -1
```
### 2.4 计划与 skill 自研
Claude Code 的 plan 文件目录不是固定值。默认在 `~/.claude/plans`,
但用户可以通过 `plansDirectory` 改到项目工作目录下,例如
`"./.claude/plans"`。统计 plans 时必须先解析候选 plan 目录,不能只枚举
`~/.claude/plans/*.md`。
解析规则:
- 先从 `~/.claude/projects/*/*.jsonl` 的 `cwd` 字段恢复 Claude Code 访问过的项目根目录。
- 对每个项目根目录,按 Claude Code settings 优先级读取:
`.claude/settings.local.json` > `.claude/settings.json` > `~/.claude/settings.json` > default。
- 如果有效 settings 中存在 `plansDirectory`:
- 绝对路径保持不变;
- `~/...` 展开为 `$HOME/...`;
- `./...` 或其他相对路径按该项目根目录解析。
- 如果没有配置,使用默认 `~/.claude/plans`。
- 把所有候选目录下的 `*.md` 真实路径去重后,再统计 plan 数量和标题。
```bash
# Plan titles (first # heading of each plan) from all resolved plan dirs.
# Include ~/.claude/plans plus any per-project plansDirectory targets.
# Count plan files by file count, not by title extraction success.
plan_count=<resolved-plan-file-count>
for f in <resolved-plan-files>; do
awk '/^# / { sub(/^# /, ""); print; exit }' "$f"
done
ls ~/.claude/skills/ | wc -l # skills installed / authored
ls ~/.claude/tasks/ | wc -l # tasks tracked
ls ~/.claude/todos/ | wc -l
```
### 2.4b Skill 清单(AI 基础设施采集)
For each `~/.claude/skills/*/SKILL.md` and `~/.codex/skills/*/SKILL.md`,
**use the `Read` tool to inspect the frontmatter** (top of file, between `---` markers). Extract `name` and the full `description` as YAML semantics dictate.
Support all four YAML scalar styles:
| 写法 | 处理 |
| --- | --- |
| 单行: `description: foo bar` | 直接取冒号后内容 |
| 引号: `description: "foo bar"` 或 `'foo bar'` | 去掉首尾引号 |
| `>` folded(多行折叠) | join indented continuation lines with spaces |
| `\|` literal(多行保留) | preserve line breaks |
停止条件:遇到下一个**未缩进的 frontmatter key**(行首无空格且形如 `key:`),或遇到关闭的 `---` 行。如果 `description` 字段缺失,回落到 `<目录名> (no description)`。
**绝不使用 `head \| grep`** —— 那会把 `>`/`\|` 多行风格静默截断到只剩 `>`,这是 v2.2 之前的真实 bug。务必 `Read` 完整 frontmatter 后按 YAML 语义解析。
枚举候选 skill 目录:
```bash
ls -d ~/.claude/skills/*/ ~/.codex/skills/*/ 2>/dev/null
```
然后对每个目录:`Read` 它的 `SKILL.md` 头部 ~30 行 → 按上表解析 YAML → 输出 `<source>|<name>|<full_description>`。
记录每个 skill 是「自建」还是「安装」。如果 skill 目录下有 git remote 指向用户自己的 repo,标记为自建;否则标记为安装。
### 2.5 配置深度
Read `~/.claude/settings.json`. Count:
- `hooks` 个数(结构化自动化能力)
- `mcpServers` 个数(外部能力接入)
- `permissions.defaultMode`
---
## Step 3 — 读取 Codex CLI 数据 (`~/.codex/`)
### 3.1 SQLite (read-only)
The primary analytics store is `~/.codex/state_5.sqlite`, table `threads`.
**Always open with `mode=ro`** so you can never write:
```bash
SQ='sqlite3 file:'"$HOME"'/.codex/state_5.sqlite?mode=ro&immutable=1'
# If WINDOW_REQUESTED=1, compute unix-second bounds once and add the filter to
# every threads query below. For queries that already have WHERE, append `AND`.
FROM_TS=$(date -j -f "%Y-%m-%d" "$REPORT_START" +%s 2>/dev/null || true)
TO_TS=$(date -j -f "%Y-%m-%d" "$REPORT_END_EXCL" +%s 2>/dev/null || true)
# created_at >= FROM_TS AND created_at < TO_TS
# Aggregate
$SQ "SELECT COUNT(*), SUM(tokens_used), MIN(created_at), MAX(created_at) FROM threads;"
# Model breakdown (note: empty/NULL model = older sessions, label as 'Codex (未标注)')
$SQ "SELECT COALESCE(NULLIF(model,''),'Codex(未标注)'), COUNT(*), SUM(tokens_used) \
FROM threads GROUP BY 1 ORDER BY 3 DESC;"
# Reasoning effort distribution (xhigh / high / medium / low / unspecified)
$SQ "SELECT COALESCE(NULLIF(reasoning_effort,''),'unspecified'), COUNT(*) \
FROM threads GROUP BY 1 ORDER BY 2 DESC;"
# Top 15 working dirs
$SQ "SELECT cwd, COUNT(*), SUM(tokens_used) FROM threads \
WHERE cwd != '' GROUP BY cwd ORDER BY 2 DESC LIMIT 15;"
# Hour-of-day heatmap
$SQ "SELECT strftime('%H', datetime(created_at,'unixepoch')), COUNT(*) \
FROM threads GROUP BY 1 ORDER BY 1;"
# Day-of-activity timeseries
$SQ "SELECT date(created_at,'unixepoch'), COUNT(*) FROM threads GROUP BY 1;"
# Sample titles + first user messages for keyword extraction (titles only — no body)
$SQ "SELECT title FROM threads WHERE title != '' ORDER BY created_at DESC LIMIT 200;"
$SQ "SELECT first_user_message FROM threads WHERE first_user_message != '' \
ORDER BY created_at DESC LIMIT 200;"
# CLI versions used (Codex evolution signal)
GitHubで見る