---
name: auto-configure-project
description: Use when setting up Claude Code configuration for a new or existing project, OR when invoked by the SessionStart hook because the project lacks `.claude/settings.json`. Detects the tech stack and proposes a `.claude/settings.json` that re-enables the plugins the project actually needs (the global default keeps almost everything off).
---

# Auto-Configure Project

The global `~/.claude/settings.json` keeps the plugin set **lean** — only universal plugins (memory, code review, commit, security, hookify, context7, superpowers, etc.) are on by default. Stack-specific plugins (Python, Terraform, FastAPI, GitHub/GitLab, AWS, Atlassian, Slack, Playwright, Serena, language LSPs) are **off** and must be re-enabled per project.

This skill detects the stack and writes the right per-project re-enables to `.claude/settings.json`.

## When this skill runs

1. **Automatically** — a SessionStart hook (`~/.claude/hooks/auto-configure-check.sh`) injects a system reminder telling Claude to invoke this skill whenever the cwd is a git repo with no `.claude/settings.json`. Skip behavior:
   - cwd has no `.git/` → skip (not a project)
   - cwd is `~/.claude` or the dotfiles repo target → skip (global config IS the project config)
   - `.claude/.no-auto-configure` exists → skip (user opted out)
2. **Manually** — user runs `/auto-configure-project` to re-tune an existing config.

## Workflow (mandatory order)

1. Detect the stack (Step 1).
2. Build a proposal mapping detected signals → plugins to re-enable (Step 2).
3. **Show the proposal to the user and ASK** before writing (Step 3). Never silently write `.claude/settings.json`.
4. On confirmation, write the file (Step 4).
5. Report what was done (Step 5).

If the user declines, offer to write `.claude/.no-auto-configure` so future sessions stop prompting.

## Step 1 — Detect the stack

Run these checks (in parallel where possible):

```bash
# Languages / frameworks
ls *.py pyproject.toml requirements*.txt setup.py setup.cfg 2>/dev/null
ls *.tf *.tfvars terraform.* 2>/dev/null
ls dbt_project.yml 2>/dev/null
ls package.json tsconfig.json 2>/dev/null
ls *.go go.mod 2>/dev/null
ls Gemfile *.rb 2>/dev/null
ls *.swift Package.swift *.xcodeproj 2>/dev/null
ls *.c *.cpp *.h compile_commands.json 2>/dev/null

# Dependency hints
grep -r "fastapi\|flask\|django" requirements*.txt pyproject.toml 2>/dev/null | head -5
grep -r "psycopg\|asyncpg\|sqlalchemy\|alembic\|timescaledb" requirements*.txt pyproject.toml 2>/dev/null | head -5
grep -r "playwright\|selenium\|cypress" requirements*.txt package.json pyproject.toml 2>/dev/null | head -5
grep -r "pytest\|unittest" requirements*.txt pyproject.toml 2>/dev/null | head -5
grep -r "boto3\|aws-cdk\|aws-sdk" requirements*.txt pyproject.toml package.json 2>/dev/null | head -5

# Git remote (drives github/gitlab choice)
git remote get-url origin 2>/dev/null

# Repo size (serena threshold)
find . -name "*.py" -o -name "*.ts" -o -name "*.go" -o -name "*.swift" 2>/dev/null | wc -l

# CI/CD hints
ls .github/workflows/ .gitlab-ci.yml .circleci/ 2>/dev/null

# Infra hints
ls Dockerfile docker-compose*.yml 2>/dev/null
ls .glue/ glue_jobs/ 2>/dev/null

# Atlassian / Slack / Jira hints
grep -ri "JIRA_\|CONFLUENCE_\|ATLASSIAN_" .env* 2>/dev/null | head -3
grep -ri "SLACK_TOKEN\|SLACK_BOT_TOKEN" .env* 2>/dev/null | head -3
```

## Step 2 — Map signals to re-enables

The global default has **only these on**: `claude-mem`, `code-review`, `code-simplifier`, `commit-commands`, `security-guidance`, `claude-code-setup`, `pr-review-toolkit`, `superpowers`, `claude-md-management`, `context7`, `hookify`. Everything else needs an explicit `true` in the project config.

### Conditional re-enables

