ecosystem/SKILL.md
Audit the Claude Code ecosystem — skill health and staleness, project activity pulse, CLAUDE.md instruction drift, Mac Mini service status. Use this skill whenever the user asks about ecosystem health, stale skills, abandoned projects, system status, infrastructure check, "what's broken", "what's stale", "how's my setup", or any request to review the state of their Claude Code environment. Also triggers on "/ecosystem", "audit my ecosystem", "ecosystem health", "ecosystem audit".
npx skillsauth add glebis/claude-skills ecosystemInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
On-demand audit of the Claude Code ecosystem. Runs 4 checks, prints a full report with an attention summary, and appends a summary to today's daily note.
Run all 4 checks sequentially using the bash blocks below. Each block runs in a fresh shell, so after all checks complete, compose the daily note summary and attention rollup from the terminal output you've collected.
CRITICAL: Run date +"%Y%m%d" before writing to the daily note.
Scan ~/.claude/skills/ for skill freshness and broken symlinks.
NOW=$(date +%s)
D30=$((NOW - 30*86400))
D90=$((NOW - 90*86400))
ACTIVE="" BROKEN=""
ACTIVE_N=0 RECENT_N=0 STALE_N=0 BROKEN_N=0 TOTAL=0
for entry in ~/.claude/skills/*/; do
[ -d "$entry" ] || continue
name=$(basename "$entry")
TOTAL=$((TOTAL + 1))
if [ -L "${entry%/}" ] && [ ! -e "${entry%/}" ]; then
target=$(readlink "${entry%/}")
BROKEN="${BROKEN} - ${name} -> ${target}\n"
BROKEN_N=$((BROKEN_N + 1))
continue
fi
real_path="$entry"
if [ -L "${entry%/}" ]; then
real_path="$(readlink "${entry%/}")/"
fi
newest=$(find "$real_path" -type f -exec stat -f %m {} + 2>/dev/null | sort -rn | head -1)
[ -z "$newest" ] && newest=0
if [ "$newest" -ge "$D30" ]; then
ACTIVE="${ACTIVE}, ${name}"
ACTIVE_N=$((ACTIVE_N + 1))
elif [ "$newest" -ge "$D90" ]; then
RECENT_N=$((RECENT_N + 1))
else
STALE_N=$((STALE_N + 1))
fi
done
echo "### Skills (${TOTAL} total)"
echo "- Active (30d): ${ACTIVE_N}${ACTIVE:+ — ${ACTIVE:2}}"
echo "- Recent (30-90d): ${RECENT_N}"
echo "- Stale (>90d): ${STALE_N}"
echo "- Broken symlinks: ${BROKEN_N}"
[ -n "$BROKEN" ] && printf "$BROKEN"
Scan ~/ai_projects/ for git repo activity and CLAUDE.md presence. Cap dormant and abandoned lists at 10 names to keep output readable.
NOW=$(date +%s)
D30=$((NOW - 30*86400))
D180=$((NOW - 180*86400))
ACTIVE="" DORMANT="" ABANDONED="" DORMANT_N=0 ABANDONED_N=0 NO_CLAUDE=0
ACTIVE_N=0 GIT_TOTAL=0 DIR_TOTAL=0 NODATA=0
for dir in ~/ai_projects/*/; do
[ -d "$dir" ] || continue
DIR_TOTAL=$((DIR_TOTAL + 1))
[ -d "${dir}.git" ] || continue
GIT_TOTAL=$((GIT_TOTAL + 1))
last_commit=$(git -C "$dir" log -1 --format=%ct 2>/dev/null)
if [ -z "$last_commit" ]; then
NODATA=$((NODATA + 1))
continue
fi
name=$(basename "$dir")
if [ "$last_commit" -ge "$D30" ]; then
ACTIVE="${ACTIVE}, ${name}"
ACTIVE_N=$((ACTIVE_N + 1))
elif [ "$last_commit" -ge "$D180" ]; then
DORMANT_N=$((DORMANT_N + 1))
[ "$DORMANT_N" -le 10 ] && DORMANT="${DORMANT}, ${name}"
else
ABANDONED_N=$((ABANDONED_N + 1))
[ "$ABANDONED_N" -le 10 ] && ABANDONED="${ABANDONED}, ${name}"
fi
[ ! -f "${dir}CLAUDE.md" ] && NO_CLAUDE=$((NO_CLAUDE + 1))
done
DORMANT_SUFFIX=""
[ "$DORMANT_N" -gt 10 ] && DORMANT_SUFFIX=" and $((DORMANT_N - 10)) more"
ABANDONED_SUFFIX=""
[ "$ABANDONED_N" -gt 10 ] && ABANDONED_SUFFIX=" and $((ABANDONED_N - 10)) more"
echo ""
echo "### Projects (${DIR_TOTAL} dirs, ${GIT_TOTAL} git repos)"
echo "- Active (30d): ${ACTIVE_N}${ACTIVE:+ — ${ACTIVE:2}}"
echo "- Dormant (30-180d): ${DORMANT_N}${DORMANT:+ — ${DORMANT:2}${DORMANT_SUFFIX}}"
echo "- Abandoned (>6mo): ${ABANDONED_N}${ABANDONED:+ — ${ABANDONED:2}${ABANDONED_SUFFIX}}"
[ "$NODATA" -gt 0 ] && echo "- No data (empty/corrupt): ${NODATA}"
echo "- Missing CLAUDE.md: ${NO_CLAUDE}"
Check if CLAUDE.md files are stale relative to their project's latest commit. Uses git commit dates (not filesystem mtime) for accuracy.
NOW=$(date +%s)
STALE_LIST="" STALE_N=0
UNTRACKED_LIST="" UNTRACKED_N=0
while IFS= read -r claude_file; do
project_dir=$(dirname "$claude_file")
while [ ! -d "${project_dir}/.git" ] && [ "$project_dir" != "$HOME/ai_projects" ]; do
project_dir=$(dirname "$project_dir")
done
[ -d "${project_dir}/.git" ] || continue
claude_commit=$(git -C "$project_dir" log -1 --format=%ct -- "$claude_file" 2>/dev/null)
project_commit=$(git -C "$project_dir" log -1 --format=%ct 2>/dev/null)
[ -z "$project_commit" ] && continue
if [ -z "$claude_commit" ]; then
rel_path="${claude_file#$HOME/}"
UNTRACKED_LIST="${UNTRACKED_LIST} - ~/${rel_path}\n"
UNTRACKED_N=$((UNTRACKED_N + 1))
continue
fi
diff=$((project_commit - claude_commit))
if [ "$diff" -gt $((90*86400)) ]; then
rel_path="${claude_file#$HOME/}"
claude_date=$(date -r "$claude_commit" +%Y-%m-%d)
project_date=$(date -r "$project_commit" +%Y-%m-%d)
STALE_LIST="${STALE_LIST} - ~/${rel_path} (last: ${claude_date}, project: ${project_date})\n"
STALE_N=$((STALE_N + 1))
fi
done < <(find ~/ai_projects -maxdepth 2 -name CLAUDE.md 2>/dev/null)
echo ""
echo "### CLAUDE.md Drift"
echo "- Stale instructions (>90d behind project): ${STALE_N}"
[ -n "$STALE_LIST" ] && printf "$STALE_LIST"
echo "- Untracked: ${UNTRACKED_N}"
[ -n "$UNTRACKED_LIST" ] && printf "$UNTRACKED_LIST"
SSH to agents-mac-mini and check services. Uses -T to avoid pseudo-tty and ECOSYS: prefix to filter iTerm escape codes from the output.
Custom services on the Mac Mini use various prefixes (com.server.*, com.telegram-agent.*, com.photopulse.*, com.health.*, com.temporal.*, ai.hermes.*, etc.), so count all non-Apple LaunchAgents.
echo ""
echo "### Mac Mini"
MINI_OUTPUT=$(ssh -T -o ConnectTimeout=5 -o BatchMode=yes mac-mini 'export TERM=dumb; thumb=$(curl -s --max-time 3 -o /dev/null -w "%{http_code}" http://localhost:8080/ 2>/dev/null); viz=$(curl -s --max-time 3 -o /dev/null -w "%{http_code}" http://localhost:8081/ 2>/dev/null); agents=$(launchctl list 2>/dev/null | tail -n +2 | awk "{print \$3}" | grep -cv "^com\.apple" || echo 0); hdb_size=$(stat -f %z ~/ai_projects/health-import/health.db 2>/dev/null || echo 0); echo "ECOSYS:${thumb}|${viz}|${agents}|${hdb_size}"' 2>/dev/null)
DATA=$(echo "$MINI_OUTPUT" | grep "^ECOSYS:" | sed 's/^ECOSYS://')
if [ -z "$DATA" ]; then
echo "- Status: UNREACHABLE (SSH failed)"
else
IFS='|' read -r THUMB VIZ AGENTS HDB_SIZE <<< "$DATA"
[ "$THUMB" = "200" ] && echo "- Thumb server (:8080): UP" || echo "- Thumb server (:8080): DOWN (${THUMB})"
[ "$VIZ" = "200" ] && echo "- Viz server (:8081): UP" || echo "- Viz server (:8081): DOWN (${VIZ})"
echo "- Custom LaunchAgents: ${AGENTS}"
if [ "$HDB_SIZE" -gt 0 ] 2>/dev/null; then
HDB_GB=$(echo "scale=1; ${HDB_SIZE}/1073741824" | bc)
echo "- Health DB: ${HDB_GB} GB"
else
echo "- Health DB: NOT FOUND"
fi
fi
After printing the full terminal report, add an attention summary highlighting anything that needs action:
### Attention
- [list any: broken symlinks, services DOWN, stale CLAUDE.md, Mac Mini unreachable]
- If nothing needs attention: "All clear."
Then compose a summary and write it to today's daily note.
Get today's date first:
TODAY=$(date +"%Y%m%d")
Build the summary block from the results you collected in Steps 1-4 (re-read the terminal output above — variables don't carry across bash blocks). Format:
## Ecosystem
Skills: N active / N recent / N stale / N broken
Projects: N active / N dormant / N abandoned
CLAUDE.md drift: N stale, N untracked
Mac Mini: [status summary]
_Ecosystem audit · YYYY-MM-DD_
Write to ~/Brains/brain/Daily/${TODAY}.md:
## Ecosystem section already exists, replace everything from ## Ecosystem to the next ## heading (or - - - separator)- - - separator> [!warning] Ecosystem issues detecteddevelopment
This skill should be used when designing, running, validating, or auditing statistical experiments on personal or observational time-series data (health metrics, speech/text corpora, behavioral logs, diaries, n-of-1 self-tracking). It enforces pre-registration, exact permutation tests, FDR discipline, data-validation gates, adversarial code review, and cross-validation with external models. Triggers on "design an experiment", "test this hypothesis on my data", "is this correlation real", "audit these findings", "pre-register", "validate this dataset", or any n-of-1 / quantified-self analysis request.
development
Create Tufte-inspired data reports and infographic dashboards as standalone HTML files. Uses EB Garamond for text, Monaspace Argon for numbers, Chart.js for interactive charts, and inline SVG sparklines. Produces publication-quality reports with 2-column narrative+data layouts, status dashboards, scroll animations, and responsive mobile support. Use this skill whenever the user wants to create a data report, activity dashboard, infographic, personal analytics page, health tracker visualization, or any document that combines narrative text with interactive charts and tables. Also triggers for "make a report like Tufte", "create an infographic", "build a dashboard", "visualize my data", or requests for beautiful data-driven documents.
documentation
Cut a software release and maintain a tiered compatibility policy. Use when the user wants to release, ship a version, bump the version, tag a release, write a changelog, or update COMPATIBILITY. Config-driven via release.config.json; bumps version files, runs a readiness gate, updates COMPATIBILITY.md tiers and deprecations, tags (→ release workflow), and reports closed issues. Teaches the underlying standards as it runs.
development
Sync and manage bilingual (EN/RU) library content for agency-docs. Use when adding, updating, or reviewing library articles. Handles translation, sync checks, and Russian stylistic review.