Project Health
One skill for everything about your project's Claude Code configuration. Run it at the start, middle, or end of a project — it figures out what's needed.
Goal: Zero permission prompts, well-organised context files, no cruft.
When to Use
| You say... | What happens | |-----------|-------------| | "project health" / "check project" | Full audit: permissions + context + docs | | "setup project" / "kickoff" / "bootstrap" | New project setup from scratch | | "tidy permissions" / "clean settings" | Fix permissions file only | | "capture learnings" / "update CLAUDE.md" | Save session discoveries | | "add python" / "add docker permissions" | Add a preset to existing settings | | "audit context" / "audit memory" | Context-focused audit only |
Architecture: Sub-Agents
Heavy analysis runs in sub-agents to keep the main conversation clean. The main agent orchestrates; sub-agents do the scanning and return summaries.
Agent 1: Permission Auditor
Launched with Task(subagent_type: "general-purpose"). Prompt:
Read .claude/settings.local.json.
**Discover connected MCP servers**: Use ToolSearch (search "mcp") and extract unique
server prefixes from tool names (e.g. mcp__vault__secret_list → vault).
**Discover installed skills**: Use the Skill tool or ToolSearch to list available skills.
For each skill that has scripts/ in its directory, note what Bash patterns it needs
(python3, env var prefixes like GEMINI_API_KEY=*, etc.). Check the SKILL.md for any
MCP tools the skill references (e.g. mcp__vault__secret_get).
Report:
1. MCP servers connected but NOT in settings (missing)
2. MCP servers in settings but NOT connected (stale)
3. Skill permissions: Bash patterns and MCP tools that installed skills need but aren't approved
4. File access: check for Read/Edit/Write patterns for .claude/** and //tmp/**
in project settings, and ~/Documents/**/~/.claude/** in global settings
5. Leaked secrets: entries containing API keys, tokens, bearer strings, hex >20 chars, base64 >20 chars
6. Legacy colon syntax: entries like Bash(git:*) instead of Bash(git *)
7. Junk entries: shell fragments (Bash(do), Bash(fi), Bash(then), Bash(else), Bash(done)),
__NEW_LINE_* artefacts, loop body fragments (Bash(break), Bash(continue), Bash(echo *))
8. Duplicates: entries covered by a broader pattern (e.g. Bash(git add *) redundant if Bash(git *) exists)
9. Missing presets: based on files present, suggest presets from [permission-presets.md]
Prefer Read/Glob/Grep tools over Bash. If you need to scan multiple files or
run 3+ commands for one analysis, write a Python script to .jez/scripts/
and run it once (mkdir -p .jez/scripts first).
Return a structured summary, not raw data.
Agent 2: Context Auditor
Launched with Task(subagent_type: "general-purpose"). Prompt:
Audit the project context landscape at [repo-path]:
1. Find all CLAUDE.md files. For each:
- Count lines (target: root 50-150, subdirs 15-50)
- Score quality on 6 criteria (see quality-criteria.md)
- Check for stale file/path references
- Flag oversized files
2. Find .claude/rules/ topic files. Check sizes (target: 20-80 lines).
3. Detect project type from files present (see project-types.md).
Check expected docs exist (ARCHITECTURE.md, DATABASE_SCHEMA.md, etc.)
4. Find public markdown (README.md, LICENSE, CONTRIBUTING.md).
Check for overlap with CLAUDE.md content.
5. Check auto-memory at ~/.claude/projects/*/memory/MEMORY.md
6. If Cloudflare project: find all wrangler.jsonc/wrangler.toml files.
Check each has "observability": { "enabled": true }. Flag any missing it.
Prefer Read/Glob/Grep tools over Bash. If you need to scan many files or
aggregate data across the repo, write a Python script to .jez/scripts/
and run it once rather than running many individual bash commands
(mkdir -p .jez/scripts first).
Return: project type, quality scores, missing docs, stale refs, overlaps,
size violations, observability gaps, and total markdown footprint.
Parallel Execution
For a full health check, launch both agents in parallel:
Task(subagent_type: "general-purpose", name: "permission-audit", prompt: "...")
Task(subagent_type: "general-purpose", name: "context-audit", prompt: "...")
Both return summaries. The main agent combines them into one report and proposes fixes.
Mode 1: Full Health Check
The default. Run this anytime.
Steps
-
Launch Permission Auditor and Context Auditor agents in parallel
-
Combine findings into a single report:
## Project Health Report **Project type**: [detected type] **CLAUDE.md quality**: [score]/100 ([grade]) ### Permissions - Missing MCP servers: [list] - Leaked secrets: [count] found - Legacy syntax: [count] entries - Missing presets: [list] ### Context - Oversized files: [list] - Stale references: [list] - Missing docs: [list] - Overlaps: [list] ### Recommended Fixes 1. [fix 1] 2. [fix 2] ... -
Apply fixes after single yes/no confirmation
Mode 2: New Project Setup
When: No .claude/settings.local.json exists, or user says "setup" / "kickoff".
Steps
-
Detect project type from files present:
| Indicator | Type | Preset | |-----------|------|--------| |
wrangler.jsoncorwrangler.toml| cloudflare-worker | JS/TS + Cloudflare | |vercel.jsonornext.config.*| vercel-app | JS/TS + Vercel | |astro.config.*| astro | JS/TS + Static Sites | |package.json(no deploy target) | javascript-typescript | JS/TS | |pyproject.tomlorsetup.pyorrequirements.txt| python | Python | |Cargo.toml| rust | Rust | |go.mod| go | Go | |GemfileorRakefile| ruby | Ruby | |composer.jsonorwp-config.php| php | PHP | |pom.xmlorbuild.gradle*| java | Java/JVM | |*.slnor*.csproj| dotnet | .NET | |mix.exs| elixir | Elixir | |Package.swift| swift | Swift + macOS | |pubspec.yaml| flutter | Mobile | |Dockerfileordocker-compose.yml| docker | Docker | |fly.tomlorrailway.jsonornetlify.toml| hosted-app | Hosting Platforms | |supabase/config.toml| supabase | Hosting + Database | |.claude/agents/or operational scripts | ops-admin | — | | Empty directory | Ask the user | — |Types stack (e.g. cloudflare-worker + javascript-typescript).
-
Generate
.claude/settings.local.json:- Read references/permission-presets.md
- Always include Universal Base (includes file access for
.claude/**,//tmp/**) - Add detected language + deployment presets
- Check if global
~/.claude/settings.local.jsonhas home-relative file access patterns (~/Documents/**,~/.claude/**). If not, suggest adding them there (NOT in the project file — home paths belong in global settings only) - Launch Permission Auditor agent to discover MCP servers and add per-server wildcards
- Always include
WebSearch,WebFetch - Always include explicit
ghsubcommands (workaround forBash(gh *)bug) - Write with
//comment groups
-
Generate
CLAUDE.md:- Read references/templates.md
- Use project-type-appropriate template
-
Generate
.gitignore:- Read references/templates.md
- Always include
.claude/settings.local.json,.claude/plans/,.jez/screenshots/,.jez/artifacts/ - Do NOT gitignore
.jez/scripts/— generated scripts are worth keeping
-
Optionally (ask first):
git init+gh repo create -
Warn: "Project settings.local.json SHADOWS global settings (does not merge). Session restart needed."
Mode 3: Tidy Permissions
When: User says "tidy permissions" or health check found permission issues.
Launch the Permission Auditor agent, then apply its recommended fixes.
Mode 4: Capture Learnings
When: End of session, "capture learnings", "save what we learned".
This runs in the main context (not a sub-agent) because it needs access to the conversation history.
- Review conversation for discoveries worth preserving
- Decide placement:
Applies to all projects? ├── YES → ~/.claude/rules/<topic>.md └── NO → Specific to a subdirectory? ├── YES → <dir>/CLAUDE.md └── NO → Reference or operational? ├── Reference → docs/ or ARCHITECTURE.md └── Operational → ./CLAUDE.md (root) - Draft all changes as diffs in a single batch
- Apply after single yes/no confirmation
Keep it concise: one line per concept.
Mode 5: Add Preset
When: "add python permissions", "add docker", "add MCP servers".
- Read the preset from references/permission-presets.md
- Read existing
.claude/settings.local.json - Merge without duplicating
- Remind: session restart required
Mode 6: Restructure Context
When: Root CLAUDE.md over 200 lines, "restructure memory".
- Launch Context Auditor agent first
- Based on findings:
- Split oversized CLAUDE.md into
.claude/rules/<topic>.md - Extract directory-specific content to sub-directory CLAUDE.md
- Move reference material to
docs/ - Resolve overlaps
- Create missing docs for project type
- Split oversized CLAUDE.md into
- Present plan, apply after approval
Size Targets
| File | Target | Maximum | |------|--------|---------| | Root CLAUDE.md | 50-150 lines | 200 | | Sub-directory CLAUDE.md | 15-50 lines | 80 | | Rules topic file | 20-80 lines | 120 |
Permission Syntax Quick Reference
| Pattern | Meaning |
|---------|---------|
| Bash(git *) | Preferred — space before * = word boundary |
| Bash(nvidia-smi) | Exact match, no arguments |
| WebFetch | Blanket web fetch |
| WebSearch | Blanket web search |
| mcp__servername__* | All tools on one MCP server |
What Does NOT Work
| Pattern | Why |
|---------|-----|
| mcp__* | Wildcard doesn't cross __ boundary |
| mcp__*__* | Still doesn't work |
| Bash(git:*) | Deprecated colon syntax (works but prefer space) |
Important Behaviours
- Not hot-reloaded:
settings.local.jsonedits need session restart - "Don't ask again" injects at runtime (no restart) using colon format — normal
- Shadows, not merges: Project settings completely replace global
ghbug:Bash(gh *)sometimes misses subcommands — include explicitBash(gh issue *)etc.
Autonomy
- Just do it: Detect project type, launch audit agents, discover MCP servers
- Brief confirmation: Write/update files (single batch yes/no)
- Ask first: git init, GitHub repo, delete existing content, major restructures
Reference Files
| When | Read | |------|------| | Building permission presets | references/permission-presets.md | | Generating CLAUDE.md, .gitignore | references/templates.md | | Scoring CLAUDE.md quality | references/quality-criteria.md | | Detecting project type + expected docs | references/project-types.md | | Setting up commit capture hook | references/commit-hook.md |