Loading...
Loading...
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 skill4agent add glebis/claude-skills ecosystemdate +"%Y%m%d"~/.claude/skills/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"~/ai_projects/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}"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"-TECOSYS:com.server.*com.telegram-agent.*com.photopulse.*com.health.*com.temporal.*ai.hermes.*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### Attention
- [list any: broken symlinks, services DOWN, stale CLAUDE.md, Mac Mini unreachable]
- If nothing needs attention: "All clear."TODAY=$(date +"%Y%m%d")## 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_~/Brains/brain/Daily/${TODAY}.md## Ecosystem## Ecosystem##- - -- - -> [!warning] Ecosystem issues detected