/hygiene
Manual cleanup of dead code, broken type refs, stale config, and schema cruft. Works on TypeScript/Svelte projects, with optional Postgres/Supabase checks. Tailored for the JST stack.
$ npx -y skills add joewinke/jat --agent claude-codeHow it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/hygiene
Context preview
What this command does when you run it.
Manual cleanup of dead code, broken type refs, stale config, and schema cruft. Works on TypeScript/Svelte projects, with optional Postgres/Supabase checks. Tailored for the JST stack.
Command definition
hygiene.mdargument-hint: [--safe-only | --dry-run]
/jat:hygiene - Code Hygiene Pass
Manual cleanup of dead code, broken type refs, stale config, and schema cruft. Works on TypeScript/Svelte projects, with optional Postgres/Supabase checks. Tailored for the JST stack.
**Use this when:** The user wants a hygiene/cleanup pass, or periodic tech-debt grooming.
**Flags:**
- `--safe-only` — Apply only auto-safe fixes (JSDoc, stale config, dead ts-ignores). Skip all deletion steps.
- `--dry-run` — Report findings without modifying any files.
**This is NOT for:** Linting/formatting (that's `prettier`/`eslint`), or refactoring.
---
Philosophy
Dead-code tools (knip, ts-prune) produce **candidates, not verdicts.** Every file/dep they flag needs human judgment because of these blind spots:
- Dynamic string imports (`target: 'pino-pretty'`)
- Build-time config refs (`vite.config.ts`, static copies)
- HTML `<script>` tag refs (`app.html`, `static/*.html`)
- Svelte dynamic components (`<svelte:component this={...}>`)
- Test fixtures / e2e harnesses outside source tree
- Type-only exports consumed externally
**Rule:** Apply safe fixes automatically. Verify every deletion candidate by hand.
---
STEP 0 — Stack Detection
Before starting, detect what applies to this project:
# Is there a frontend (Svelte/TS)?
test -f package.json && echo "has-node"
test -d src && ls src/**/*.svelte 2>/dev/null | head -1 && echo "has-svelte"
grep -l "typescript" package.json 2>/dev/null && echo "has-ts"
# Is there a database?
test -d supabase && echo "has-supabase"
test -d migrations && echo "has-migrations"
grep -l '"pg"\|"postgres"\|@supabase' package.json 2>/dev/null && echo "has-pg-client"
# Is this a SvelteKit app?
test -f svelte.config.js && echo "has-sveltekit"
Announce what you detected and skip irrelevant steps.
---
STEP 1 — Safe Auto-Fixes (always run, never ask)
These are pure wins with no behavioral risk. Apply them silently, then mention the total in the report.
1a. Broken JSDoc Type Imports
Find `@type` / `@typedef` / `@param` blocks importing nonexistent files:
# If svelte-check is available, use it
npx svelte-check --output machine 2>&1 | grep -i "cannot find module" || true
# Otherwise grep for JSDoc imports and verify each path
grep -rn "import('\./" src/ --include='*.js' --include='*.ts' --include='*.svelte' | \
grep -oP "import\('[^']+'" | sort -uFor each broken ref:
- If the correct path is obvious (file was moved, import path wrong), fix it
- Otherwise replace with `any` — JSDoc is non-runtime, this is safe
1b. Stale Build Config
Check that every package referenced in build config actually exists in `package.json`:
# Grep for package names in build files
grep -oE "'[a-z0-9@/-]+'" vite.config.ts svelte.config.js 2>/dev/null | sort -u
Remove stale refs in:
- `vite.config.ts` — `ssr.external`, `optimizeDeps.include`, `rollupOptions.external`, `resolve.alias`
- `svelte.config.js` — `kit.alias`, preprocessor plugins
- `tsconfig.json` — `paths`, `types` arrays pointing at deleted `@types/*`
1c. Dead TS-Ignore Comments
# Run tsc and look for "unused @ts-expect-error" errors
npx tsc --noEmit 2>&1 | grep "unused" || true
Remove every `// @ts-expect-error` / `// @ts-ignore` that TypeScript reports as unused.
---
STEP 2 — Knip Scan + Manual Review
Only run if `--safe-only` was not passed.
# Make sure knip is available
npx knip --no-progress 2>&1 | tee /tmp/knip-report.txt
Classify findings into these buckets. **Do not delete anything yet.**
Bucket A: Unused Files
For each flagged file, run these checks before deleting:
# 1. Is it referenced anywhere by basename? (catches dynamic imports, HTML refs)
git grep -F "$(basename FILE .svelte)"
# 2. Is it referenced by relative path? (catches partial matches)
git grep -F "FILE_PATH"
# 3. Is it a SvelteKit convention file? (+page, +layout, +server, +error)
# If yes → KEEP. knip should know but sometimes misses.
# 4. Is it in static/ and loaded from HTML?
grep -r "FILENAME" static/*.html src/app.html 2>/dev/null
**Decision:**
- 0 hits outside itself → candidate for deletion
- Any hit → investigate, likely a false positive
Bucket B: Unused Dependencies
For each flagged package, two false-positive patterns to check:
# 1. Dynamic string imports (pino-pretty trap)
git grep -F "'PACKAGE_NAME'"
git grep -F "\"PACKAGE_NAME\""
# 2. Build-time usage
git grep -F "PACKAGE_NAME" vite.config.ts svelte.config.js scripts/ package.json
If either returns a hit, **keep** the dep and note why.
Bucket C: Unused Exports / Types (LOW priority)
Skip unless the user explicitly asks. These have high churn risk and low cleanup value. Unused type exports in particular are cheap to keep and annoying if wrong.
**Exception:** Duplicate exports (same symbol exported twice) — usually safe to consolidate.
---
STEP 3 — Svelte-Specific Checks
Only for projects with `.svelte` files.
# svelte-check should report zero new errors (or only known baseline)
npx svelte-check 2>&1 | tail -20
# Look for runes used in wrong file types
grep -rn '\$state\|\$derived\|\$props' src/ --include='*.ts' --include='*.js' \
| grep -v '\.svelte\.' || true
# These only work in .svelte / .svelte.ts / .svelte.js files
Flag any runes used outside `.svelte*` files — they're silently broken.
---
STEP 4 — Postgres / Supabase Hygiene (if applicable)
Only for projects with a database. Read-only checks — never modify schema without explicit approval.
# If Supabase CLI is installed
supabase db lint 2>/dev/null || echo "supabase CLI not available"
# Unused indexes (via any PG client the project uses)
# Report only — do NOT drop indexes automatically
Queries to run manually (report results, don't act):
-- Unused indexes (never scanned)
SELECT schemaname, relname AS table, indexrelname AS index, idx_scan
FROM pg_stat_user_
Read more
argument-hint: [--safe-only | --dry-run]
/jat:hygiene - Code Hygiene Pass
Manual cleanup of dead code, broken type refs, stale config, and schema cruft. Works on TypeScript/Svelte projects, with optional Postgres/Supabase checks. Tailored for the JST stack.
**Use this when:** The user wants a hygiene/cleanup pass, or periodic tech-debt grooming.
**Flags:**
- `--safe-only` — Apply only auto-safe fixes (JSDoc, stale config, dead ts-ignores). Skip all deletion steps.
- `--dry-run` — Report findings without modifying any files.
**This is NOT for:** Linting/formatting (that's `prettier`/`eslint`), or refactoring.
---
Philosophy
Dead-code tools (knip, ts-prune) produce **candidates, not verdicts.** Every file/dep they flag needs human judgment because of these blind spots:
- Dynamic string imports (`target: 'pino-pretty'`)
- Build-time config refs (`vite.config.ts`, static copies)
- HTML `<script>` tag refs (`app.html`, `static/*.html`)
- Svelte dynamic components (`<svelte:component this={...}>`)
- Test fixtures / e2e harnesses outside source tree
- Type-only exports consumed externally
**Rule:** Apply safe fixes automatically. Verify every deletion candidate by hand.
---
STEP 0 — Stack Detection
Before starting, detect what applies to this project:
# Is there a frontend (Svelte/TS)? test -f package.json && echo "has-node" test -d src && ls src/**/*.svelte 2>/dev/null | head -1 && echo "has-svelte" grep -l "typescript" package.json 2>/dev/null && echo "has-ts" # Is there a database? test -d supabase && echo "has-supabase" test -d migrations && echo "has-migrations" grep -l '"pg"\|"postgres"\|@supabase' package.json 2>/dev/null && echo "has-pg-client" # Is this a SvelteKit app? test -f svelte.config.js && echo "has-sveltekit"
Announce what you detected and skip irrelevant steps.
---
STEP 1 — Safe Auto-Fixes (always run, never ask)
These are pure wins with no behavioral risk. Apply them silently, then mention the total in the report.
1a. Broken JSDoc Type Imports
Find `@type` / `@typedef` / `@param` blocks importing nonexistent files:
# If svelte-check is available, use it
npx svelte-check --output machine 2>&1 | grep -i "cannot find module" || true
# Otherwise grep for JSDoc imports and verify each path
grep -rn "import('\./" src/ --include='*.js' --include='*.ts' --include='*.svelte' | \
grep -oP "import\('[^']+'" | sort -uFor each broken ref:
- If the correct path is obvious (file was moved, import path wrong), fix it
- Otherwise replace with `any` — JSDoc is non-runtime, this is safe
1b. Stale Build Config
Check that every package referenced in build config actually exists in `package.json`:
# Grep for package names in build files grep -oE "'[a-z0-9@/-]+'" vite.config.ts svelte.config.js 2>/dev/null | sort -u
Remove stale refs in:
- `vite.config.ts` — `ssr.external`, `optimizeDeps.include`, `rollupOptions.external`, `resolve.alias`
- `svelte.config.js` — `kit.alias`, preprocessor plugins
- `tsconfig.json` — `paths`, `types` arrays pointing at deleted `@types/*`
1c. Dead TS-Ignore Comments
# Run tsc and look for "unused @ts-expect-error" errors npx tsc --noEmit 2>&1 | grep "unused" || true
Remove every `// @ts-expect-error` / `// @ts-ignore` that TypeScript reports as unused.
---
STEP 2 — Knip Scan + Manual Review
Only run if `--safe-only` was not passed.
# Make sure knip is available npx knip --no-progress 2>&1 | tee /tmp/knip-report.txt
Classify findings into these buckets. **Do not delete anything yet.**
Bucket A: Unused Files
For each flagged file, run these checks before deleting:
# 1. Is it referenced anywhere by basename? (catches dynamic imports, HTML refs) git grep -F "$(basename FILE .svelte)" # 2. Is it referenced by relative path? (catches partial matches) git grep -F "FILE_PATH" # 3. Is it a SvelteKit convention file? (+page, +layout, +server, +error) # If yes → KEEP. knip should know but sometimes misses. # 4. Is it in static/ and loaded from HTML? grep -r "FILENAME" static/*.html src/app.html 2>/dev/null
**Decision:**
- 0 hits outside itself → candidate for deletion
- Any hit → investigate, likely a false positive
Bucket B: Unused Dependencies
For each flagged package, two false-positive patterns to check:
# 1. Dynamic string imports (pino-pretty trap) git grep -F "'PACKAGE_NAME'" git grep -F "\"PACKAGE_NAME\"" # 2. Build-time usage git grep -F "PACKAGE_NAME" vite.config.ts svelte.config.js scripts/ package.json
If either returns a hit, **keep** the dep and note why.
Bucket C: Unused Exports / Types (LOW priority)
Skip unless the user explicitly asks. These have high churn risk and low cleanup value. Unused type exports in particular are cheap to keep and annoying if wrong.
**Exception:** Duplicate exports (same symbol exported twice) — usually safe to consolidate.
---
STEP 3 — Svelte-Specific Checks
Only for projects with `.svelte` files.
# svelte-check should report zero new errors (or only known baseline) npx svelte-check 2>&1 | tail -20 # Look for runes used in wrong file types grep -rn '\$state\|\$derived\|\$props' src/ --include='*.ts' --include='*.js' \ | grep -v '\.svelte\.' || true # These only work in .svelte / .svelte.ts / .svelte.js files
Flag any runes used outside `.svelte*` files — they're silently broken.
---
STEP 4 — Postgres / Supabase Hygiene (if applicable)
Only for projects with a database. Read-only checks — never modify schema without explicit approval.
# If Supabase CLI is installed supabase db lint 2>/dev/null || echo "supabase CLI not available" # Unused indexes (via any PG client the project uses) # Report only — do NOT drop indexes automatically
Queries to run manually (report results, don't act):
-- Unused indexes (never scanned) SELECT schemaname, relname AS table, indexrelname AS index, idx_scan FROM pg_stat_user_
Agents ship, suggest, repeat. You supervise — or they run on their own. JAT is the complete, self-contained environment for agentic development. Task management, agent orchestration, code editor, git integration, terminal access—all unified in a single IDE.
Repo: joewinke/jat
Other commands on jat.
- /adapt
/home/jw/code/jat/.agents/skills/adapt//SKILL.md
Open command - /animate
/home/jw/code/jat/.agents/skills/animate//SKILL.md
Open command - /arrange
/home/jw/code/jat/.agents/skills/arrange//SKILL.md
Open command - /audit
Runs the multi-agent fan-out + adversarial-verify audit pattern that produced `ide/docs/internal/optimization-audit-2026-06.md` — codified as a reusable, parameterizable Workflow (`.claude/workflows/forensic-audit.js`), so it no longer has to be re-derived by hand each time.
Open command - /bolder
/home/jw/code/jat/.agents/skills/bolder//SKILL.md
Open command - /clarify
/home/jw/code/jat/.agents/skills/clarify//SKILL.md
Open command

