Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add commands/martybonacci/specswarm/metricsgit clone --depth 1 https://github.com/MartyBonacci/specswarmWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/commands/martybonacci/specswarm/metrics)<a href="https://agentmods.dev/commands/martybonacci/specswarm/metrics"><img src="https://agentmods.dev/badge/commands/martybonacci/specswarm/metrics.svg" alt="Measured on agentmods" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5 | $0.00019 | $0.03135 |
| Opus 5 | $0.00010 | $0.01568 |
| Sonnet 5 | $0.00004 | $0.00627 |
| Haiku 4.5 | $0.00002 | $0.00314 |
Grade A, and why
feature-metrics scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 5d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 421 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Feature-Level Metrics Dashboard
#!/bin/bash
# Parse arguments
PROJECT_PATH=""
RECENT_COUNT=10
EXPORT_FILE=""
FEATURE_NUMBER=""
SPRINT_FILTER=""
SHOW_DETAILS=false
while [[ $# -gt 0 ]]; do
case $1 in
--recent)
RECENT_COUNT="$2"
shift 2
;;
--export)
EXPORT_FILE="${2:-feature-metrics-$(date +%Y%m%d_%H%M%S).csv}"
shift 2
;;
--feature)
FEATURE_NUMBER="$2"
shift 2
;;
--sprint)
SPRINT_FILTER="$2"
shift 2
;;
--details)
SHOW_DETAILS=true
shift
;;
--path)
PROJECT_PATH="$2"
shift 2
;;
*)
if [ -z "$PROJECT_PATH" ] && [ -d "$1" ]; then
PROJECT_PATH="$1"
fi
shift
;;
esac
done
# Default to current directory if no path specified
PROJECT_PATH="${PROJECT_PATH:-$(pwd)}"
# Source the feature metrics collector library
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
PLUGIN_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
if [ -f "$PLUGIN_ROOT/lib/feature-metrics-collector.sh" ]; then
source "$PLUGIN_ROOT/lib/feature-metrics-collector.sh"
else
echo "⚠️ Feature metrics collector not available — using basic metrics"
fi
# Set project root for library
export PROJECT_ROOT="$PROJECT_PATH"
echo "📊 SpecSwarm Feature-Level Metrics Dashboard"
echo "============================================"
echo ""
echo "Project: $PROJECT_PATH"
echo ""
# Collect all feature data
echo "🔍 Scanning for features..."
features_json=$(fm_analyze_all_features "$PROJECT_PATH")
# Check if any features found
total_features=$(echo "$features_json" | jq 'length')
if [ "$total_features" -eq 0 ]; then
echo ""
echo "ℹ️ No features found in $PROJECT_PATH"
echo ""
echo "Features are detected by the presence of spec.md files."
echo "Make sure you're in a project directory with SpecSwarm features."
echo ""
echo "Searched for:"
echo " - */spec.md"
echo " - features/*/spec.md"
echo " - .features/*/spec.md"
echo ""
exit 0
fi
echo "✅ Found $total_features features"
echo ""
# Calculate aggregates
aggregates=$(fm_calculate_aggregates "$features_json")
# Display based on requested view
if [ -n "$FEATURE_NUMBER" ]; then
#==========================================================================
# SINGLE FEATURE DETAILS
#==========================================================================
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Feature $FEATURE_NUMBER Details"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Find the feature
feature=$(echo "$features_json" | jq --arg num "$FEATURE_NUMBER" \
'.[] | select(.metadata.feature_number == $num)')
if [ -z "$feature" ] || [ "$feature" = "null" ]; then
echo "❌ Feature $FEATURE_NUMBER not found"
exit 1
fi
# Display metadata
echo "📋 Metadata"
echo "───────────"
echo "$feature" | jq -r '" Name: \(.metadata.feature_name)
Status: \(.metadata.status)
Parent Branch: \(.metadata.parent_branch)
Created: \(.metadata.created_at)
Completed: \(.metadata.completed_at // "N/A")
Directory: \(.metadata.feature_dir)"'
echo ""
# Display task stats
echo "✅ Tasks"
echo "────────"
echo "$feature" | jq -r '" Total: \(.tasks.total)
Completed: \(.tasks.completed) (\(.tasks.completion_rate)%)
Failed: \(.tasks.failed)
Pending: \(.tasks.pending)"'
echo ""
# Display test stats
if [ "$(echo "$feature" | jq '.tests.total_tests')" -gt 0 ]; then
echo "🧪 Tests"
echo "────────"
echo "$feature" | jq -r '" Total: \(.tests.total_tests)
Passing: \(.tests.passing_tests) (\(.tests.pass_rate)%)
Failing: \(.tests.failing_tests)"'
echo ""
fi
# Display git stats
echo "🔀 Git History"
echo "──────────────"
echo "$feature" | jq -r '" Branch: \(.git.branch)
Commits: \(.git.commits)
Merged: \(.git.merged)
Merge Date: \(.git.merge_date // "N/A")"'
echo ""
# v7.16.0 (AUTO-MAGIC WS8): open DECIDED-BY-DATA deferrals for this feature.
# A fork deferred to a metric is a decision with a due date — surface it so
# the review-when condition doesn't rot forgotten in the spec.
DBD_LIB="${PLUGIN_DIR}/lib/decisions/decided-by-data.sh"
if [ -f "$DBD_LIB" ]; then
# shellcheck disable=SC1091
source "$DBD_LIB"
DBD_MARKERS=$(ss_dbd_scan_feature "$FEATURE_DIR" 2>/dev/null || true)
if [ -n "$DBD_MARKERS" ]; then
echo "📊 Decided-by-Data (open deferrals)"
echo "───────────────────────────────────"
while IFS=$'\t' read -r mfile mline metric review; do
printf " • %s — review when: %s (%s:%s)\n" "$metric" "$review" "$(basename "$mfile")" "$mline"
done <<< "$DBD_MARKERS"
echo " Resolve each: gather the metric, make the ruling, replace the marker with the decision (+ distill via ss_taste_add)."
echo ""
fi
fi
elif [ -n "$SPRINT_FILTER" ]; then
#==========================================================================
# SPRINT AGGREGATE VIEW
#==========================================================================
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Sprint: $SPRINT_FILTER"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Filter features for this sprint
sprint_features=$(fm_filter_features "$features_json" "metadata.parent_branch" "$SPRINT_FILTER")
sprint_count=$(echo "$sprint_features" | jq 'length')
if [ "$sprint_count" -eq 0 ]; then
echo "ℹ️ No features found for sprint: $SPRINT_FILTER"
exit 0
fi
# Calculate sprint aggregates
sprint_aggregates=$(fm_calculate_aggregates "$sprint_features")
echo "📊 Sprint Statistics"
echo "────────────────────"
echo "$sprint_aggregates" | jq -r '" Total Features: \(.features.total)
Completed: \(.features.completed)
In Progress: \(.features.in_progress)
Total Tasks: \(.tasks.total)
Completed: \(.tasks.completed)
Failed: \(.tasks.failed)
Avg Completion Rate: \(.tasks.avg_completion_rate)%
Total Tests: \(.tests.total)
Passing: \(.tests.passing) (\(.tests.avg_pass_rate)%)
Failing: \(.tests.failing)"'
echo ""
echo "📝 Features in $SPRINT_FILTER"
echo "─────────────────────────────"
echo "$sprint_features" | jq -r '.[] | " [\(.metadata.feature_number)] \(.metadata.feature_name)
Status: \(.metadata.status) | Tasks: \(.tasks.completed)/\(.tasks.total) | Tests: \(.tests.passing_tests)/\(.tests.total_tests)\n"'
echo ""
else
#==========================================================================
# DASHBOARD SUMMARY VIEW
#==========================================================================
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Overall Statistics"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "📊 Features"
echo "───────────"
echo "$aggregates" | jq -r '" Total: \(.features.total)
Completed: \(.features.completed)
In Progress: \(.features.in_progress)"'
echo ""
echo "✅ Tasks"
echo "────────"
echo "$aggregates" | jq -r '" Total: \(.tasks.total)
Completed: \(.tasks.completed)
Failed: \(.tasks.failed)
Avg Completion Rate: \(.tasks.avg_completion_rate)%"'
echo ""
echo "🧪 Tests"
echo "────────"
if [ "$(echo "$aggregates" | jq '.tests.total')" -gt 0 ]; then
echo "$aggregates" | jq -r '" Total: \(.tests.total)
Passing: \(.tests.passing) (\(.tests.avg_pass_rate)%)
Failing: \(.tests.failing)"'
else
echo " No test data found"
fi
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Recent Features (Last $RECENT_COUNT)"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Get recent features
recent_features=$(fm_get_recent "$features_json" "$RECENT_COUNT")
# Display recent features table
echo "$recent_features" | jq -r '.[] |
"[\(.metadata.feature_number)] \(.metadata.feature_name)
Status: \(.metadata.status) | Parent: \(.metadata.parent_branch)
Tasks: \(.tasks.completed)/\(.tasks.total) (\(.tasks.completion_rate)%) | Tests: \(.tests.passing_tests)/\(.tests.total_tests) (\(.tests.pass_rate)%)
Created: \(.metadata.created_at)
"'
# Sprint breakdown
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Features by Sprint/Parent Branch"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
# Group by parent branch
echo "$features_json" | jq -r 'group_by(.metadata.parent_branch) |
.[] |
"[\(.[0].metadata.parent_branch)]
Features: \(length)
Tasks Completed: \([.[].tasks.completed] | add)/\([.[].tasks.total] | add)
"'
fi
# Export to CSV if requested
if [ -n "$EXPORT_FILE" ]; then
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Exporting to CSV"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
exported_file=$(fm_export_csv "$features_json" "$EXPORT_FILE")
echo "✅ Metrics exported to: $exported_file"
echo ""
echo "Total rows: $((total_features + 1))" # +1 for header
echo ""
fi
# Help message for next steps
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "Available Commands"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo " /ss:metrics Dashboard summary"
echo " /ss:metrics --recent 20 Show last 20 features"
echo " /ss:metrics --feature 015 Feature 015 details"
echo " /ss:metrics --sprint sprint-4 Sprint aggregates"
echo " /ss:metrics --export Export to CSV"
echo " /ss:metrics --path /project Analyze specific project"
echo ""
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 5d ago First seen · 421 lines · 19 tokens per session scan A 30f4e48d22ea
feature-metrics is a command published in the GitHub repository MartyBonacci/specswarm (65 stars, last pushed 1mo ago), licensed MIT. It adds 19 tokens to every session and 3,135 once invoked, about $0.0001 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other commands, from other repositories
template
Manage issue templates for streamlined issue creation.
sync-linear
Sync current work with Linear ticket status.
add-note
Add an internal or external note to a ConnectWise PSA ticket.
fest-show
Show festival progression (in-progress tasks, roadmap, and dependency view).
dispatcher
Pick the next-best repo to work on across the portfolio — rank free repos, recommend one, claim its lease atomically, and route to the entry command.
clarify
Walk through inbox items applying the GTD decision tree. Usage: /gtd:clarify [--id gtd-xxx].