stats
npx machina-cli add skill agenticnotetaking/arscontexta/stats --openclawRuntime Configuration (Step 0 — before any processing)
Read these files to configure domain-specific behavior:
-
ops/derivation-manifest.md— vocabulary mapping- Use
vocabulary.notesfor the notes folder name - Use
vocabulary.note/vocabulary.note_pluralfor note type references - Use
vocabulary.topic_map/vocabulary.topic_map_pluralfor MOC references - Use
vocabulary.inboxfor the inbox folder name - Use
vocabulary.notes_collectionfor semantic search collection name
- Use
-
ops/config.yaml— processing depth, automation settings
If no derivation file exists, use universal terms (notes, MOCs, etc.).
EXECUTE NOW
Target: $ARGUMENTS
Parse immediately:
- If target contains
--share: output compact shareable format after full stats - If target is empty: output full stats display
- If target names a specific category (e.g., "health", "growth", "pipeline"): show only that category
START NOW. Collect metrics and present them.
Philosophy
Make the invisible visible.
The knowledge graph grows silently. Without metrics, the user cannot tell whether their system is healthy, growing, stagnating, or fragmenting. /stats provides a snapshot that makes growth tangible — numbers that show progress, health indicators that catch problems, and trends that reveal trajectory.
The output should make the user feel informed, not overwhelmed. Metrics are evidence, not judgment. "12 orphans" is a fact. What to DO about it belongs to /graph or /{vocabulary.cmd_reflect}.
Step 1: Collect Metrics
Gather all metrics. Run these checks in parallel where possible to minimize latency.
1a. Knowledge Graph Metrics
NOTES_DIR="{vocabulary.notes}"
# Note count (excluding MOCs)
TOTAL_FILES=$(ls -1 "$NOTES_DIR"/*.md 2>/dev/null | wc -l | tr -d ' ')
MOC_COUNT=$(grep -rl '^type: moc' "$NOTES_DIR"/*.md 2>/dev/null | wc -l | tr -d ' ')
NOTE_COUNT=$((TOTAL_FILES - MOC_COUNT))
# Connection count (all wiki links across notes/)
LINK_COUNT=$(grep -ohP '\[\[[^\]]+\]\]' "$NOTES_DIR"/*.md 2>/dev/null | wc -l | tr -d ' ')
# Average connections per note
if [[ "$NOTE_COUNT" -gt 0 ]]; then
AVG_LINKS=$(echo "scale=1; $LINK_COUNT / $NOTE_COUNT" | bc)
else
AVG_LINKS="0"
fi
# Topic count (unique values in topics: fields)
TOPIC_COUNT=$(grep -ohP '^\s*-\s*"\[\[([^\]]+)\]\]"' "$NOTES_DIR"/*.md 2>/dev/null | sort -u | wc -l | tr -d ' ')
# Link density
if [[ "$NOTE_COUNT" -gt 1 ]]; then
POSSIBLE=$((NOTE_COUNT * (NOTE_COUNT - 1)))
DENSITY=$(echo "scale=4; $LINK_COUNT / $POSSIBLE" | bc)
else
DENSITY="N/A"
fi
1b. Health Metrics
# Orphan count (notes with zero incoming links)
ORPHAN_COUNT=0
for f in "$NOTES_DIR"/*.md; do
NAME=$(basename "$f" .md)
grep -q '^type: moc' "$f" 2>/dev/null && continue
INCOMING=$(grep -rl "\[\[$NAME\]\]" "$NOTES_DIR"/ 2>/dev/null | grep -v "$f" | wc -l | tr -d ' ')
[[ "$INCOMING" -eq 0 ]] && ORPHAN_COUNT=$((ORPHAN_COUNT + 1))
done
# Dangling link count
DANGLING_COUNT=$(grep -ohP '\[\[([^\]]+)\]\]' "$NOTES_DIR"/*.md 2>/dev/null | sort -u | while read -r link; do
NAME=$(echo "$link" | sed 's/\[\[//;s/\]\]//')
[[ ! -f "$NOTES_DIR/$NAME.md" ]] && echo "$NAME"
done | wc -l | tr -d ' ')
# Schema compliance (% of notes with required fields: description, topics)
MISSING_DESC=$(grep -rL '^description:' "$NOTES_DIR"/*.md 2>/dev/null | wc -l | tr -d ' ')
MISSING_TOPICS=$(grep -rL '^topics:' "$NOTES_DIR"/*.md 2>/dev/null | wc -l | tr -d ' ')
SCHEMA_ISSUES=$((MISSING_DESC + MISSING_TOPICS))
if [[ "$TOTAL_FILES" -gt 0 ]]; then
# Notes with BOTH required fields
COMPLIANT=$((TOTAL_FILES - MISSING_DESC))
COMPLIANCE=$(echo "scale=0; $COMPLIANT * 100 / $TOTAL_FILES" | bc)
else
COMPLIANCE="N/A"
fi
# MOC coverage
COVERED=0
for f in "$NOTES_DIR"/*.md; do
NAME=$(basename "$f" .md)
grep -q '^type: moc' "$f" 2>/dev/null && continue
if grep -rl '^type: moc' "$NOTES_DIR"/*.md 2>/dev/null | xargs grep -l "\[\[$NAME\]\]" >/dev/null 2>&1; then
COVERED=$((COVERED + 1))
fi
done
if [[ "$NOTE_COUNT" -gt 0 ]]; then
COVERAGE=$(echo "scale=0; $COVERED * 100 / $NOTE_COUNT" | bc)
else
COVERAGE="N/A"
fi
1c. Pipeline Metrics
# Inbox items
INBOX_COUNT=$(find {vocabulary.inbox}/ -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
# Queue pending (check both YAML and JSON formats)
QUEUE_FILE=""
if [[ -f "ops/queue/queue.yaml" ]]; then
QUEUE_FILE="ops/queue/queue.yaml"
QUEUE_PENDING=$(grep -c 'status: pending' "$QUEUE_FILE" 2>/dev/null || echo 0)
QUEUE_DONE=$(grep -c 'status: done' "$QUEUE_FILE" 2>/dev/null || echo 0)
elif [[ -f "ops/queue/queue.json" ]]; then
QUEUE_FILE="ops/queue/queue.json"
QUEUE_PENDING=$(grep -c '"status": "pending"' "$QUEUE_FILE" 2>/dev/null || echo 0)
QUEUE_DONE=$(grep -c '"status": "done"' "$QUEUE_FILE" 2>/dev/null || echo 0)
else
QUEUE_PENDING=0
QUEUE_DONE=0
fi
# Processed ratio (notes vs inbox)
TOTAL_CONTENT=$((NOTE_COUNT + INBOX_COUNT))
if [[ "$TOTAL_CONTENT" -gt 0 ]]; then
PROCESSED_PCT=$(echo "scale=0; $NOTE_COUNT * 100 / $TOTAL_CONTENT" | bc)
else
PROCESSED_PCT="N/A"
fi
1d. Growth Metrics
# This week's growth (notes with created: date within last 7 days)
WEEK_AGO=$(date -v-7d +%Y-%m-%d 2>/dev/null || date -d '7 days ago' +%Y-%m-%d 2>/dev/null)
if [[ -n "$WEEK_AGO" ]]; then
THIS_WEEK_NOTES=$(grep -rl "^created: " "$NOTES_DIR"/*.md 2>/dev/null | while read -r f; do
CREATED=$(grep '^created:' "$f" | head -1 | awk '{print $2}')
[[ "$CREATED" > "$WEEK_AGO" || "$CREATED" == "$WEEK_AGO" ]] && echo "$f"
done | wc -l | tr -d ' ')
else
THIS_WEEK_NOTES="?"
fi
# This week's connections (approximate — count links in recently created notes)
if [[ "$THIS_WEEK_NOTES" -gt 0 && -n "$WEEK_AGO" ]]; then
THIS_WEEK_LINKS=$(grep -rl "^created: " "$NOTES_DIR"/*.md 2>/dev/null | while read -r f; do
CREATED=$(grep '^created:' "$f" | head -1 | awk '{print $2}')
[[ "$CREATED" > "$WEEK_AGO" || "$CREATED" == "$WEEK_AGO" ]] && grep -oP '\[\[[^\]]+\]\]' "$f" 2>/dev/null
done | wc -l | tr -d ' ')
else
THIS_WEEK_LINKS="?"
fi
1e. System Metrics
# Self space
if [[ -d "self/" ]]; then
SELF_FILES=$(find self/ -name "*.md" 2>/dev/null | wc -l | tr -d ' ')
SELF_STATUS="enabled ($SELF_FILES files)"
else
SELF_STATUS="disabled"
fi
# Methodology notes
METHODOLOGY_COUNT=$(ls -1 ops/methodology/*.md 2>/dev/null | wc -l | tr -d ' ')
# Observations pending
OBS_PENDING=$(grep -rl '^status: pending' ops/observations/ 2>/dev/null | wc -l | tr -d ' ')
# Tensions pending
TENSION_PENDING=$(grep -rl '^status: open\|^status: pending' ops/tensions/ 2>/dev/null | wc -l | tr -d ' ')
# Sessions captured
SESSION_COUNT=$(ls -1 ops/sessions/*.md 2>/dev/null | wc -l | tr -d ' ')
Adapt all directory names to domain vocabulary. Skip checks for directories that do not exist — report "N/A" instead of errors.
Step 2: Format Output
Full Output (default)
Generate a progress bar for the Processed metric:
Progress bar calculation:
filled = PROCESSED_PCT / 5 (number of = characters out of 20)
empty = 20 - filled
bar = [===... ] PCT%
--=={ stats }==--
Knowledge Graph
===============
{vocabulary.note_plural}: [NOTE_COUNT]
Connections: [LINK_COUNT] (avg [AVG_LINKS] per {vocabulary.note})
{vocabulary.topic_map_plural}: [MOC_COUNT] (covering [COVERAGE]% of {vocabulary.note_plural})
Topics: [TOPIC_COUNT]
Health
======
Orphans: [ORPHAN_COUNT]
Dangling: [DANGLING_COUNT]
Schema: [COMPLIANCE]% compliant
Pipeline
========
Processed: [============== ] [PROCESSED_PCT]%
Inbox: [INBOX_COUNT] items
Queue: [QUEUE_PENDING] pending tasks
Growth
======
This week: +[THIS_WEEK_NOTES] {vocabulary.note_plural}, +[THIS_WEEK_LINKS] connections
Graph density: [DENSITY]
System
======
Self space: [SELF_STATUS]
Methodology: [METHODOLOGY_COUNT] learned patterns
Observations: [OBS_PENDING] pending
Tensions: [TENSION_PENDING] open
Sessions: [SESSION_COUNT] captured
Generated by Ars Contexta v1.6
Interpretation Notes
After the stats block, add brief interpretation for any notable findings:
| Condition | Note |
|---|---|
| ORPHAN_COUNT > 0 | "[N] orphan {vocabulary.note_plural} — run /graph health for details" |
| DANGLING_COUNT > 0 | "[N] dangling links — run /graph health to identify broken links" |
| COMPLIANCE < 90 | "Schema compliance below 90% — some {vocabulary.note_plural} missing required fields" |
| OBS_PENDING >= 10 | "[N] pending observations — consider running /{vocabulary.rethink}" |
| TENSION_PENDING >= 5 | "[N] open tensions — consider running /{vocabulary.rethink}" |
| DENSITY < 0.02 | "Graph density is low — connections are thin. Run /{vocabulary.cmd_reflect} to strengthen the network" |
| PROCESSED_PCT < 50 | "More content in inbox than in {vocabulary.notes}/ — consider processing backlog" |
| THIS_WEEK_NOTES == 0 | "No new {vocabulary.note_plural} this week" |
Only show interpretation notes when conditions are notable. A healthy vault gets just the stats, no warnings.
Step 3: Shareable Format (--share flag)
If invoked with --share, output a compact markdown block suitable for sharing on social media or in documentation:
## My Knowledge Graph
- **[NOTE_COUNT]** {vocabulary.note_plural} with **[LINK_COUNT]** connections (avg [AVG_LINKS] per {vocabulary.note})
- **[MOC_COUNT]** {vocabulary.topic_map_plural} covering [COVERAGE]% of {vocabulary.note_plural}
- Schema compliance: [COMPLIANCE]%
- This week: +[THIS_WEEK_NOTES] {vocabulary.note_plural}, +[THIS_WEEK_LINKS] connections
- Graph density: [DENSITY]
*Built with [Ars Contexta](https://github.com/arscontexta) v1.6*
The shareable format:
- Omits health warnings (positive framing for sharing)
- Omits pipeline state (internal detail)
- Omits system metrics (internal detail)
- Includes only growth-positive metrics
- Always includes the Ars Contexta attribution line
Step 4: Trend Analysis (when history exists)
If previous /stats runs are logged in ops/stats-history.yaml (or similar), compare current metrics against the last snapshot:
Trend (vs last check):
{vocabulary.note_plural}: [N] (+[delta] since [date])
Connections: [N] (+[delta])
Density: [N] ([up/down/stable])
Orphans: [N] ([improved/worsened/stable])
If no history exists, skip trend analysis. Do NOT create the history file — that is /health's responsibility.
Edge Cases
Empty Vault (0 notes)
Show zeros gracefully:
--=={ stats }==--
Your knowledge graph is new. Start capturing to see it grow.
Knowledge Graph
===============
{vocabulary.note_plural}: 0
Connections: 0
{vocabulary.topic_map_plural}: 0
Topics: 0
Generated by Ars Contexta v1.6
Do not show health, pipeline, growth, or system sections for an empty vault — they would all be zeros or N/A.
No Queue System
Skip the Pipeline section entirely. Do not show an error.
No Self Space
Show "disabled" for self space line. Do not show an error.
No ops/derivation-manifest.md
Use universal vocabulary (notes, MOCs, etc.). All metrics work identically.
Very Large Vault (500+ notes)
The orphan and MOC coverage checks may be slow for large vaults. If {vocabulary.notes}/ has >200 files:
- Run orphan detection with a simpler heuristic (check only for presence in any MOC, not full backlink scan)
- Note: "Metrics approximate for large vault. Run /graph health for precise analysis."
Platform-Specific Date Commands
macOS uses date -v-7d, Linux uses date -d '7 days ago'. The script tries both. If neither works, report "?" for growth metrics instead of failing.
Source
git clone https://github.com/agenticnotetaking/arscontexta/blob/main/skill-sources/stats/SKILL.mdView on GitHub Overview
stats gathers vault health, growth, and knowledge graph metrics into a single snapshot. It surfaces key counts like notes, MOCs, and links, plus health signals such as orphans and dangling links, so you can monitor progress and identify issues quickly. Use it to share a concise, evidence-based view of vault status with teammates.
How This Skill Works
The skill runs runtime checks to collect knowledge graph metrics (note count, MOC count, total links, average links per note, topic count, and link density) and health metrics (orphan notes, dangling links, and basic schema issues). It reads markdown notes in the notes directory, computes values, and outputs either a full display or a compact shareable summary when invoked with --share.
When to Use It
- You want a quick pulse of vault health, growth, and knowledge graph health.
- You need to share a concise, exportable snapshot with teammates using the --share flag.
- You want to view only health-related metrics to diagnose linkage issues.
- You want to focus on growth-related metrics to assess vault expansion.
- You want to inspect knowledge graph metrics such as note/link counts and topic coverage.
Quick Start
- Step 1: Run /stats or /stats --share to generate a snapshot.
- Step 2: If you want a category view, pass health, growth, or knowledge as the target.
- Step 3: Review the numbers and act on any issues (orphans, dangling links, missing metadata).
Best Practices
- Run the checks in parallel where possible to minimize latency.
- Use the --share flag when you need a compact snapshot for colleagues.
- Regularly review orphan and dangling counts to catch fragmentation early.
- Monitor schema issues (missing description or topics) to maintain data quality.
- Keep the NOTES_DIR and vocab mappings up to date so metrics reflect the current vault structure.
Example Use Cases
- Full stats output shows Notes: 120, MOCs: 8, Links: 420, Avg links per note: 3.5, Topics: 12, Density: 0.002. Orphans: 5, Dangling: 2, Schema issues: Descriptions missing: 1, Topics missing: 0.
- Health-focused view highlights Orphans: 1 and Dangling: 2, helping you pinpoint missing inbound links and broken references.
- Growth-focused view reports total Notes and Links rising month over month, indicating expanding coverage and interconnections.
- Knowledge graph view emphasizes Topic count and average links per note, guiding where to add new topics or strengthen cross-links.
- Compact shareable output (via --share) yields a brief line like: Notes 120 | Links 420 | Orphans 5 | Dangling 2 | Topics 12.