Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Repository Health Score

v1.0.0

Score a repository's health across 8 dimensions — code quality, testing, documentation, CI/CD, security, dependencies, community, and maintainability. Produc...

0· 30·0 current·0 all-time

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for charlie-morrison/repository-health-score.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "Repository Health Score" (charlie-morrison/repository-health-score) from ClawHub.
Skill page: https://clawhub.ai/charlie-morrison/repository-health-score
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install repository-health-score

ClawHub CLI

Package manager switcher

npx clawhub@latest install repository-health-score
Security Scan
Capability signals
Requires walletRequires sensitive credentials
These labels describe what authority the skill may exercise. They are separate from suspicious or malicious moderation verdicts.
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Suspicious
medium confidence
!
Purpose & Capability
The skill's stated purpose (scoring a repository across multiple dimensions) matches the actions in SKILL.md (inspecting README, tests, CI config, lockfiles, searching for secrets). However the SKILL.md invokes several command-line tools (examples seen: rg (ripgrep), python3, bc, find, wc, grep, awk, ls, head) but the registry metadata declares no required binaries. This mismatch is disproportionate and likely to cause runtime failures or hidden dependencies.
Instruction Scope
Instructions are limited to scanning repository files and producing scores, which aligns with the stated purpose. The script intentionally searches for potential secrets (regex hits) and inspects many files; this is expected for a health scan but means the tool will read any file in the repo. There are no explicit outbound network calls in the visible SKILL.md, but the skill prints potentially sensitive content (secret hits) to stdout — consider that outputs could be captured or sent by the caller.
!
Install Mechanism
This is an instruction-only skill with no install spec (low write-to-disk risk). However, the lack of an install spec combined with undeclared runtime dependencies is risky: users will need to ensure appropriate tools are present (ripgrep, python3, bc, etc.). The skill does not provide guidance to install or vendor these tools.
Credentials
The skill does not request environment variables, credentials, or config paths. Its scanning of the repository content is proportional to the purpose. Note: because it searches for secret-like patterns, it may identify sensitive strings present in the repo — the behavior is expected but worth being explicit about.
Persistence & Privilege
The skill is not always-enabled and does not request persistent system presence or modify other skills; autonomous invocation is allowed by platform default but not combined with other elevated privileges here.
What to consider before installing
This skill runs many shell searches and small utilities against a repository to compute scores — that's consistent with its purpose. However, the SKILL.md calls tools such as ripgrep (rg), python3, bc, find, awk, grep, wc, head, etc., while the skill metadata lists no required binaries or install steps. Before installing or invoking it: (1) review the full SKILL.md yourself; (2) run it in a safe/isolated environment (container or VM) first; (3) ensure required tools are installed (or ask the author to declare them); (4) be mindful the tool will read and print repository contents (including potential secret-like strings), so avoid running it in repos containing sensitive data unless you trust the environment and capture/retention policies.

Like a lobster shell, security has layers — review code before you run it.

latestvk97fmh515n5sgzf5xkk7hvtm5d85n6x0
30downloads
0stars
1versions
Updated 5h ago
v1.0.0
MIT-0

Repository Health Score

Rate any repository on a 0-100 scale across 8 dimensions. Like a credit score for code — quick assessment of project maturity, maintenance quality, and risk level.

Use when: "how healthy is this repo", "rate this codebase", "project quality audit", "is this repo well-maintained", "should we adopt this library", "repository assessment", or during due diligence on open-source dependencies.

Commands

1. score — Full Health Assessment

Run all dimension checks and produce a composite score.

Dimension 1: Documentation (15 points)

echo "=== Documentation ==="
SCORE=0

# README quality
if [ -f "README.md" ]; then
  LINES=$(wc -l < README.md)
  if [ "$LINES" -gt 50 ]; then SCORE=$((SCORE + 3))
  elif [ "$LINES" -gt 20 ]; then SCORE=$((SCORE + 2))
  elif [ "$LINES" -gt 5 ]; then SCORE=$((SCORE + 1)); fi

  # Check for key sections
  grep -qi "install" README.md && SCORE=$((SCORE + 1))
  grep -qi "usage\|getting started\|quick start" README.md && SCORE=$((SCORE + 1))
  grep -qi "api\|reference\|documentation" README.md && SCORE=$((SCORE + 1))
  grep -qi "contribut" README.md && SCORE=$((SCORE + 1))
  grep -qi "license" README.md && SCORE=$((SCORE + 1))
else
  echo "❌ No README.md"
fi

# Additional docs
[ -f "CONTRIBUTING.md" ] && SCORE=$((SCORE + 2))
[ -f "CHANGELOG.md" ] || [ -f "CHANGES.md" ] && SCORE=$((SCORE + 2))
[ -d "docs" ] || [ -d "doc" ] && SCORE=$((SCORE + 2))
[ -f "LICENSE" ] || [ -f "LICENSE.md" ] && SCORE=$((SCORE + 1))

