---
name: dynamic-skill-loader
description: "Auto-detects the current project's technology stack and hot-loads context-appropriate skills at session start using Claude Code's SessionStart hook with reloadSkills: true. Detects Node.js/TypeScript, Next.js, Python, Rust, Go, Ruby, and monorepo layouts. Emits a .claude/dynamic-context.md with the detected stack and recommended skill list, then signals Claude Code to reload skills before the first agent turn."
version: "1.0.0"
category: productivity
platforms:
  - CLAUDE_CODE
---

You are a session-configuration agent. Your job is to auto-detect the current project's technology stack and write a Claude Code SessionStart hook that hot-loads the right skills for each project automatically.

Do NOT ask the user what stack they use. Detect it from files. Do NOT install skills the project does not need.

TARGET PROJECT:
$ARGUMENTS

============================================================
PHASE 1: STACK DETECTION
============================================================

Scan the working directory root for the following markers, in priority order:

1. **Next.js**: `next.config.ts`, `next.config.js`, or `next.config.mjs` present → `nextjs`
2. **React SPA**: `package.json` with `"react"` in dependencies but no `next` → `react`
3. **Node.js / TypeScript**: `package.json` present, no frontend framework → `node`
4. **Python**: `pyproject.toml`, `requirements.txt`, or `setup.py` → `python`
5. **Rust**: `Cargo.toml` → `rust`
6. **Go**: `go.mod` → `go`
7. **Ruby on Rails**: `Gemfile` with `rails` → `rails`
8. **Monorepo**: `pnpm-workspace.yaml`, `nx.json`, `turbo.json`, or `lerna.json` → `monorepo`
9. **Fallback**: `generic`

For monorepos, also check the `apps/` and `packages/` subdirectories to determine the primary framework (Next.js monorepo, etc.).

Report the detected stack and the list of markers found. If multiple stacks are detected, report all and pick the most specific one.

============================================================
PHASE 2: WRITE HOOK + DYNAMIC CONTEXT
============================================================

Create or update two files:

**File 1: `.claude/hooks/session-start.sh`**

Write a POSIX-compatible shell script that:
1. Detects the stack using the same markers from Phase 1
2. Builds a skill list appropriate for that stack (see mapping below)
3. Writes `.claude/dynamic-context.md` with the detected stack and skill list
4. Outputs `{"reloadSkills": true}` to stdout so Claude Code reloads skills immediately

Stack-to-skills mapping:
- `nextjs`  → `nextjs-conventions, code-review, seo, security/owasp-audit`
- `react`   → `react-conventions, code-review, security/owasp-audit`
- `node`    → `node-conventions, code-review, security/owasp-audit`
- `python`  → `python-conventions, code-review, security/owasp-audit`
- `rust`    → `rust-conventions, code-review`
- `go`      → `go-conventions, code-review`
- `rails`   → `rails-conventions, code-review, security/owasp-audit`
- `monorepo`→ `monorepo-conventions, code-review, security/owasp-audit`
- `generic` → `code-review`

Make the script executable. If `.claude/hooks/` does not exist, create it.

Example output for a Next.js project:

```bash
#!/bin/bash
# Auto-generated by dynamic-skill-loader. Do not edit by hand.

STACK="generic"
[ -f "next.config.ts" ] || [ -f "next.config.js" ] || [ -f "next.config.mjs" ] && STACK="nextjs"
# ... (full detection logic)

case "$STACK" in
  nextjs)  SKILLS="nextjs-conventions, code-review, seo, security/owasp-audit" ;;
  node)    SKILLS="node-conventions, code-review, security/owasp-audit" ;;
  python)  SKILLS="python-conventions, code-review, security/owasp-audit" ;;
  rust)    SKILLS="rust-conventions, code-review" ;;
  go)      SKILLS="go-conventions, code-review" ;;
  rails)   SKILLS="rails-conventions, code-review, security/owasp-audit" ;;
  *)       SKILLS="code-review" ;;
esac

mkdir -p .claude
cat > .claude/dynamic-context.md <<EOF
# Auto-generated project context
# Generated by dynamic-skill-loader on $(date -u +"%Y-%m-%d")
Stack: $STACK
Recommended skills: $SKILLS
EOF

echo '{"reloadSkills": true}'
```

**File 2: `.claude/dynamic-context.md`**

Write this file immediately (do not wait for the hook to run) so Claude Code has context in the current session too:

```markdown
# Auto-generated project context
Stack: <detected-stack>
Recommended skills: <skill-list>
```

============================================================
PHASE 3: WIRE THE HOOK IN SETTINGS
============================================================

Check if `.claude/settings.json` exists.

- If it exists, read it and add the SessionStart hook entry to the `hooks` array. Do not overwrite other hooks already registered.
- If it does not exist, create it with the following structure:

```json
{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/session-start.sh"
          }
        ]
      }
    ]
  }
}
```

If `hooks.SessionStart` already contains an entry pointing to a different session-start hook, add the dynamic-skill-loader as a second entry — do not remove existing hooks.

============================================================
PHASE 4: VERIFY + REPORT
============================================================

1. Verify the hook file exists and is executable: `ls -la .claude/hooks/session-start.sh`
2. Dry-run the hook: `bash .claude/hooks/session-start.sh` and confirm it outputs valid JSON
3. Verify `.claude/dynamic-context.md` was written
4. Verify `.claude/settings.json` contains the SessionStart hook entry

Report:

```
DYNAMIC-SKILL-LOADER SETUP REPORT

Project root: <path>
Stack detected: <stack>
Detection markers: <files that triggered the detection>
Skills configured: <list>

Files written:
  ✓ .claude/hooks/session-start.sh (executable)
  ✓ .claude/dynamic-context.md
  ✓ .claude/settings.json (hook registered)

Hook dry-run output: {"reloadSkills": true}

Next steps:
  - Start a new Claude Code session — skills will auto-load for this stack
  - To reload mid-session: /reload-skills
  - To update the stack mapping, edit .claude/hooks/session-start.sh
```

============================================================
STRICT RULES
============================================================

- Never ask "what framework are you using?" — detect from files.
- Never overwrite an existing SessionStart hook without first reading it.
- The hook script must be POSIX sh compatible (no bash-isms beyond `[[ ]]`).
- The hook must always output valid JSON. If detection fails, output `{}` (not `{"reloadSkills": true}`).
- Keep the dynamic-context.md concise — it is injected into every session start.
