Help us improve
Share bugs, ideas, or general feedback.
From agent-flow
Generates pipeline analytics reports from issue tracker and git data — success rate, per-agent effectiveness, failure patterns, optional HTML dashboard.
npx claudepluginhub asysta-act/agent-flow --plugin agent-flowHow this skill is triggered — by the user, by Claude, or both
Slash command
/agent-flow:metrics [--period <N>] [--output <path>] [--format <md|json|html>][--period <N>] [--output <path>] [--format <md|json|html>]This skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Input: `$ARGUMENTS` = optional flags (`--period <N>`, `--output <path>`, `--format <md|json|html>`)
Collects agent usage metrics from git history and generates health reports or dashboards. Use for measuring adoption rates, system health, or periodic reviews via Python script.
Collects agent usage metrics from git history via Python script and generates markdown/JSON health reports. Use for measuring adoption, system health, or dashboards.
Analyzes git commit history for engineering retrospectives, tracking work patterns, code quality metrics, trends, per-person breakdowns, shipping streaks, and actionable improvements. Use for 'retro', weekly reviews, or 'what did we ship'.
Share bugs, ideas, or general feedback.
Input: $ARGUMENTS = optional flags (--period <N>, --output <path>, --format <md|json|html>)
FORMAT="" # empty = no flag supplied = trigger interactive prompt path
PERIOD=30
OUTPUT=""
while [[ $# -gt 0 ]]; do
case "$1" in
--period)
PERIOD="$2"; shift 2
;;
--output)
OUTPUT="$2"; shift 2
;;
--format)
FORMAT="$2"; shift 2
[[ "$FORMAT" =~ ^(md|json|html)$ ]] || { echo "Error: --format must be 'md', 'json', or 'html'"; exit 1; }
;;
*)
shift
;;
esac
done
# Sentinel for interactive-prompt path
NO_FORMAT_FLAG=0
if [ -z "$FORMAT" ]; then
NO_FORMAT_FLAG=1
FORMAT="md" # default render is markdown; prompt fires AFTER render
fi
--period N → period in days (default: 30)--output path → output file (default: stdout)--format md|json|html → output format (default: md with interactive prompt)Read Automation Config from CLAUDE.md section ## Automation Config:
Before any pipeline operation, verify MCP tool availability:
mcp__* tool matching the tracker type is accessible/agent-flow:check-setup for diagnostics."Via MCP server (per Issue Tracker → Type), fetch all issues matching Bug query + Feature query (if it exists). For each issue: ID, title, state, comments, created date.
For each issue, go through comments. Extract:
Triage checkpoint:
Regex: ^\[agent-flow\] Triage completed\. Severity: (.+)\. Area: (.+)\.$
Spec checkpoint:
Regex: ^\[agent-flow\] Spec analysis completed\. Area: (.+)\. Criteria: (.+)\.$
Block comment:
Regex (multiline): ^\[agent-flow\] 🔴 Pipeline Block
Following lines: Agent: (.+), Step: (.+), Reason: (.+), Detail: (.+), Recommendation: (.+)
PR link:
Regex: PR: (https?://\S+) or #(\d+)
git log --oneline --since="{period} days ago" via Bash. Parse commit messages for issue ID references.
total_attempted = issues with a [agent-flow] comment in the given periodtotal_fixed = issues with PR merged (or in a state from State transitions → For Review/Done)total_blocked = issues with a [agent-flow] 🔴 Pipeline Block comment and still in Blocked statesuccess_rate = total_fixed / total_attempted (percentage)avg_time_to_fix = average time from the first [agent-flow] comment to merged PR (if data available)block_by_stage = count of blocks per pipeline stage (triage, analysis, fix, review, test, publish)top_block_reasons = top 5 most frequent "Reason:" values from block commentsFor each agent (analyst, fixer, reviewer, test-engineer, browser-agent, publisher, scaffolder, spec-writer, spec-analyst, architect, acceptance-gate, deployment-verifier, backlog-creator, sprint-planner, priority-engine, spec-reviewer, rollback-agent): count blocks, success rate, most frequent failure reason.
avg_fixer_iterations = from reviewer comments (how many REQUEST_CHANGES before APPROVE)failure_pattern_detection = if an agent blocks > 30% of issues → flag pattern with top reasonPer-issue estimate (heuristic fallback): count stages × model tokens (sonnet ~30k, opus ~50k, haiku ~5k per invocation). Total estimate for the period.
For each issue identified in Step 4, glob .agent-flow/*/state.json to locate per-run state files. Classify each pipeline run:
pipeline.total_tokens is present in state.json → use pipeline.total_tokens directly; do NOT apply heuristic constants.pipeline.total_tokens is absent (legacy run or incomplete pipeline) → apply heuristic constants from Step 6.tokens_used but no top-level pipeline.total_tokens → classify the pipeline as ESTIMATED at the pipeline level, but note which stages had measured data in the detail section.For each pipeline run, collect:
measured_tokens = pipeline.total_tokens if present, else 0measured_stages = count of stages where {stage}.tokens_used exists and is > 0estimated_tokens = heuristic sum for stages missing tokens_usedtotal_stages = count of all stages present in state.jsonMaintain two global accumulators across all issues:
all_measured_issues = list of issue IDs classified as MEASUREDall_estimated_issues = list of issue IDs classified as ESTIMATED (including HYBRID)Output format depends on --format flag (default: md).
When --format json: emit a single JSON object matching the schema below. Do NOT emit any markdown text. Write to --output path if specified, otherwise stdout.
JSON schema:
{
"generated_at": "ISO-8601 timestamp",
"period_days": 30,
"project": "string (tracker project key, e.g. PROJ — NOT full project name)",
"pipeline_overview": {
"issues_attempted": 0,
"issues_fixed": 0,
"issues_blocked": 0,
"success_rate": 0.0,
"avg_time_to_fix_hours": 0.0
},
"token_cost": {
"measured_issues": ["PROJ-42"],
"estimated_issues": ["PROJ-37"],
"measured_tokens": 0,
"estimated_tokens": 0
},
"block_analysis": {
"by_stage": [
{"stage": "triage", "blocks": 0, "pct": 0.0}
],
"top_reasons": [
{"reason": "string (sanitized — block.detail content excluded per state/schema.md hard contract)", "count": 0}
]
},
"per_agent": [
{
"agent": "fixer",
"invocations": 0,
"blocks": 0,
"success_rate": 0.0,
"top_failure": "string"
}
],
"recommendations": ["string"]
}
HARD CONTRACT — block.detail exclusion: top_reasons[].reason uses block.reason only (the sanitized 2-sentence summary from the block comment). block.detail is NEVER serialized into JSON output. This cross-references the comprehensive INCLUDE/EXCLUDE channel table in state/schema.md §"Sensitive field exclusion contract".
When --format md (default): emit markdown report as follows.
## Pipeline Metrics Report — {project} ({period} days)
### Pipeline Overview
| Metric | Value |
|--------|-------|
| Issues attempted | {N} |
| Issues fixed | {N} ({rate}%) |
| Issues blocked | {N} |
| Avg time to fix | {N} hours |
### Token Cost — Per Pipeline Breakdown
For each pipeline run in the period, emit separate line items for measured and estimated
tokens. NEVER emit a single combined grand total when any issues fall back to heuristics.
**Example output for a run with both measured and estimated data:**
Pipeline PROJ-42 (2026-04-18):
Measured: 42,150 tokens (8 stages)
Estimated: 12,500 tokens (2 stages, heuristic)
Total: 54,650 tokens
Pipeline PROJ-37 (2026-04-17): [ESTIMATED — legacy state]
Estimated: 85,000 tokens (heuristic: 2×opus + 1×sonnet + 1×haiku)
Pipeline PROJ-55 (2026-04-19): [MEASURED]
Measured: 78,300 tokens (5 stages)
Total: 78,300 tokens
**Hybrid pipeline (some stages measured, some not):**
Pipeline PROJ-60 (2026-04-20): [ESTIMATED — partial measurement]
Measured stages: triage (12,500 tok), code_analysis (9,800 tok)
Estimated stages: fixer_reviewer, test (heuristic)
Estimated: ~80,000 tokens
Note: pipeline classified as ESTIMATED because pipeline.total_tokens is absent;
2 of 4 stages had measured data.
### Token Cost — Period Summary
| Category | Issues | Tokens |
|----------|--------|--------|
| Measured (state.json) | {X} | {sum} |
| Estimated (heuristic) | {Y} | ~{sum} |
> Measured and estimated totals are NOT summed into a single grand total.
### Block Analysis
| Stage | Blocks | % of total |
|-------|--------|------------|
| triage | ... | ... |
| analysis | ... | ... |
| fix | ... | ... |
| review | ... | ... |
| test | ... | ... |
| publish | ... | ... |
Top block reasons:
1. {reason} ({N} occurrences)
...
### Per-Agent Effectiveness
| Agent | Invocations | Blocks | Success Rate | Top Failure |
|-------|-------------|--------|-------------|-------------|
| fixer | ... | ... | ... | ... |
| ... | ... | ... | ... | ... |
### Recommendations
- {threshold-based recommendations}
---
Data source: measured={X} pipelines (state.json.pipeline.total_tokens present), estimated={Y} pipelines (heuristic fallback).
**Provenance:** {X} pipeline(s) used measured token data from state.json (pipeline.total_tokens).
{Y} pipeline(s) fell back to heuristic estimates (sonnet ~30k, opus ~50k, haiku ~5k per stage).
{If Y > 0}: Pipelines run before per-stage usage tracking was introduced lack per-stage usage fields and are reported as estimated.
Estimated pipelines: {comma-separated list of estimated issue IDs and run dates}.
Generated: {timestamp} | agent-flow v{version}
If --output specified: write to file, otherwise stdout.
When $FORMAT == "html", generate a self-contained HTML file with inline CSS and JavaScript.
HTML escape (XSS defense for user-controlled data paths):
html_escape() {
local s="$1"
s="${s//&/&}"
s="${s//</<}"
s="${s//>/>}"
s="${s//\"/"}"
s="${s//\'/'}"
printf '%s' "$s"
}
Order is critical: & MUST be substituted first to avoid double-escaping subsequent entity references.
All 5 user-controlled / tracker-sourced fields MUST be passed through html_escape BEFORE being interpolated into the HTML output:
$(html_escape "$issue_title")$(html_escape "$state_label")$(html_escape "$block_reason")$(html_escape "$block_recommendation")$(html_escape "$timeline_content")HTML structure (ported from the deleted dashboard skill):
— when pipeline.total_tokens is absent from state.json[agent-flow] comments by timestamp desc)CSS (inline <style> block):
JavaScript (inline <script> block, minimal):
When $FORMAT == "html":
$OUTPUT is empty: HTML_PATH="./metrics.html"$HTML_PATH via Write toolWhen $FORMAT == "md" or $FORMAT == "json" AND $OUTPUT is non-empty:
$OUTPUT instead of stdoutWhen $NO_FORMAT_FLAG == 1:
After the markdown report is displayed on stdout, present the following Czech prompt to the user as a question requiring a response:
Save output? [1] No [2] JSON → stdout [3] HTML → ./metrics.html
Handle the response:
1 → exit (no save)2 → re-render the report at --format json to stdout (re-execute Step 7's JSON branch)3 → re-render the report at --format html to ./metrics.html (execute Step 7a + Step 8)1 (no save)When $NO_FORMAT_FLAG == 0: SKIP this step entirely. The user explicitly chose a format; honor that choice silently.
Autopilot safety: Autopilot does NOT invoke /metrics. The interactive prompt is therefore safe from non-TTY automation contexts.