echo "Documentation score: $SCORE/15"

Dimension 2: Testing (15 points)

echo "=== Testing ==="
SCORE=0

# Test files exist
TEST_COUNT=$(find . -type f \( -name "*.test.*" -o -name "*.spec.*" -o -name "test_*" -o -name "*_test.*" \) \
  -not -path '*/node_modules/*' -not -path '*/vendor/*' 2>/dev/null | wc -l)
SRC_COUNT=$(find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.py" -o -name "*.go" -o -name "*.rs" -o -name "*.java" \) \
  -not -path '*/node_modules/*' -not -path '*/vendor/*' -not -path '*/dist/*' \
  -not -name '*.test.*' -not -name '*.spec.*' 2>/dev/null | wc -l)

if [ "$TEST_COUNT" -gt 0 ]; then
  RATIO=$(echo "scale=0; $TEST_COUNT * 100 / ($SRC_COUNT + 1)" | bc)
  if [ "$RATIO" -gt 80 ]; then SCORE=$((SCORE + 5))
  elif [ "$RATIO" -gt 50 ]; then SCORE=$((SCORE + 4))
  elif [ "$RATIO" -gt 30 ]; then SCORE=$((SCORE + 3))
  elif [ "$RATIO" -gt 10 ]; then SCORE=$((SCORE + 2))
  else SCORE=$((SCORE + 1)); fi
  echo "Test ratio: ${RATIO}% ($TEST_COUNT tests / $SRC_COUNT sources)"
fi

# Test runner configured
if [ -f "package.json" ]; then
  HAS_TEST=$(python3 -c "import json; d=json.load(open('package.json')); s=d.get('scripts',{}).get('test',''); print('yes' if s and 'no test' not in s else 'no')" 2>/dev/null)
  [ "$HAS_TEST" = "yes" ] && SCORE=$((SCORE + 2))
fi
[ -f "pytest.ini" ] || [ -f "conftest.py" ] && SCORE=$((SCORE + 2))
[ -f "jest.config.js" ] || [ -f "jest.config.ts" ] || [ -f "vitest.config.ts" ] && SCORE=$((SCORE + 2))

# Coverage config
rg -l "coverage|istanbul|c8|nyc" package.json .nycrc jest.config.* vitest.config.* pyproject.toml 2>/dev/null | head -1 && SCORE=$((SCORE + 3))

# E2E tests
find . -path "*/e2e/*" -o -path "*/cypress/*" -o -path "*/playwright/*" 2>/dev/null | head -1 && SCORE=$((SCORE + 3))

echo "Testing score: $SCORE/15"

Dimension 3: CI/CD (12 points)

echo "=== CI/CD ==="
SCORE=0

# CI config exists
[ -d ".github/workflows" ] && SCORE=$((SCORE + 3))
[ -f ".gitlab-ci.yml" ] && SCORE=$((SCORE + 3))
[ -f ".circleci/config.yml" ] && SCORE=$((SCORE + 3))
[ -f "Jenkinsfile" ] && SCORE=$((SCORE + 3))

# Multiple workflows (build + test + deploy)
if [ -d ".github/workflows" ]; then
  WF_COUNT=$(ls .github/workflows/*.yml .github/workflows/*.yaml 2>/dev/null | wc -l)
  [ "$WF_COUNT" -ge 3 ] && SCORE=$((SCORE + 3))
  [ "$WF_COUNT" -ge 2 ] && SCORE=$((SCORE + 2)) || true

  # Quality gates
  rg -l "lint\|format\|type-check\|typecheck" .github/workflows/ 2>/dev/null | head -1 && SCORE=$((SCORE + 2))
  rg -l "deploy\|release\|publish" .github/workflows/ 2>/dev/null | head -1 && SCORE=$((SCORE + 2))
fi

# Branch protection indicators
[ -f ".github/branch-protection.yml" ] || [ -f "CODEOWNERS" ] || [ -f ".github/CODEOWNERS" ] && SCORE=$((SCORE + 2))

echo "CI/CD score: $SCORE/12"

Dimension 4: Security (12 points)

echo "=== Security ==="
SCORE=0

# .gitignore quality
if [ -f ".gitignore" ]; then
  SCORE=$((SCORE + 1))
  grep -q "\.env" .gitignore && SCORE=$((SCORE + 1))
  grep -q "node_modules\|vendor\|__pycache__" .gitignore && SCORE=$((SCORE + 1))
fi

# No secrets in repo
SECRET_HITS=$(rg -c "(PRIVATE_KEY|SECRET_KEY|sk-[a-zA-Z0-9]{20,}|ghp_[a-zA-Z0-9]{36}|password\s*=\s*['\"][^'\"]{8,})" \
  -g '!node_modules' -g '!vendor' -g '!*.lock' -g '!*.test.*' -g '!*.example*' \
  --type-not binary 2>/dev/null | awk -F: '{s+=$2} END {print s+0}')
if [ "$SECRET_HITS" -eq 0 ]; then SCORE=$((SCORE + 3))
elif [ "$SECRET_HITS" -lt 3 ]; then SCORE=$((SCORE + 1)); fi

# Security policy
[ -f "SECURITY.md" ] || [ -f ".github/SECURITY.md" ] && SCORE=$((SCORE + 2))

# Dependency scanning
rg -l "dependabot\|renovate\|snyk\|socket" .github/ 2>/dev/null | head -1 && SCORE=$((SCORE + 2))

# Lock file committed
([ -f "package-lock.json" ] || [ -f "yarn.lock" ] || [ -f "pnpm-lock.yaml" ] || [ -f "Cargo.lock" ] || [ -f "go.sum" ]) && SCORE=$((SCORE + 2))

echo "Security score: $SCORE/12"

Dimension 5: Code Quality (12 points)

echo "=== Code Quality ==="
SCORE=0

# Linting configured
([ -f ".eslintrc.js" ] || [ -f ".eslintrc.json" ] || [ -f "eslint.config.js" ] || [ -f "biome.json" ] || [ -f ".flake8" ] || [ -f "ruff.toml" ] || [ -f ".golangci.yml" ]) && SCORE=$((SCORE + 3))

# Formatting configured
([ -f ".prettierrc" ] || [ -f ".prettierrc.json" ] || [ -f "biome.json" ] || [ -f ".editorconfig" ]) && SCORE=$((SCORE + 2))

# Type checking (TypeScript, mypy, etc.)
([ -f "tsconfig.json" ] || rg -l "mypy\|pyright" pyproject.toml setup.cfg 2>/dev/null | head -1) && SCORE=$((SCORE + 3))

# Low TODO/FIXME density
TODO_COUNT=$(rg -c "TODO|FIXME|HACK|XXX" -g '!node_modules' -g '!vendor' --type-not binary 2>/dev/null | awk -F: '{s+=$2} END {print s+0}')
if [ "$TODO_COUNT" -lt 5 ]; then SCORE=$((SCORE + 2))
elif [ "$TODO_COUNT" -lt 20 ]; then SCORE=$((SCORE + 1)); fi

# Pre-commit hooks
([ -f ".husky/pre-commit" ] || [ -f ".pre-commit-config.yaml" ] || [ -d ".lefthook" ]) && SCORE=$((SCORE + 2))

echo "Code quality score: $SCORE/12"

Dimension 6: Dependencies (10 points)

echo "=== Dependencies ==="
SCORE=0

# Dependency count is reasonable
if [ -f "package.json" ]; then
  DEP_COUNT=$(python3 -c "import json; d=json.load(open('package.json')); print(len(d.get('dependencies',{})))" 2>/dev/null)
  if [ "$DEP_COUNT" -lt 20 ]; then SCORE=$((SCORE + 3))
  elif [ "$DEP_COUNT" -lt 50 ]; then SCORE=$((SCORE + 2))
  elif [ "$DEP_COUNT" -lt 100 ]; then SCORE=$((SCORE + 1)); fi
fi

# No deprecated dependencies
DEPRECATED=$(python3 -c "
import json
d = json.load(open('package.json'))
deps = {**d.get('dependencies',{}), **d.get('devDependencies',{})}
deprecated = ['request','node-uuid','nomnom','optimist','jade','istanbul','coffee-script','bower','grunt','moment']
found = [p for p in deprecated if p in deps]
print(len(found))
" 2>/dev/null || echo "0")
[ "$DEPRECATED" -eq 0 ] && SCORE=$((SCORE + 3))

# Engine constraints specified
python3 -c "import json; d=json.load(open('package.json')); print('yes' if 'engines' in d else 'no')" 2>/dev/null | grep -q "yes" && SCORE=$((SCORE + 2))

# Peer dependency aware
python3 -c "import json; d=json.load(open('package.json')); print('yes' if 'peerDependencies' in d else 'na')" 2>/dev/null | grep -q "yes" && SCORE=$((SCORE + 2))

echo "Dependencies score: $SCORE/10"

Dimension 7: Maintainability (12 points)

echo "=== Maintainability ==="
SCORE=0

# Consistent project structure
([ -d "src" ] || [ -d "lib" ] || [ -d "pkg" ] || [ -d "internal" ]) && SCORE=$((SCORE + 2))

# No god files (>1000 lines)
GOD_FILES=$(find . -type f \( -name "*.ts" -o -name "*.js" -o -name "*.py" -o -name "*.go" \) \
  -not -path '*/node_modules/*' -not -path '*/vendor/*' -not -path '*/dist/*' 2>/dev/null | \
  xargs wc -l 2>/dev/null | awk '$1 > 1000 {count++} END {print count+0}')
if [ "$GOD_FILES" -eq 0 ]; then SCORE=$((SCORE + 3))
elif [ "$GOD_FILES" -lt 3 ]; then SCORE=$((SCORE + 2))
elif [ "$GOD_FILES" -lt 5 ]; then SCORE=$((SCORE + 1)); fi

# Recent activity (commits in last 90 days)
RECENT=$(git log --since="90 days ago" --oneline 2>/dev/null | wc -l)
if [ "$RECENT" -gt 20 ]; then SCORE=$((SCORE + 3))
elif [ "$RECENT" -gt 5 ]; then SCORE=$((SCORE + 2))
elif [ "$RECENT" -gt 0 ]; then SCORE=$((SCORE + 1)); fi

# Issue/PR templates
([ -f ".github/ISSUE_TEMPLATE/bug_report.md" ] || [ -d ".github/ISSUE_TEMPLATE" ] || [ -f ".github/pull_request_template.md" ]) && SCORE=$((SCORE + 2))

# Multiple contributors
CONTRIBUTORS=$(git log --format="%an" 2>/dev/null | sort -u | wc -l)
[ "$CONTRIBUTORS" -gt 3 ] && SCORE=$((SCORE + 2))

echo "Maintainability score: $SCORE/12"

Dimension 8: Community (12 points)

echo "=== Community ==="
SCORE=0

# Contributing guide
[ -f "CONTRIBUTING.md" ] && SCORE=$((SCORE + 3))

# Code of conduct
[ -f "CODE_OF_CONDUCT.md" ] && SCORE=$((SCORE + 2))

# Issue templates
[ -d ".github/ISSUE_TEMPLATE" ] && SCORE=$((SCORE + 2))

# PR template
[ -f ".github/pull_request_template.md" ] && SCORE=$((SCORE + 2))

# GitHub features
if command -v gh &>/dev/null; then
  STARS=$(gh repo view --json stargazerCount -q '.stargazerCount' 2>/dev/null || echo "0")
  FORKS=$(gh repo view --json forkCount -q '.forkCount' 2>/dev/null || echo "0")
  [ "$STARS" -gt 100 ] && SCORE=$((SCORE + 1))
  [ "$FORKS" -gt 10 ] && SCORE=$((SCORE + 1))
fi

# Badges in README (community engagement indicator)
if [ -f "README.md" ]; then
  BADGES=$(grep -c "!\[" README.md 2>/dev/null || echo "0")
  [ "$BADGES" -gt 3 ] && SCORE=$((SCORE + 1))
fi

echo "Community score: $SCORE/12"

Composite Score

Sum all dimensions (max 100) and assign a letter grade:

ScoreGradeAssessment
90-100AExcellent — production-ready, well-maintained
80-89BGood — solid project with minor gaps
70-79CFair — functional but needs attention
60-69DBelow average — significant gaps
<60FPoor — high risk, needs major investment

2. compare — Compare Two Repositories

Run score on two repos and produce a side-by-side comparison. Useful for choosing between competing libraries.

3. improve — Top 5 Improvements

Based on the score breakdown, suggest the 5 highest-impact improvements with AI reasoning:

## Top 5 Improvements (by score impact)

1. **Add tests** (+8 points) — No test files found. Start with unit tests for core modules.
   Effort: M | Impact: Testing 0→8/15

2. **Configure CI** (+6 points) — No CI pipeline. Add GitHub Actions with lint+test+build.
   Effort: S | Impact: CI/CD 0→6/12

3. **Add CHANGELOG.md** (+2 points) — No changelog. Start with Keep a Changelog format.
   Effort: XS | Impact: Documentation 11→13/15

4. **Set up Dependabot** (+2 points) — No dependency automation.
   Effort: XS | Impact: Security 8→10/12

5. **Add CONTRIBUTING.md** (+3 points) — No contributor guide.
   Effort: S | Impact: Community 4→7/12

Output Formats

  • text (default): Human-readable scorecard with bar chart
  • json: {total, grade, dimensions: {name: {score, max, details: []}}, improvements: []}
  • markdown: Report card format with tables and grade badges
  • badge: Shield.io badge URL for README: ![Health Score](https://img.shields.io/badge/health-B%2083%25-green)

Notes

  • Works on any git repository — adapts to language/framework automatically
  • Does not execute code or install dependencies — purely static analysis
  • Community dimension requires gh CLI for GitHub metrics (optional)
  • Scores are relative — a CLI tool and a web app have different baselines
  • Run periodically to track improvement trends

Comments

Loading comments...