From pragma
Configure Claude Code for this project - detects languages and sets up rules, skills, and validators
npx claudepluginhub peteski22/agent-pragma --plugin pragmaThis skill is limited to using the following tools:
Automatically configure Claude Code for the current project. Supports monorepos with multiple languages in subdirectories.
Bootstraps .claude/ dotclaude config from template if missing, then customizes all files to match project's tech stack, conventions, and patterns. Interactive via user confirmations.
Initializes Claude Code projects by auto-detecting Node.js frameworks from package.json and lockfiles, replaces CLAUDE.md placeholders, installs rules, hooks, and scripts.
Generates project-specific CLAUDE.md rules by detecting stack from package.json, Cargo.toml, pyproject.toml, go.mod, git log, and user-selecting categories like response format, library preference, code review stance. Use for new projects, repo onboarding, or establishing conventions.
Share bugs, ideas, or general feedback.
Automatically configure Claude Code for the current project. Supports monorepos with multiple languages in subdirectories.
The skill loader provides the base directory in the header: Base directory for this skill: <path>. Derive the plugin root from that:
PLUGIN_ROOT = <base directory>/../../
For example, if the skill base directory is ~/.claude/plugins/cache/pragma/skills/setup-project, then PLUGIN_ROOT is ~/.claude/plugins/cache/pragma.
Verify the plugin root is valid by checking for the plugin manifest:
PLUGIN_ROOT="<base directory>/../.."
[[ -f "$PLUGIN_ROOT/.claude-plugin/plugin.json" ]] && echo "OK" || echo "ERROR: Plugin root invalid - .claude-plugin/plugin.json not found at $PLUGIN_ROOT"
true
Note: Replace <base directory> with the actual path from the skill loader header above. For example, if the header says Base directory for this skill: /home/user/.claude/plugins/cache/pragma/skills/setup-project, then PLUGIN_ROOT="/home/user/.claude/plugins/cache/pragma/skills/setup-project/../..".
If the check fails, stop and show:
Plugin root could not be resolved. The pragma plugin may not be installed correctly.
Reinstall:
/plugin marketplace add peteski22/agent-pragma
/plugin install pragma@agent-pragma
STOP if check fails. Do not proceed.
Get org and repo name from git remote:
git remote get-url origin 2>/dev/null | sed -E 's|.*[:/]([^/]+)/([^/]+)(\.git)?$|\1 \2|'
Store {org} and {repo} for templating.
Check root directory AND immediate subdirectories for language markers.
# Root level
[[ -f go.mod ]] && echo "root:go"
( [[ -f pyproject.toml ]] || [[ -f setup.py ]] ) && echo "root:python"
[[ -f package.json ]] && echo "root:javascript"
[[ -f tsconfig.json ]] && echo "root:typescript"
[[ -f Cargo.toml ]] && echo "root:rust"
# Subdirectories (one level deep)
for dir in */; do
[[ -f "${dir}go.mod" ]] && echo "${dir%/}:go"
( [[ -f "${dir}pyproject.toml" ]] || [[ -f "${dir}setup.py" ]] ) && echo "${dir%/}:python"
[[ -f "${dir}package.json" ]] && echo "${dir%/}:javascript"
[[ -f "${dir}tsconfig.json" ]] && echo "${dir%/}:typescript"
[[ -f "${dir}Cargo.toml" ]] && echo "${dir%/}:rust"
done
true
This produces output like:
root:go (single-language project)backend:python, frontend:typescript (monorepo)Check for rule files generated by a previous run:
[[ -d .claude/rules ]] && ls .claude/rules/*.md 2>/dev/null | while read -r f; do echo "rules:$f"; done
true
If any exist, read them. If they have <!-- Assembled by /setup-project comment, safe to overwrite. Otherwise, ask before overwriting.
.claude/CLAUDE.md filesCheck for old-style assembled CLAUDE.md files from previous versions of /setup-project:
for f in .claude/CLAUDE.md */.claude/CLAUDE.md; do
[[ -f "$f" ]] && echo "legacy:$f"
done
true
If any are found, read them. If they contain the <!-- Assembled by /setup-project marker, delete them — the new modular rules in .claude/rules/ replace them. If they do not contain the marker (user-authored), warn the user and ask before removing.
Create the directory:
mkdir -p .claude/rules
Generate modular rule files. Each file is standalone with its own header comment.
Write .claude/rules/universal.md with:
$PLUGIN_ROOT/claude-md/universal/base.mdHeader:
<!-- Assembled by /setup-project from agent-pragma -->
<!-- Org/Repo: {org}/{repo} -->
<!-- Re-run /setup-project to regenerate -->
Write .claude/rules/local-supplements.md with content describing how CLAUDE.local.md works:
Header:
<!-- Assembled by /setup-project from agent-pragma -->
<!-- Re-run /setup-project to regenerate -->
Content:
<!-- This file is documentation only. It does not contain executable validation commands. -->
<!-- Validators: skip this file when searching for "Validation Commands" sections. -->
## Local Supplements
`CLAUDE.local.md` at the project root contains per-user, per-project instructions. Claude Code auto-loads it and adds it to `.gitignore`; if you create the file manually, verify it is in your `.gitignore`.
### Validation Command Overrides
Rules from `CLAUDE.local.md` are generally additive, but can override validation commands. Add a "Validation Commands" section to `CLAUDE.local.md` to specify custom lint/test scripts:
```markdown
## Validation Commands
- **Lint:** `./scripts/backend-lint.sh`
- **Test:** `./scripts/backend-test.sh`
```
These override the defaults in the language rules. Precedence (highest → lowest): CLAUDE.local.md > path-scoped rules > universal rules > built-in defaults.
**Common scenarios for overriding validation commands:**
- **Wrapper scripts:** Your project has `./scripts/lint.sh` that runs multiple tools (ruff + mypy + security scans) in sequence
- **Tool versioning:** Use a specific linter version not available in the default environment
- **Integration tests:** Run integration tests as part of the validation process before commits
- **Security scanning:** Add custom vulnerability checks (e.g., `bandit`, `semgrep`) before commits
- **CI/CD parity:** Match the exact validation commands used in your CI pipeline
- **Monorepo isolation:** Different validation commands for different subdirectories
### Other Uses
- Custom environment setup notes.
- Personal workflow preferences.
- Machine-specific paths or configurations.
In git worktrees, use `@import` (a Claude Code directive that includes another CLAUDE.md file) in `CLAUDE.local.md` to reference a shared local rules file rather than duplicating it per worktree (e.g., `@import ../shared-local-rules.md`).
Create local supplements file and ensure it is gitignored:
test -f CLAUDE.local.md || touch CLAUDE.local.md
grep -qxF 'CLAUDE.local.md' .gitignore 2>/dev/null || echo 'CLAUDE.local.md' >> .gitignore
For each detected language (whether at root or in a subdirectory), create a path-scoped rule file in .claude/rules/.
File naming: .claude/rules/{lang}.md (e.g., go.md, python.md, typescript.md).
Always add paths frontmatter to scope language rules to matching file extensions. This prevents language-specific rules from applying to unrelated files (e.g., Go rules applying to .py files when both languages are detected at root).
If the language was detected at root (e.g., root:go), scope to the extension at the repo root:
---
paths:
- "**/*.go"
---
If the language was detected in a subdirectory (e.g., backend:python), scope to the subdirectory and extension:
---
paths:
- "backend/**/*.py"
---
If the same language appears at root and in subdirectories, or in multiple subdirectories, combine the paths:
---
paths:
- "backend/**/*.py"
- "scripts/**/*.py"
---
File extension mapping:
go → *.gopython → *.pytypescript → *.ts and *.tsx (use two separate paths entries, not brace expansion)javascript → *.js and *.jsx (use two separate paths entries, not brace expansion)rust → *.rsAssemble each language rule file with:
$PLUGIN_ROOT/claude-md/languages/{lang}/{lang}.mdHeader:
<!-- Assembled by /setup-project from agent-pragma -->
<!-- Language: {lang} -->
<!-- Re-run /setup-project to regenerate -->
OpenCode uses opencode.json at the project root to load custom instructions. Create or update this file so OpenCode auto-loads the same .claude/rules/*.md files that Claude Code loads natively.
Check for existing opencode.json:
test -f opencode.json && echo "opencode-json:exists" || echo "opencode-json:missing"
If missing, create it:
{
"$schema": "https://opencode.ai/config.json",
"instructions": [".claude/rules/*.md"]
}
If it exists, read it and merge the instructions field:
opencode.json.bak and create a fresh opencode.json with the content above. Inform the user that the original was backed up.instructions already contains .claude/rules/*.md: No changes needed.instructions exists and is an array but does not contain .claude/rules/*.md: Append .claude/rules/*.md to the existing array.instructions exists but is not an array (e.g., a string): Convert it to an array containing the original value plus .claude/rules/*.md.instructions field is missing: Add it with [".claude/rules/*.md"].Do not overwrite other fields in an existing opencode.json (e.g., model, provider, agent).
All skills and agents are provided by the pragma plugin — no symlinks needed.
Check star-chamber prerequisites:
command -v uv >/dev/null 2>&1 && echo "uv:ok" || echo "uv:missing"
Store the result - if uv:missing, include a warning in Step 9 output.
Build go-structural (ONLY if Go was detected in Step 2):
Skip this entirely if no go language was detected in Step 2 output (e.g. if the only output was root:python, there is no Go — do not build go-structural).
If and only if Go was detected (any line matching *:go in Step 2 output):
cd "$PLUGIN_ROOT/tools/go-structural" && go build -o go-structural . && echo "go-structural:ok" || echo "go-structural:build-failed"
If go is not available or the build fails, note in Step 9 output that go-structural is unavailable.
For each language detected in Step 2, read $PLUGIN_ROOT/claude-md/languages/{lang}/setup.md if it exists. This file defines:
$PLUGIN_ROOT).For each language that has a setup.md:
.eslintrc.*, .prettierrc*).$PLUGIN_ROOT/<path>, replacing {org} and {repo} template variables with values from Step 1.Skip languages that have no setup.md file.
## Setup Complete
**Project:** {org}/{repo}
**Structure detected:**
- Root: [languages or "none"]
- backend/: Python
- frontend/: TypeScript
**Created:**
- .claude/rules/universal.md
- .claude/rules/local-supplements.md
- .claude/rules/python.md (scoped to backend/**)
- .claude/rules/typescript.md (scoped to frontend/**)
- opencode.json (OpenCode instructions — loads .claude/rules/*.md)
**Skills available (via pragma plugin):**
- /implement - implement with auto-validation
- /review - review changes against all validators
- /validate - run all validators
- /star-chamber - multi-LLM advisory council
**Agents available (via pragma plugin):**
- security - auto-invokes on trust boundary changes
- star-chamber - auto-invokes on architectural decisions
**Usage:**
/implement <task> - implement with validation loop
/review - validate current changes
**Star-Chamber:** Run `/star-chamber` — first invocation launches interactive provider setup.
If uv is missing, include this warning:
⚠️ **Warning:** uv is not installed. /star-chamber requires uv to run.
Install uv:
curl -LsSf https://astral.sh/uv/install.sh | sh
Or see: https://docs.astral.sh/uv/getting-started/installation/
Then continue with:
**Recommended:**
- **Optional:** If you want other contributors to benefit from the same rules, commit the generated `.claude/rules/` files. Otherwise, add `.claude/rules/` to `.gitignore` to keep them local.
- `CLAUDE.local.md` has been created for personal/machine-specific rules (custom validation commands, local environment notes, personal workflow preferences). It is auto-loaded by Claude Code and gitignored.