| Detected signal | Re-enable |
| --- | --- |
| `*.py`, `pyproject.toml`, `requirements*.txt` | `python@python-backend-plugins`, `astral@astral-sh` |
| `fastapi` or `flask` or `django` in deps | `fastapi@python-backend-plugins`, `tech-lead@python-backend-plugins` |
| `*.tf` or `*.tfvars` | `terraform-code-generation@hashicorp`, `terraform-module-generation@hashicorp`, `terraform-skill@antonbabenko` |
| `psycopg`, `asyncpg`, `sqlalchemy`, `timescaledb` in deps | `pg@aiguide` |
| `playwright`, `selenium`, `cypress` in deps | `playwright@claude-plugins-official` |
| `dbt_project.yml` | `python@python-backend-plugins`, `astral@astral-sh` |
| Git remote contains `gitlab` | `gitlab@claude-plugins-official` |
| Git remote contains `github` OR `.github/` directory exists | `github@claude-plugins-official` |
| Jira/Confluence env vars or `.atlassian` config | `atlassian@claude-plugins-official` |
| `SLACK_TOKEN` in env or Slack usage | `slack@claude-plugins-official` |
| >100 source files | `serena@claude-plugins-official` |
| `Dockerfile`, `docker-compose`, CI pipelines | `ci-cd@devops-skills` |
| `boto3`, AWS Glue jobs, AWS-CDK, AWS service usage | `aws-cost-optimization@devops-skills` |
| Non-trivial feature work expected | `feature-dev@claude-plugins-official` |
| `*.swift`, `Package.swift`, `*.xcodeproj` | `swift-lsp@claude-plugins-official` |
| `*.c`, `*.cpp`, `*.h`, `compile_commands.json` | `clangd-lsp@claude-plugins-official` |
| Python project where strict type-checking is wanted | `pyright-lsp@claude-plugins-official` (only when ruff isn't enough) |

### Ambiguous signals

If a signal is borderline (e.g. only one `.py` file in an otherwise non-Python repo), mention it in the proposal as a question rather than auto-including it.

## Step 3 — Propose, then ask

Output a compact summary like this and **stop for user confirmation**:

```text
Detected stack: Python (uv, ruff), PostgreSQL, GitLab remote, 47 source files

Proposed `.claude/settings.json`:
{
  "enabledPlugins": {
    "python@python-backend-plugins": true,
    "astral@astral-sh": true,
    "pg@aiguide": true,
    "gitlab@claude-plugins-official": true
  }
}

Write this file? (y/n, or tell me what to add/remove)
```

Do not write the file until the user agrees (or asks for changes).

## Step 4 — Write the config

On confirmation, write `.claude/settings.json`. If the file already exists (e.g. user ran `/auto-configure-project` manually to re-tune), **merge** rather than overwrite — preserve any keys the user added (env, permissions, hooks) and only update `enabledPlugins`.

Only emit entries that **differ from the global default**:

- Re-enable: `"plugin@marketplace": true` for things the global has off but the project needs.
- Disable: `"plugin@marketplace": false` for the rare case a globally-on plugin should be off here.

Do not redundantly list plugins that already match the global state.

## Step 5 — Report

Tell the user, in this order:

1. Stack signals detected (one line)
2. Plugins re-enabled and why (one line each)
3. Plugins NOT re-enabled despite weak signal, and why (so they can override)
4. Path to the file written
5. **Mandatory final block** — emit this verbatim, as the LAST thing in the response, so the user can't miss it:

```text
⚠️  RESTART REQUIRED

The new plugins won't load until Claude Code is restarted.
Please exit this session  (Ctrl+D, /exit, or close the window) and relaunch.
The new plugins and skills will then be available in the next session.
```

After the restart block, optionally remind: edit `.claude/settings.json` directly to tweak later, or create `.claude/.no-auto-configure` to suppress the SessionStart prompt for this project.

## Notes

- `.claude/settings.json` is safe to commit — no secrets, benefits collaborators who clone the repo.
- If `.claude/settings.local.json` exists, leave it untouched (it's machine-specific overrides).
- MCP servers from re-enabled plugins activate automatically.
- The global default list of always-on plugins evolves. Re-read `~/.claude/settings.json` at the start of each invocation — don't trust the list cached in this skill.
