跳到主要内容
知仓学习社ZHICANG

ecosystem

Audit the Claude Code ecosystem — skill health and staleness, project activity pulse, CLAUDE.md instruction drift, Mac Mini service status. Use this…

执行命令联网无严重或高危命中glebis/claude-skills

它会碰到什么

扫了多少1 个文本文件,8 KB
它会碰到什么执行命令联网
命中总数2 处
命中统计严重 0 · 高 0 · 中 0 · 低 0

这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。

技能内容

Ecosystem Audit

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.

Workflow

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.

Step 1: Skill Health

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"

Step 2: Project Pulse

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}"

Step 3: CLAUDE.md Drift

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"

Step 4: Mac Mini Health

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

Step 5: Attention Summary + Daily Note

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:

  • If ## Ecosystem section already exists, replace everything from ## Ecosystem to the next ## heading (or - - - separator)
  • If it doesn't exist, insert above the first - - - separator
  • If any red flags (broken symlinks > 0, services down, stale CLAUDE.md > 3), prepend > [!warning] Ecosystem issues detected

想直接用这个技能?

本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。