/profile
Session clock-time AND token/cost analyzer. Reads the foundry plugin's timings.jsonl and invocations.jsonl logs (written by task-log.js) for wall-time, plus Claude Code transcripts (~/.claude/projects/**, main-loop + subagent files) for token usage and USD cost, and merges both
Claude Code
$ npx -y skills add Borda/AI-Rig --skill profile --agent claude-code
Codex
$ npx skills add Borda/AI-Rig --skill profile -a codex -y
Cursor
$ npx skills add Borda/AI-Rig --skill profile -a cursor -y
Gemini CLI
$ npx skills add Borda/AI-Rig --skill profile -a gemini-cli -y
GitHub Copilot
$ npx skills add Borda/AI-Rig --skill profile -a github-copilot -y
OpenCode
$ npx skills add Borda/AI-Rig --skill profile -a opencode -y
Windsurf
$ npx skills add Borda/AI-Rig --skill profile -a windsurf -y
SKILL.md
profile.SKILL.mdname: profile
description: "Session clock-time AND token/cost analyzer. Reads the foundry plugin's timings.jsonl and invocations.jsonl logs (written by task-log.js) for wall-time, plus Claude Code transcripts (~/.claude/projects/**, main-loop + subagent files) for token usage and USD cost, and merges both into one per-session and per-skill report — local-tool vs subagent-spawn vs Skill vs AskUserQuestion idle vs main-loop reasoning residual time, and main-loop vs subagent spend by model tier. Useful for answering \"why did /oss:resolve run 30 minutes?\", \"what did this session cost?\", or \"which skill burns the most tokens?\". Pure log/transcript read — no instrumentation, no skill edits, no LLM calls. TRIGGER when: user asks where wall-clock time OR tokens/cost go during a skill/session, why a skill is slow or expensive, what dominates total runtime or spend, or wants a per-skill rollup over a recent window; phrases: \"where does time go\", \"why so slow\", \"what did this cost\", \"token spend\", \"why so expensive\", \"profile last session\", \"clock breakdown\", \"session timing\", \"which skill burns tokens\". SKIP: per-line Python perf (use foundry:perf-optimizer); known failure or hang (use /foundry:investigate); a real billing statement (prices are public list rates, not effective plan rates)."
argument-hint: '[--since 24h|7d|30d] [--session-id ID] [--top-n N]'
allowed-tools: Read, Write, Bash, TaskList, TaskCreate, TaskUpdate, AskUserQuestion
effort: low
<objective>
Bucket session **clock time** from `~/.claude/logs/{timings,invocations}.jsonl` into:
1. **Local tools** — Bash/Read/Edit/Write/Grep/Glob and other main-process tools 2. **Agent / subagent spawns** — Task/Agent calls (sync + background) 3. **Skill** — `tool=Skill` wall durations 4. **AskUserQuestion idle** — human-wait, separate column, excluded from compute total 5. **Main-loop reasoning (residual)** — session wall minus buckets above
...and bucket session **tokens/cost** from Claude Code transcripts (`~/.claude/projects/**`, main-loop + subagent files) into:
6. **Sessions ranked by cost** (window mode) — main $ vs subagent $ vs total $ per session, plus a per-command rollup; or **one session's deep-dive** (`--session-id`) — cost by main/sidechain × model tier, agent roster, top cache-rebuild calls, cold-start share
Outputs a markdown report at `.reports/profile/<UTC-timestamp>/report.md` plus a `.temp/output-profile-...md` copy: per-session clock table, per-skill clock rollup, top-N longest single calls, plus a `## Tokens & cost` section scoped to same window / `--session-id`.
NOT for: per-line Python perf (use `foundry:perf-optimizer`); known failure diagnosis (use `/foundry:investigate`); a real billing statement (prices are public list rates, not effective plan rates).
</objective>
<inputs>
- **`--since DURATION`** (default `24h`) — window: `NNs|NNm|NNh|NNd`
- **`--session-id ID`** — optional; restrict to one session
- **`--top-n N`** (default `5`) — slowest single calls to list
If $ARGUMENTS empty, default window is 24h.
</inputs>
<workflow>
**Task hygiene** — task tools may be deferred; load before first use: `ToolSearch(query="select:TaskList,TaskCreate,TaskUpdate,TaskGet", max_results=4)`. Call `TaskList` first and triage each task it returns: `completed` if work clearly done, `deleted` if orphaned, keep `in_progress` only if genuinely continuing. Never spend a turn on bookkeeping alone — every `TaskCreate`/`TaskUpdate` ships in the same response as the next substantive tool call; one exception, `TaskUpdate(completed)` immediately before a long output block (`rules/task-lifecycle.md`).
**Task tracking**: TaskCreate two tasks up front — 1 "Run analyzers + render report" (Steps 1–3), 2 "Step 4: Print report header" (Step 4). Mark each `in_progress` before its first tool call; 1 completed once `report.md` exists, 2 completed right after the header and path are printed, before the executive summary.
Step 1: Parse args + create run dir
**Unsupported flag check** — before executing Step 2, scan `$ARGUMENTS` for `--<token>` patterns. Supported: `--since`, `--session-id`, `--top-n` (space-separated or `=` values). Any other flag, including `--noop` (an internal parser placeholder, not a supported profile flag): invoke `AskUserQuestion` with question text `` ! Unknown flag(s): `--<token>`. Supported: `--since`, `--session-id`, `--top-n`. `` — (a) **Abort** (stop, re-invoke with correct flags) · (b) **Continue ignoring** (remove unknown flags before passing `$ARGUMENTS` to Step 2). On Abort: stop.
The first part of the Step 2 block below does this step (one Bash call with the clock-time analyzer): argument text is parsed in `bin/` and validated against closed patterns before use, then persisted as `KEY=VALUE` lines to `${TMPDIR:-/tmp}/foundry-profile-state-${CSID}`; Steps 2b–3 read it back key by key, never sourcing it (bash state doesn't persist across Bash calls, and `REPORT_DIR` carries a per-shell timestamp that can't be re-derived).
Step 2: Run analyzers — clock time, then tokens/cost
PLUGIN_ROOT=$(python "${CLAUDE_PLUGIN_ROOT}/bin/resolve_plugin_root.py" --plugin-name foundry) || exit $?; export PLUGIN_ROOT
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
# timeout: 60000
# --flags is mandatory for the helper; profile has no boolean flags. --keep-state: no eval; --inlined: profile keeps no compaction contract, so it clears none
python "$PLUGIN_ROOT/bin/parse-skill-flags.py" --flags noop --value-flags since,session-id,top-n --keep-state profile --inlined -- "$ARGUMENTS" >/dev/null
IFS= read -r SINCE < "${TMPDIR:-/tmp}/profile-since-${CSID}" 2>/dev/null; SINCE="${SINCE:-24h}"
IFS= read -r TOP_N < "${TMPDIR:-/tmp}/profile-top-n-${CSID}" 2>/dev/null; TOP_N="${TOP_N:-5}"
IFS= read -r SESSION_ID < "${TMPDIR:-/tmp}/profile-session-id-${CSID}" 2>/dev/null || SESSION_ID=""
[[ $SINCE =~ ^[0-9]+[smhd]$ && $TOP_N =~ ^[0-9]+$ && $SESSION_ID =~ ^[A-Za-z0-9._-]*$ ]] || { echo "! BLOCKERead more
name: profile description: "Session clock-time AND token/cost analyzer. Reads the foundry plugin's timings.jsonl and invocations.jsonl logs (written by task-log.js) for wall-time, plus Claude Code transcripts (~/.claude/projects/**, main-loop + subagent files) for token usage and USD cost, and merges both into one per-session and per-skill report — local-tool vs subagent-spawn vs Skill vs AskUserQuestion idle vs main-loop reasoning residual time, and main-loop vs subagent spend by model tier. Useful for answering \"why did /oss:resolve run 30 minutes?\", \"what did this session cost?\", or \"which skill burns the most tokens?\". Pure log/transcript read — no instrumentation, no skill edits, no LLM calls. TRIGGER when: user asks where wall-clock time OR tokens/cost go during a skill/session, why a skill is slow or expensive, what dominates total runtime or spend, or wants a per-skill rollup over a recent window; phrases: \"where does time go\", \"why so slow\", \"what did this cost\", \"token spend\", \"why so expensive\", \"profile last session\", \"clock breakdown\", \"session timing\", \"which skill burns tokens\". SKIP: per-line Python perf (use foundry:perf-optimizer); known failure or hang (use /foundry:investigate); a real billing statement (prices are public list rates, not effective plan rates)." argument-hint: '[--since 24h|7d|30d] [--session-id ID] [--top-n N]' allowed-tools: Read, Write, Bash, TaskList, TaskCreate, TaskUpdate, AskUserQuestion effort: low
<objective>
Bucket session **clock time** from `~/.claude/logs/{timings,invocations}.jsonl` into:
1. **Local tools** — Bash/Read/Edit/Write/Grep/Glob and other main-process tools 2. **Agent / subagent spawns** — Task/Agent calls (sync + background) 3. **Skill** — `tool=Skill` wall durations 4. **AskUserQuestion idle** — human-wait, separate column, excluded from compute total 5. **Main-loop reasoning (residual)** — session wall minus buckets above
...and bucket session **tokens/cost** from Claude Code transcripts (`~/.claude/projects/**`, main-loop + subagent files) into:
6. **Sessions ranked by cost** (window mode) — main $ vs subagent $ vs total $ per session, plus a per-command rollup; or **one session's deep-dive** (`--session-id`) — cost by main/sidechain × model tier, agent roster, top cache-rebuild calls, cold-start share
Outputs a markdown report at `.reports/profile/<UTC-timestamp>/report.md` plus a `.temp/output-profile-...md` copy: per-session clock table, per-skill clock rollup, top-N longest single calls, plus a `## Tokens & cost` section scoped to same window / `--session-id`.
NOT for: per-line Python perf (use `foundry:perf-optimizer`); known failure diagnosis (use `/foundry:investigate`); a real billing statement (prices are public list rates, not effective plan rates).
</objective>
<inputs>
- **`--since DURATION`** (default `24h`) — window: `NNs|NNm|NNh|NNd`
- **`--session-id ID`** — optional; restrict to one session
- **`--top-n N`** (default `5`) — slowest single calls to list
If $ARGUMENTS empty, default window is 24h.
</inputs>
<workflow>
**Task hygiene** — task tools may be deferred; load before first use: `ToolSearch(query="select:TaskList,TaskCreate,TaskUpdate,TaskGet", max_results=4)`. Call `TaskList` first and triage each task it returns: `completed` if work clearly done, `deleted` if orphaned, keep `in_progress` only if genuinely continuing. Never spend a turn on bookkeeping alone — every `TaskCreate`/`TaskUpdate` ships in the same response as the next substantive tool call; one exception, `TaskUpdate(completed)` immediately before a long output block (`rules/task-lifecycle.md`).
**Task tracking**: TaskCreate two tasks up front — 1 "Run analyzers + render report" (Steps 1–3), 2 "Step 4: Print report header" (Step 4). Mark each `in_progress` before its first tool call; 1 completed once `report.md` exists, 2 completed right after the header and path are printed, before the executive summary.
Step 1: Parse args + create run dir
**Unsupported flag check** — before executing Step 2, scan `$ARGUMENTS` for `--<token>` patterns. Supported: `--since`, `--session-id`, `--top-n` (space-separated or `=` values). Any other flag, including `--noop` (an internal parser placeholder, not a supported profile flag): invoke `AskUserQuestion` with question text `` ! Unknown flag(s): `--<token>`. Supported: `--since`, `--session-id`, `--top-n`. `` — (a) **Abort** (stop, re-invoke with correct flags) · (b) **Continue ignoring** (remove unknown flags before passing `$ARGUMENTS` to Step 2). On Abort: stop.
The first part of the Step 2 block below does this step (one Bash call with the clock-time analyzer): argument text is parsed in `bin/` and validated against closed patterns before use, then persisted as `KEY=VALUE` lines to `${TMPDIR:-/tmp}/foundry-profile-state-${CSID}`; Steps 2b–3 read it back key by key, never sourcing it (bash state doesn't persist across Bash calls, and `REPORT_DIR` carries a per-shell timestamp that can't be re-derived).
Step 2: Run analyzers — clock time, then tokens/cost
PLUGIN_ROOT=$(python "${CLAUDE_PLUGIN_ROOT}/bin/resolve_plugin_root.py" --plugin-name foundry) || exit $?; export PLUGIN_ROOT
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
# timeout: 60000
# --flags is mandatory for the helper; profile has no boolean flags. --keep-state: no eval; --inlined: profile keeps no compaction contract, so it clears none
python "$PLUGIN_ROOT/bin/parse-skill-flags.py" --flags noop --value-flags since,session-id,top-n --keep-state profile --inlined -- "$ARGUMENTS" >/dev/null
IFS= read -r SINCE < "${TMPDIR:-/tmp}/profile-since-${CSID}" 2>/dev/null; SINCE="${SINCE:-24h}"
IFS= read -r TOP_N < "${TMPDIR:-/tmp}/profile-top-n-${CSID}" 2>/dev/null; TOP_N="${TOP_N:-5}"
IFS= read -r SESSION_ID < "${TMPDIR:-/tmp}/profile-session-id-${CSID}" 2>/dev/null || SESSION_ID=""
[[ $SINCE =~ ^[0-9]+[smhd]$ && $TOP_N =~ ^[0-9]+$ && $SESSION_ID =~ ^[A-Za-z0-9._-]*$ ]] || { echo "! BLOCKEPractical agent workflows for Python, ML, and open-source maintenance. AI-Rig turns recurring work—scoping a change, reproducing a bug, reviewing a pull request, running an experiment, or checking release readiness—into explicit workflows with specialist
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about profile.
- Which coding agents can use profile?
- profile installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

