healthcheck · iurykrieger — Claude Code skill: what it does, how to install
Runs read-only diagnostics on your bedrock vault to detect orphaned entities, stale notes, and missing graph files without modifying data.
npx skills add iurykrieger/claude-bedrock --skill healthcheck -a claude-codeWhat healthcheck does
This skill inspects a bedrock vault without editing any files on disk. It validates graphify-out/graph.json and verifies the folder layout. It also detects orphan entities lacking inbound wikilinks and highlights notes untouched for more than 15 days.
Target vault selection relies on the --vault flag, directory matching against vaults.json, or the default registry entry. Once resolved, the scanner reads markdown files in folders such as actors and projects, extracting frontmatter fields alongside wikilinks.
The agent operates strictly in read-only mode and spawns no subagents. If the resolved vault folder is missing on disk, diagnostics halt immediately until re-registered via /bedrock:setup.
What it helps with
- detect orphan entities lacking inbound wikilinks
- verify the integrity of
graphify-out/graph.json - identify notes left unedited for more than 15 days
- inspect vault directory structure and entity templates
Example prompts for the agent
- Run
/bedrock:healthcheckto inspect the active vault. - Check the vault health using
--vault work. - Run a vault diagnostic to find unlinked notes and stale content.
How to install healthcheck
1Skills CLI (Vercel)
npx skills add iurykrieger/claude-bedrock --skill healthcheck -a claude-code2Manually: put the files in place
~/.claude/skills/healthcheck/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/healthcheck/
1Skills CLI (Vercel)
npx skills add iurykrieger/claude-bedrock --skill healthcheck -a codex2Manually: put the files in place
.agents/skills/healthcheck/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add iurykrieger/claude-bedrock --skill healthcheck -a cursor2Manually: put the files in place
.cursor/skills/healthcheck/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install iurykrieger/claude-bedrock healthcheck2Manually: put the files in place
.github/skills/healthcheck/SKILL.md1Skills CLI (Vercel)
npx skills add iurykrieger/claude-bedrock --skill healthcheck -a gemini-cli2Platform CLI
gemini skills install https://github.com/iurykrieger/claude-bedrock --path skills/healthcheckManually: put the files in place
.devin/skills/healthcheck/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add iurykrieger/claude-bedrock --skill healthcheck -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about healthcheck
How to install healthcheck in Claude Code?
Run npx skills add iurykrieger/claude-bedrock --skill healthcheck -a claude-code.
What does the healthcheck skill verify?
It executes five diagnostics covering directory layout and graph.json integrity. It also flags disconnected notes and files older than 15 days.
Can healthcheck alter vault files?
No, it operates in strict read-only mode. It uses Read, Glob, Grep, and Bash solely to assemble a terminal diagnostic report.
Source text
SKILL.md · MIT
---
name: healthcheck
description: >
Read-only vault health diagnostic. Generates a report without modifying any files.
Checks: graphify-out integrity, setup verification, orphan entities, dangling content,
old content (>15 days). Safe to run at any frequency.
Use when: "bedrock healthcheck", "bedrock-healthcheck", "vault health", "check vault",
"vault status", "/bedrock:healthcheck".
user_invocable: true
allowed-tools: Bash, Read, Glob, Grep
---
# /bedrock:healthcheck — Vault Health Report
## Plugin Paths
Entity definitions and templates are in the plugin directory, not the vault root.
Use the "Base directory for this skill" provided at invocation to resolve paths:
- Entity definitions: `<base_dir>/../../entities/`
- Templates: `<base_dir>/../../templates/{type}/_template.md`
- Plugin CLAUDE.md: `<base_dir>/../../CLAUDE.md` (already injected automatically into context)
Where `<base_dir>` is the path provided in "Base directory for this skill".
---
## Vault Resolution
Resolve which vault to diagnose. This skill can be invoked from any directory.
**Step 1 — Parse `--vault` flag:**
Check if the input arguments include `--vault <name>`. If found, extract the vault name.
**Step 2 — Resolve vault path:**
1. **If `--vault <name>` was provided:**
Read the vault registry at `<base_dir>/../../vaults.json`. Find the entry matching the name.
If not found: error — "Vault `<name>` is not registered. Run `/bedrock:vaults` to see available vaults."
If found: set `VAULT_PATH` to the entry's `path` value.
2. **If no `--vault` flag — CWD detection:**
Read `<base_dir>/../../vaults.json`. Check if the current working directory is inside any registered vault path
(CWD starts with a registered vault's absolute path). If multiple match, use the longest path (most specific).
If found: set `VAULT_PATH` to the matching vault's `path`.
3. **If CWD detection fails — default vault:**
From the registry, find the vault with `"default": true`.
If found: set `VAULT_PATH` to the default vault's `path`.
4. **If no resolution:**
Error — "No vault resolved. Available vaults:" followed by the registry listing.
"Use `--vault <name>` to specify, or run `/bedrock:setup` to register a vault."
**Step 3 — Validate vault path:**
```bash
test -d "<VAULT_PATH>" && echo "exists" || echo "missing"
```
If missing: error — "Vault path `<VAULT_PATH>` does not exist on disk. Run `/bedrock:setup` to re-register."
**Step 4 — Read vault config:**
```bash
cat <VAULT_PATH>/.bedrock/config.json 2>/dev/null
```
Extract `language` and other relevant fields for use in later phases.
**From this point forward, ALL vault file operations use `<VAULT_PATH>` as the root.**
- Entity directories: `<VAULT_PATH>/actors/`, `<VAULT_PATH>/people/`, etc.
- Graphify output: `<VAULT_PATH>/graphify-out/`
---
## Overview
This skill produces a diagnostic report of vault health without modifying any files.
It scans the vault once, runs 5 checks against the scan data, and prints the results.
**You are a read-only agent.** You do NOT write files, commit, push, invoke other skills,
or spawn subagents. Your only output is the diagnostic report printed to the terminal.
### Five health checks
| # | Check | What it verifies |
|---|---|---|
| 1 | graphify-out | Graph.json exists, is valid, is fresh |
| 2 | Setup | Directories, templates, entity definitions, plugin manifest |
| 3 | Orphan entities | Entities with zero inbound wikilinks |
| 4 | Dangling content | Entities fully disconnected (no inbound, no outbound, no relations) |
| 5 | Old content | Entities with `updated_at` older than 15 days |
### Status values
Each check reports one of:
- **OK** — no issues found
- **WARN** — issues found (with details)
- **MISSING** — prerequisite not met (e.g., graphify-out absent)
---
## Phase 1 — Scan the Vault
Read all entity files once and store the data for use across all 5 checks.
### 1.1 Enumerate entity files
For each entity directory (`<VAULT_PATH>/actors/`, `<VAULT_PATH>/people/`, `<VAULT_PATH>/teams/`, `<VAULT_PATH>/concepts/`, `<VAULT_PATH>/topics/`, `<VAULT_PATH>/discussions/`, `<VAULT_PATH>/projects/`, `<VAULT_PATH>/fleeting/`):
1. List all `.md` files using Glob, **excluding `_template.md` and `_template_node.md`**
- For actors: include both `<VAULT_PATH>/actors/*.md` (flat) and `<VAULT_PATH>/actors/*/*.md` (folder)
- Include code entities: `<VAULT_PATH>/actors/*/nodes/*.md`
2. Record the directory and filename for each entity
### 1.2 Read entity data
For each entity file found in 1.1:
1. Read the file
2. Extract from frontmatter:
- `type`
- `name` (or derive from filename)
- `aliases` (array)
- `updated_at` (date string)
- All frontmatter array fields that contain wikilinks (e.g., `actors`, `people`, `teams`, `related_to`, etc.)
3. Extract from body:
- All wikilinks `[[target]]` (regex: `\[\[([^\]]+)\]\]`)
4. Compute:
- `outbound_wikilinks`: union of all wikilinks from body + frontmatter arrays
- `has_frontmatter_relations`: true if any frontmatter array field contains at least one wikilink value
- `entity_slug`: the filename without extension (used as the canonical identifier)
**Output:** `vault_entities` map: `entity_slug → {type, name, aliases[], updated_at, outbound_wikilinks[], has_frontmatter_relations, file_path}`
Also collect: `all_entity_slugs` — set of all entity slugs in the vault (for resolving wikilinks).
---
## Phase 2 — Run Checks
### 2.1 Check 1 — graphify-out
1. Check if directory `<VAULT_PATH>/graphify-out/` exists:
```bash
ls -d <VAULT_PATH>/graphify-out/ 2>/dev/null && echo "EXISTS" || echo "MISSING"
```
2. If MISSING:
- Status: **MISSING**
- Details: "graphify-out/ directory not found. Run `/bedrock:learn` on an actor repository to generate."
- Skip remaining sub-checks.
3. If EXISTS, check `<VAULT_PATH>/graphify-out/graph.json`:
```bash
test -f <VAULT_PATH>/graphify-out/graph.json && echo "EXISTS" || echo "MISSING"
```
4. If graph.json MISSING:
- Status: **MISSING**
- Details: "graph.json not found in graphify-out/. Run `/bedrock:learn` to generate."
- Skip remaining sub-checks.
5. If graph.json EXISTS, validate and extract stats:
```bash
python3 -c "
import json, os, time
from pathlib import Path
g = json.loads(Path('<VAULT_PATH>/graphify-out/graph.json').read_text())
nodes = g.get('nodes', [])
code_nodes = [n for n in nodes if n.get('file_type') == 'code']
mtime = os.path.getmtime('<VAULT_PATH>/graphify-out/graph.json')
mod_date = time.strftime('%Y-%m-%d', time.localtime(mtime))
days_old = (time.time() - mtime) / 86400
print(f'total_nodes={len(nodes)}')
print(f'code_nodes={len(code_nodes)}')
print(f'mod_date={mod_date}')
print(f'days_old={int(days_old)}')
print(f'stale={\"yes\" if days_old > 30 else \"no\"}')
" 2>/dev/null || echo "INVALID_JSON"
```
6. If INVALID_JSON:
- Status: **WARN**
- Details: "graph.json exists but is not valid JSON."
7. If valid:
- If stale (>30 days): Status: **WARN**, Details: "Graph.json is stale (>30 days). Last updated: {mod_date}. Run `/bedrock:learn` or `/bedrock:sync` to update."
- If fresh: Status: **OK**, Details: "{total_nodes} nodes ({code_nodes} code). Last updated: {mod_date}."
**Store:** `graphify_status`, `graphify_details`, `graphify_node_count`
### 2.2 Check 2 — Setup
Verify the vault structure and plugin dependencies.
#### 2.2.1 Entity directories
Check that each expected directory exists:
- `<VAULT_PATH>/actors/`, `<VAULT_PATH>/people/`, `<VAULT_PATH>/teams/`, `<VAULT_PATH>/concepts/`, `<VAULT_PATH>/topics/`, `<VAULT_PATH>/discussions/`, `<VAULT_PATH>/projects/`, `<VAULT_PATH>/fleeting/`
For each directory, check if `_template.md` exists inside it.
Record: list of missing directories, list of directories missing templates.
#### 2.2.2 Entity definitions
Check that entity definitions exist in the plugin directory:
```
<base_dir>/../../entities/
```
Expected files: `actor.md`, `person.md`, `team.md`, `concept.md`, `topic.md`, `discussion.md`, `project.md`, `fleeting.md`
Record: list of missing entity definitions.
#### 2.2.3 Plugin manifest
Check that `.claude-plugin/plugin.json` exists and is valid JSON:
```bash
python3 -c "import json; json.loads(open('.claude-plugin/plugin.json').read()); print('VALID')" 2>/dev/null || echo "INVALID"
```
Record: manifest status.
#### 2.2.4 Result
- If everything present: Status: **OK**, Details: "All directories, templates, definitions, and manifest verified."
- If issues found: Status: **WARN**, Details: list of missing items.
**Store:** `setup_status`, `setup_details`, `setup_issue_count`
### 2.3 Check 3 — Orphan entities
For each entity in `vault_entities`:
1. Count **inbound wikilinks**: how many OTHER entities reference this entity via `[[entity_slug]]`
- Search: count how many entities in `vault_entities` have this entity's slug in their `outbound_wikilinks`
- Also check for alias matches: if entity has `aliases`, check if any alias (converted to slug format) appears in other entities' outbound wikilinks
2. If inbound count = 0: mark as **orphan**
Exclude from orphan check:
- Templates (`_template.md`)
- The entity itself (self-links don't count)
**Store:** `orphan_entities[]` — list of `{entity_slug, type}`
**Aggregate:** `orphan_count_by_type` — map `type → count`
Result:
- If 0 orphans: Status: **OK**
- If orphans found: Status: **WARN**, Details: count per type + entity names
### 2.4 Check 4 — Dangling content
From the orphan list (Check 3), further filter for entities that are **fully disconnected**:
An entity is dangling if ALL three conditions are true:
1. **No inbound wikilinks** (already orphan from Check 3)
2. **No outbound wikilinks** in the body (entity's `outbound_wikilinks` is empty)
3. **No frontmatter relations** (entity's `has_frontmatter_relations` is false)
**Store:** `dangling_entities[]` — list of `{entity_slug, type}`
Result:
- If 0 dangling: Status: **OK**
- If dangling found: Status: **WARN**, Details: entity names
### 2.5 Check 5 — Old content
For each entity in `vault_entities`:
1. Read `updated_at` from the entity data
2. If `updated_at` is missing or cannot be parsed: skip (do not flag — missing metadata is a setup issue, not a staleness issue)
3. Calculate age in days: `current_date - updated_at`
4. If age > 15 days: mark as **old**
**Store:** `old_entities[]` — list of `{entity_slug, type, updated_at, age_days}`, sorted by `age_days` descending (oldest first)
**Aggregate:** `old_count_by_type` — map `type → count`
Result:
- If 0 old: Status: **OK**
- If old found: Status: **WARN**, Details: count per type, oldest entity with age
---
## Phase 3 — Generate Report
Print the full report to the terminal.
```markdown
## /bedrock:healthcheck — Report
| Check | Status | Count | Details |
|---|---|---|---|
| graphify-out | {graphify_status} | {node_count} nodes | {graphify_details} |
| Setup | {setup_status} | {setup_issue_count} issues | {setup_details} |
| Orphan entities | {orphan_status} | {orphan_count} orphans | {orphan_details} |
| Dangling content | {dangling_status} | {dangling_count} dangling | {dangling_details} |
| Old content (>15d) | {old_status} | {old_count} stale | {old_details} |
```
### Orphan details (if WARN)
```markdown
### Orphan Entities
| # | Entity | Type |
|---|---|---|
| 1 | [[entity-slug]] | actor |
| 2 | [[entity-slug]] | person |
| ... | ... | ... |
**By type:** actors: N, people: N, teams: N, ...
```
### Dangling details (if WARN)
```markdown
### Dangling Content (fully disconnected)
| # | Entity | Type |
|---|---|---|
| 1 | [[entity-slug]] | fleeting |
| ... | ... | ... |
```
### Old content details (if WARN)
```markdown
### Old Content (>15 days without update)
| # | Entity | Type | Last updated | Age |
|---|---|---|---|---|
| 1 | [[entity-slug]] | actor | 2026-03-01 | 45 days |
| 2 | [[entity-slug]] | topic | 2026-03-15 | 31 days |
| ... | ... | ... | ... | ... |
**By type:** actors: N, topics: N, ...
```
### Suggestions
Based on findings, append actionable suggestions:
- If orphan or dangling count > 0: "Run `/bedrock:compress` to detect and fix alignment issues (broken backlinks, missing entities)."
- If graphify-out is MISSING or stale: "Run `/bedrock:learn` on an actor repository to generate or update the graph."
- If old count > 0: "Review {N} stale entities for relevance. Consider updating or archiving."
- If setup has issues: "Run `/bedrock:setup` to initialize missing directories or templates."
- If all checks are OK: "Vault is healthy. No action needed."
---
## Error Handling
| Situation | Action |
|---|---|
| Empty vault (no entity files) | Report all checks as OK with 0 counts. "Vault is empty — no entities found." |
| Entity file cannot be read | Skip entity, do not fail the check. Note in report: "N entities skipped due to read errors." |
| Frontmatter cannot be parsed | Skip entity for frontmatter-dependent checks (updated_at, relations). Count as readable for wikilink checks. |
| graphify-out/graph.json is not valid JSON | Report as WARN for Check 1. Continue with other checks. |
| Plugin directory not accessible | Report as WARN for Check 2. Continue with other checks. |
| No `updated_at` field in entity | Skip for Check 5 (old content). Do not flag as old. |
---
## Critical Rules
| Rule | Detail |
|---|---|
| Read-only | NEVER use Write, Edit, Skill, or Agent tools. This skill only reads and reports. |
| No git operations | NEVER run git add, commit, push, pull, or any mutating git command. |
| No skill invocations | NEVER invoke /bedrock:compress, /bedrock:learn, /bedrock:preserve, or any other skill. Suggest them in text only. |
| Terminal output only | The report is printed to the terminal. No files are created or modified. |
| Single-pass scan | Phase 1 scans once. All 5 checks in Phase 2 use the same scan data. |
| Exclude templates | Always exclude `_template.md` and `_template_node.md` from entity counts and checks. |
| 15-day threshold | Old content is defined as `updated_at` > 15 days from current date. Hardcoded. |
| 30-day threshold | Stale graph is defined as graph.json modification date > 30 days. Hardcoded. |
| Bare wikilinks | Parse wikilinks as `[[name]]` only. Never path-qualified (`[[dir/name]]`). |
| Sensitive data | NEVER include credentials, tokens, passwords, PANs, CVVs in the report. |
| Vault resolution first | Resolve `VAULT_PATH` before any file operation — never assume CWD is the vault |
| All entity paths use `<VAULT_PATH>/` prefix | `<VAULT_PATH>/actors/`, not `actors/` |
© iurykrieger · MIT · iurykrieger/claude-bedrock
Similar skills
All skills for Agent setup: memory, context, orchestration →healthcheck by other authors comes first.