| name | rackup |
| description | Generates a production-ready AGENTS.md and complete .claude/ setup through guided codebase discovery and targeted interview. Detects the user's global setup, the project's filesystem, and installed tooling — then asks the user to confirm rather than assuming. Creates skills, hooks, settings, and symlinks tailored to the project. Use when setting up a new project for AI-assisted development or updating an existing setup.
|
| user-invocable | true |
| disable-model-invocation | true |
| argument-hint | [--quick | --update | --audit | --help] |
/rackup — Intelligent AGENTS.md Generator
Generate a production-ready AGENTS.md with full tooling setup through guided discovery.
MISSION
Create the optimal AI agent instruction file for this project by:
- Analyzing the codebase automatically (via parallel subagents)
- Scanning the user's global
~/.claude/ setup and the project's existing .claude/ directory
- Asking targeted questions to fill gaps
- Generating AGENTS.md + symlinks + skills + hooks + settings
Output: A complete .claude/ setup — AGENTS.md, skills, hooks, and config — that makes AI assistants effective from the first prompt.
Why AGENTS.md?: Agent-agnostic source of truth. Claude Code, Cursor, Windsurf, Copilot, Aider, Cline all read from symlinks pointing to one file.
Self-contained: Rackup generates everything from scratch per project. Every skill, hook, and config is created fresh — no dependency on the user's global ~/.claude/ skills.
CORE PRINCIPLE: DETECT, DON'T ASSUME
Rackup never hardcodes a preferred ecosystem. Before asking any tooling question:
- Inspect the user's global setup —
~/.claude/skills/, ~/.claude/plugins/, ~/.claude/settings.json, ~/.claude/CLAUDE.md, and any memory files under ~/.claude/projects/*/memory/.
- Inspect the project filesystem — config files, lockfiles, manifest files across all ecosystems (node, deno, bun, python, rust, go, php, ruby, elixir, jvm).
- Inspect installed binaries —
command -v for tools that might be relevant but not wired in.
- Then ask the user — always confirm, often with pre-filled defaults from the detection above.
Every generated script, hook, and skill body uses detected tools. The templates in this document are illustrative — real output adapts to what was found.
PHASE 1: DISCOVERY
Launch 3 subagents in parallel using the Agent tool with subagent_type: Explore. Send all three in a single message so they run concurrently.
The full prompt for each subagent lives in a separate file — reference them one level deep:
- Agent 1 — Stack + Structure: see
subagents/01-stack-structure.md
- Agent 2 — Config/Tooling + Docs: see
subagents/02-config-docs.md
- Agent 3 — Git + Existing agent config + Active-agent detection: see
subagents/03-git-claude.md
Subagent 3 also identifies which AI agent is running the current rackup session (via env vars, install path, and project agent dirs) and which other Agent Skills-compatible agents the user has configured. This drives Group 12 (cross-agent skill distribution) in Phase 2.
After all three return, merge their findings into a single discovery summary to use in Phases 2 and 4.
PHASE 2: INTERVIEW
After discovery, ask targeted questions to fill gaps. Group by topic, skip groups where discovery gave clear answers. Prefer multi-select or yes/no questions with sensible defaults over open-ended prompts.
Group 1: Tech Stack (only if unclear from discovery)
- What framework version are you targeting?
- Any planned migrations?
Group 2: Architecture
- Describe your module/component organization pattern
- Any architectural decisions AI should respect?
- Any areas that should NOT be modified?
Group 3: Commands
- Dev workflow? (dev server, build, test, deploy)
- Any non-obvious scripts?
Group 4: Code Style
- What's NOT captured by your linter config?
- Naming conventions for files, components, functions?
- Import order preferences?
Group 5: Testing
- Testing framework and patterns (pre-fill from Subagent 2 findings)?
- Where do tests live? (co-located,
__tests__/, separate tests/)
- Any testing conventions (e.g., test naming)?
Group 6: Workflow
- Git branching strategy (pre-fill from Subagent 3)?
- Commit message format (pre-fill from Subagent 3)?
- PR process?
Group 7: Skills
Default skills (always generated): /learn, /commit, /add-feature.
Auto-invocation for /learn — ask with pros and cons:
"Auto-invoke /learn when the session starts, resumes, or after compact/clear?"
Pros: Claude orients faster in unfamiliar code; fewer 'where is X' detours.
Cons: extra tokens every session (can be significant on large codebases).
[Y/n, default Y]
The answer flips disable-model-invocation and decides whether to generate the SessionStart hook (Group 10).
Conditional skills — ask Y/n for each:
/review — code review of current changes
/lint — run linters per file type
/brainstorm — exploratory dialogue, one question at a time, 2–3 approaches with trade-offs (adapted from the brainstorm pattern in umputun/cc-thingz)
/clarify — explain actual behavior when the user is confused or has contradictory expectations
- Any custom skills the user names
Commit style: conventional commits? imperative mood? emoji? prefixes? (Pre-fill defaults from Subagent 3's analysis of recent commits.)
Group 8: Linters / Formatters (based on Subagent 2 detection)
For each detected tool, confirm:
- Is it active and how do you invoke it? (pre-fill the detected command)
- Should the lint-on-write hook auto-fix, or only report?
- Any file patterns to exclude?
If multiple linters exist for the same file type (e.g., both Biome and ESLint), ask which to prefer.
Group 9: Hooks
- Enable lint-on-write? (
PostToolUse: Write|Edit)
- Enable format-on-write? (merged with above when the tool supports both)
- Enable test-on-stop? (
Stop — run tests for changed files before finishing)
- Any custom hooks?
Group 10: SessionStart Hook
Only ask if the user answered Y to auto-invoking /learn in Group 7.
Ask which directories /learn should study on start (pre-fill from the source directories detected in Subagent 1 — e.g., src/, lib/, app/, packages/*).
Group 11: Symlinks — which AI tools do you use?
Multi-select. Each option shows the consuming tool name, not just the filename:
AGENTS.md is always the source of truth. Whatever the user picks, rackup creates symlinks from those targets to AGENTS.md.
Group 12: Cross-Agent Skill Distribution
Agent Skills is an open standard adopted by Claude Code, Cursor, Gemini CLI, OpenCode, OpenHands, Goose, Amp, OpenAI Codex, Factory, Kiro, Junie, Roo Code, Emdash, Mux, Firebender, Letta, and others. A skill written in the standard format can run under any of them if each agent's per-tool skills directory points at a shared source.
Rackup can either:
- Claude-only mode — generate skills directly into
.claude/skills/ (simpler, works only for Claude Code).
- Agent-agnostic mode — store skills in
.agents/skills/ and symlink each selected agent's skills/ directory to that source. The skills are authored once and read by every agent the user picks.
Default is chosen from Subagent 3's active-agent detection:
- If the active agent is Claude Code AND no other agent config dirs are found in the project or
~/ → default "No, Claude-only".
- If the active agent is non-Claude OR additional agent config dirs are detected → default "Yes, agent-agnostic".
Ask:
"Store skills in .agents/skills/ for cross-agent portability, or keep them in .claude/skills/ only?"
Default: <No, Claude-only | Yes, agent-agnostic> (from detection above)
If Yes, present a multi-select of agents to symlink. Pre-check any whose config directory was detected in the project or globally. Each option shows the consuming agent by name:
For each selected agent, rackup creates <agent-dir>/skills as a symlink to .agents/skills. If <agent-dir>/skills already exists and contains unrelated content, rackup asks before replacing it.
If No (Claude-only), rackup writes skills directly to .claude/skills/ with no .agents/ directory.
Group 13: Review / Annotation Tool (three-layer detection)
- Scan the user's
~/.claude/skills/, ~/.claude/plugins/, the project .claude/, and memory files for review tools (revdiff, git-review, planotator, etc.).
- If nothing found, check installed binaries —
command -v for known review CLIs.
- If anything is found, ask: "Wire
/review to invoke <detected-tool> for presentation? [Y/n]". If declined or nothing detected, generate a tool-agnostic /review that prints results inline.
No review tool is ever hardcoded in rackup or in generated skill bodies.
Group 14: Legacy Migration (conditional — only if Subagent 3 found legacy commands)
- Found N legacy commands in
.claude/commands/. Convert to skills format?
- For each, choose invocation mode:
- User-only (
disable-model-invocation: true, user-invocable: true)
- Claude-only (
disable-model-invocation: false, user-invocable: false)
- Both (
disable-model-invocation: false, user-invocable: true)
- Delete old
.claude/commands/ files after migration?
.claude/commands/*.md still works in current Claude Code, so migration is not mandatory — only recommended for consistency with skills-everywhere style.
PHASE 3: PLANNING
Present the full setup plan for approval before writing any files.
1. AGENTS.md Structure
1. Project Overview (2 lines)
2. Bash Commands (from Subagent 1)
3. Code Style (from config + interview)
4. Workflow (branching, commits, PR)
5. Testing (framework, patterns, location)
6. Critical Files (DO NOT MODIFY)
7. Anti-patterns (from observed patterns)
Target: concise, under 200 lines
2. Skills to Generate
| Skill | Type | Notes |
|---|
/learn | default | Auto-invoke per Group 7 answer; body tailored to detected project type |
/commit | default (user-only) | Matches user's detected commit style |
/add-feature | default (user-only) | Brainstorm-style dialogue: one question at a time, 2–3 approaches, section-by-section design |
/review | conditional | Tool-agnostic; wires to detected review tool if user opts in |
/lint | conditional | Uses detected linters/formatters |
/brainstorm | conditional | Standalone exploration dialogue (from cc-thingz) |
/clarify | conditional | Explain-first when user is confused (from cc-thingz) |
Mark each conditional row as confirmed / declined; remove declined.
3. Skill Directory & Cross-Agent Distribution (from Group 12)
Show the active-agent detection and the chosen distribution mode:
Active agent (from Phase 1 detection): <claude-code | cursor | ... | other>
Distribution mode: <Claude-only | Agent-agnostic>
Skill source: <.claude/skills/ | .agents/skills/>
Symlinks from: <list only if Agent-agnostic>
- .claude/skills → .agents/skills
- .cursor/skills → .agents/skills
- .gemini/skills → .agents/skills
- …
4. AGENTS.md Symlinks to Create
| Target file | Tool | Status |
|---|
CLAUDE.md | Claude Code | confirmed/declined |
.github/copilot-instructions.md | GitHub Copilot | confirmed/declined |
.cursorrules | Cursor | confirmed/declined |
| ... | ... | ... |
5. Hooks to Generate
| Event | Matcher | Action | Script | Status |
|---|
| PostToolUse | Write|Edit | Lint + format changed file (detected tools) | lint-format.sh | confirmed/declined |
| Stop | (all) | Run tests for changed files (detected runner) | test-changed.sh | confirmed/declined |
| SessionStart | startup|resume|compact|clear | Auto-learn key directories | learn-on-start.sh | confirmed/declined |
6. Legacy Migration (if applicable)
| Legacy Command | New Skill Name | Invocation Mode |
|---|
project__plan.md | /plan | user-only |
| ... | ... | ... |
Proceed? [Y/n]
PHASE 4: GENERATION
4.1 AGENTS.md (under 200 lines)
Rules:
- Be specific — exact commands and paths, not vague descriptions
- Be concise — target under 200 lines; trim redundancy aggressively
- Use emphasis —
IMPORTANT: or YOU MUST for critical rules
- Reference files —
@path/to/file instead of copying content
- Bullet points under markdown headers
- One line per item — no verbose explanations
- Challenge each token — only add context the model doesn't already have
4.2 Symlinks (interview-driven)
Create only the symlinks the user selected in Group 11. Template:
[confirmed_CLAUDE] && ln -sf AGENTS.md CLAUDE.md
[confirmed_COPILOT] && mkdir -p .github && ln -sf ../AGENTS.md .github/copilot-instructions.md
[confirmed_CURSOR] && ln -sf AGENTS.md .cursorrules
[confirmed_WINDSURF] && ln -sf AGENTS.md .windsurfrules
[confirmed_CONVENTIONS] && ln -sf AGENTS.md CONVENTIONS.md
4.3 settings.json
Generate .claude/settings.json with permissions for all generated skills and the hooks the user confirmed. Use explicit matcher strings so intent is visible.
{
"permissions": {
"allow": [
"Skill(learn)",
"Skill(commit)",
"Skill(add-feature)"
]
},
"hooks": {
"PostToolUse": [{
"matcher": "Write|Edit",
"hooks": [{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/lint-format.sh"
}]
}],
"Stop": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/test-changed.sh"
}]
}]
}
}
Expand permissions.allow to include every generated skill (including conditional ones the user confirmed).
If auto-invoke /learn was confirmed (Group 7 + Group 10), add:
{
"hooks": {
"SessionStart": [{
"matcher": "startup|resume|compact|clear",
"hooks": [{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/learn-on-start.sh"
}]
}]
}
}
4.4 Skill Directory & Cross-Agent Symlinks (from Group 12)
The skill source path is decided by Group 12:
Claude-only mode (default when the active agent is Claude Code and no other agent dirs were detected):
Write skills to: .claude/skills/<name>/SKILL.md
No .agents/ directory is created.
Agent-agnostic mode (default when a non-Claude active agent or multiple agents are detected):
mkdir -p .agents/skills
for agent_dir in .claude .cursor .gemini .opencode .openhands .goose .amp .codex .factory .kiro .junie .roo .emdash .mux .firebender .letta .autohand .workshop .ona .trae ; do
if [[ selected ]]; then
mkdir -p "$agent_dir"
if [[ -d "$agent_dir/skills" && ! -L "$agent_dir/skills" ]]; then
:
fi
ln -sfn "../.agents/skills" "$agent_dir/skills"
fi
done
Skills authored in .agents/skills/ use the portable Agent Skills format (name, description required; license, compatibility, metadata, allowed-tools optional). Claude Code-specific extras (user-invocable, disable-model-invocation, argument-hint) are added when Claude Code is among the target agents — other agents simply ignore unknown frontmatter fields.
Hooks and settings.json remain Claude Code-specific under .claude/ regardless of mode. The cross-agent symlinks apply to the skills/ directory only.
4.5 Skills
All skills use <skill_root>/<name>/SKILL.md where <skill_root> is either .claude/skills (Claude-only mode) or .agents/skills (agent-agnostic mode — symlinked from each selected agent's skills/ directory).
Conventions:
- Name: lowercase, hyphens only, max 64 chars, verb-based. Must match the parent directory name.
- Description: third person, includes "Use when…" trigger, max 1024 chars.
- Body: structured with headers and numbered steps.
- Progressive disclosure: keep SKILL.md focused; reference supporting files one level deep.
Optional frontmatter fields:
effort: high for /add-feature (plan-heavy work) — Claude Code extension
allowed-tools — per the AgentSkills spec, a space-separated list
model — rare, usually leave unset
license, compatibility, metadata — AgentSkills standard optional fields
Default: /learn (project-type aware)
Path: .claude/skills/learn/SKILL.md
Frontmatter: (the disable-model-invocation value comes from Group 7's answer)
---
name: learn
description: >
Studies existing code patterns, architecture, and conventions in the project.
Reads reference implementations and extracts patterns before writing new code.
Use when writing new code, entering an unfamiliar area, or starting a session.
user-invocable: true
disable-model-invocation: ${false_if_auto_invoke_else_true}
argument-hint: "[optional: area or pattern to study]"
---
Body (template — adapt tool commands and directories to detected project type):
# Learn Patterns
Study existing code to understand project patterns before writing anything new.
## Steps
### 1. Identify target area
If `$ARGUMENTS` is provided, focus on that area or pattern.
Otherwise, study the directories most relevant to the current task (suggested: ${detected_source_dirs}).
### 2. Find reference files
Find 3–5 recent, well-structured files in the target area.
Use the approach appropriate to the project runtime — e.g., `ls -lt <dir> | head -5`, or a language-native equivalent.
### 3. Read and analyze
Extract:
- Import ordering and grouping
- Naming conventions (files, functions, variables, components)
- Code structure and organization patterns
- Error handling approach
- Type usage and patterns (${detected_type_system_note})
- Test patterns (if test files found nearby)
### 4. Identify utilities and helpers
Look for shared utilities/hooks/helpers that should be reused (grep for the project's export idiom — e.g. `export function` for TS, `def` for Python, `pub fn` for Rust).
### 5. Summarize findings
Report:
- **Patterns to follow** — concrete examples from the code
- **Utilities to reuse** — specific imports and purpose
- **Conventions** — naming, structure, style rules observed
- **Anti-patterns** — things the codebase avoids
## Rules
- Read actual code, do not guess patterns
- Focus on the area relevant to the current task
- Be specific: "imports are grouped: react, external, internal, relative" beats "follow import conventions"
- Note deviations: flag when two files do things differently
${auto_invoke_token_note_if_enabled}
If auto-invoke is enabled, append this note at the bottom of the skill body:
Note: this skill auto-invokes on session start/resume/compact/clear. That adds tokens per session — disable via disable-model-invocation: true in frontmatter if cost matters more than orientation speed.
During generation, replace ${detected_source_dirs}, ${detected_type_system_note}, etc., with real values from Phase 1.
Default: /commit
Path: <skill_root>/commit/SKILL.md
Frontmatter:
---
name: commit
description: >
Prepares a git commit by analyzing staged changes and detecting commit
style from whatever signals the project actually has — user git
history, repo history, commit templates, and any commit-msg hook the
project has configured. Confirms with the user only when signals
conflict. Use when the user wants to commit changes or asks to prepare
a commit message.
user-invocable: true
disable-model-invocation: true
argument-hint: "[optional: what was done]"
---
Body:
# Commit Changes
Detect, don't assume. Inspect the repo's signals before writing anything.
## Steps
### 1. Check staged changes
Run `git status` and `git diff --cached`. If nothing is staged, tell the user to stage files first and stop — do not stage automatically.
### 2. Detect style signals (parallel)
- `git config user.name` — author identity
- `git log --author="$(git config user.name)" -5 --format="%B%n---%n"` — user's personal style
- `git log -10 --format="%s"` — repo's recent titles (convention check, fallback when user history is thin)
- `git config --get commit.template` — if set, read the template file
- Enforced conventions — probe for any of these, skip each that doesn't exist: ${detected_commit_hook_files}. Treat this list as examples, not requirements — swap in whatever the project uses
- `CONTRIBUTING.md` at repo root — if present, scan for a commit-message section
### 3. Analyze
From whichever signals were found, identify:
- **Title**: imperative vs past tense, capitalization, length cap, conventional commits (`feat:`, `fix:`), optional scope (`feat(auth):`)
- **Body**: present always / sometimes / never, "why" paragraph + bullet pattern
- **Bullets**: granularity (file-level change, behavior-level, high-level summary)
- **Trailers**: `Co-Authored-By`, `Signed-off-by`, `Refs #NNN` — include only if the user's recent commits or the repo template include them
- **Emoji / icon prefixes**: include only if the user's history shows them
If the user's personal style and an enforced convention conflict (e.g., user writes imperative titles but a commit-msg hook enforces conventional commits), favor the enforced convention and say which one was used and why.
### 4. Draft message
Match the detected style exactly — do not impose a different format. If `$ARGUMENTS` is provided, use it as context for the body.
### 5. Create the commit
Use a heredoc to preserve formatting:
\```bash
git commit -m "$(cat <<'EOF'
Title here
Body explaining why and what problem it solves.
- Specific change with detail
- Another specific change
EOF
)"
\```
If a commit-msg hook rejects the message, read the hook's feedback, adjust the message, and retry once — do not bypass with `--no-verify`.
## Rules
- Match the detected style exactly — do not impose a different format
- Title: imperative mood ("Add" not "Added"), under 50 chars, unless detected style differs
- Body: explain motivation and context, not just "what"
- Bullets: specific — include paths, identifiers, or behaviors
- NEVER add "Generated with Claude Code" or `Co-Authored-By` lines unless the user's recent commits or the repo template include them
- NEVER add emoji unless the user's history shows emoji usage
- If nothing is staged, tell the user and stop — do not stage files automatically
- If a commit-msg hook blocks the commit, fix the root cause; never bypass with `--no-verify`
During generation, replace ${detected_commit_hook_files} with the hook/config filenames actually found in Phase 1 (e.g., .husky/commit-msg, commitlint.config.js, .gitmessage) or drop the bullet entirely if none were detected.
Default: /add-feature (brainstorm-style dialogue)
Path: .claude/skills/add-feature/SKILL.md
Frontmatter:
---
name: add-feature
description: >
Implements a new feature using a dialogue-first workflow: researches codebase,
asks one question at a time to clarify, explores 2–3 approaches with trade-offs,
validates the chosen design section-by-section, then implements after approval.
Use when implementing new functionality or significant changes.
user-invocable: true
disable-model-invocation: true
argument-hint: "<feature description>"
effort: high
---
Body:
# Add Feature
Feature request: $ARGUMENTS
## Phase 1: Understand
- Read files, docs, and recent commits relevant to the request
- Find similar existing implementations as reference
- Identify all files that would be affected
- Note testing patterns used in similar features
## Phase 2: Clarify (one question at a time)
Ask focused questions **one at a time**. Prefer multiple choice over open-ended.
Topics to cover (skip any resolved by Phase 1 or by $ARGUMENTS):
- Scope boundaries — what's in and out
- Edge cases and error handling
- Accessibility (if UI)
- Design/UX decisions (if UI)
- Integration points
Do not batch bullets. One question per message. If a topic needs deeper exploration, split it into several questions across turns.
## Phase 3: Explore Approaches
Propose **2–3 approaches** with trade-offs. Lead with a recommendation and explain why.
Example shape:
\```
I see three directions here:
**Option A: [name]** (recommended)
- how it works: …
- pros: …
- cons: …
**Option B: [name]**
- how it works: …
- pros: …
- cons: …
Which direction appeals to you?
\```
## Phase 4: Design (incremental validation)
Once an approach is selected, present the design in **200–300 word sections** and ask after each whether it looks right. Cover:
- Architecture / where things live
- Components / modules
- Data flow / state
- Error handling
- Testing strategy
Be ready to backtrack if something doesn't make sense.
## Phase 5: Next Step
Use `AskUserQuestion` to confirm how to proceed:
\```json
{
"questions": [{
"question": "Design looks complete. What's next?",
"header": "Next step",
"options": [
{"label": "Write plan file", "description": "Create docs/plans/YYYY-MM-DD-<topic>.md with the implementation steps"},
{"label": "Enter plan mode", "description": "Use native plan mode (ExitPlanMode) for approval-gated implementation"},
{"label": "Start now", "description": "Begin implementing directly"}
],
"multiSelect": false
}]
}
\```
## Phase 6: Implement
- Follow the approved plan step by step
- Run the appropriate linter after writing each file
- Write tests alongside implementation
- Ask before committing — do not auto-commit
## Principles
- One question at a time — do not overwhelm
- Multiple choice preferred when possible
- YAGNI ruthlessly — remove unnecessary scope
- Explore alternatives — always 2–3 approaches before committing
- Incremental validation — catch misunderstandings early
- Lead with a recommendation — have an opinion, but let the user decide
Conditional: /review
Offered during interview. Only generate if user confirms.
Path: .claude/skills/review/SKILL.md
Frontmatter:
---
name: review
description: >
Reviews recent code changes for style compliance, test coverage, edge cases,
and performance implications. Use when reviewing staged changes or current
branch diff.
user-invocable: true
disable-model-invocation: true
argument-hint: "[optional: file or path to review]"
---
Body: Review process tailored to the project's specific linters, patterns, and AGENTS.md rules discovered in Phase 1.
If Group 12 detected a review tool and the user opted in, the body ends with a step that invokes that tool. Otherwise, the body prints inline review output. The tool name is injected during generation — no tool name is hardcoded in this document or in the skill template.
Conditional: /lint
Offered during interview. Only generate if user confirms.
Path: .claude/skills/lint/SKILL.md
Frontmatter:
---
name: lint
description: >
Runs the appropriate linter and formatter for specified files based on file
type. Maps extensions to project tools. Use when linting specific files or
directories.
user-invocable: true
disable-model-invocation: true
argument-hint: "<file or directory>"
---
Body: Detect file extension → map to detected project tool (from Phase 1) → run with --fix where supported → report results. The extension-to-tool mapping is built from the detection results, not from a template.
Conditional: /brainstorm (from cc-thingz)
Offered during interview. Only generate if user confirms.
Path: .claude/skills/brainstorm/SKILL.md
Frontmatter:
---
name: brainstorm
description: >
Guides collaborative dialogue to turn ideas into designs through one-at-a-time
questions, approach exploration with trade-offs, and incremental validation.
Use before creative work or significant changes — when the user asks to
"brainstorm", "think through", "explore options for", or similar.
user-invocable: true
disable-model-invocation: false
---
Body: Same pattern as /add-feature's Phases 1–5, minus the implementation phase. Exits to Write plan / Enter plan mode / Start now via AskUserQuestion. Does not implement code itself.
Conditional: /clarify (from cc-thingz)
Offered during interview. Only generate if user confirms.
Path: .claude/skills/clarify/SKILL.md
Frontmatter:
---
name: clarify
description: >
Handles user confusion by explaining actual behavior and determining whether
there is a real issue to address. Primary goal is clarification, not a fix.
Use when the user says "I don't understand", "this doesn't make sense", or
shows contradictory expectations.
user-invocable: true
disable-model-invocation: false
---
Body: Verify intent, read the relevant code, explain what actually happens, then ask whether the user wants to (a) accept the explanation, (b) file a change request, or (c) investigate further. Do not jump to fixes.
4.6 Hook Scripts
Create .claude/hooks/. All hook scripts:
- Read JSON from stdin (uses
jq when available — verified in Phase 1)
- Use
"$CLAUDE_PROJECT_DIR" for paths
- Are
chmod +x after creation
- Include a
# Generated by /rackup header comment
All tool commands in these scripts are filled in from Phase 1 detection, not from this template.
lint-format.sh (PostToolUse: Write|Edit)
Skeleton — the case branches are generated per detected tool. Any ecosystem not detected is omitted.
#!/bin/bash
set -euo pipefail
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_response.filePath // .tool_input.file_path // empty')
[ -z "$FILE_PATH" ] && exit 0
[ ! -f "$FILE_PATH" ] && exit 0
case "$FILE_PATH" in
*) ;;
esac
ERRORS=""
if [ -n "$ERRORS" ]; then
jq -n --arg errors "$ERRORS" --arg file "$FILE_PATH" '{
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": ("Lint errors in " + $file + ":\n" + $errors + "\nFix these errors.")
}
}'
fi
exit 0
test-changed.sh (Stop)
Skeleton — the test runner invocation is generated from the detected runner (from configs + lockfiles). No hardcoded default runner.
#!/bin/bash
set -euo pipefail
INPUT=$(cat)
STOP_ACTIVE=$(echo "$INPUT" | jq -r '.stop_hook_active // false')
[ "$STOP_ACTIVE" = "true" ] && exit 0
CHANGED=$(git diff --name-only HEAD 2>/dev/null || true)
[ -z "$CHANGED" ] && exit 0
TEST_FILES=""
[ -z "$TEST_FILES" ] && exit 0
if <detected_test_command> $TEST_FILES 2>&1; then
exit 0
else
jq -n '{
"decision": "block",
"reason": "Tests failed for changed files. Fix failing tests before finishing."
}'
fi
learn-on-start.sh (SessionStart — conditional)
Only generated if the user confirmed auto-invoking /learn in Group 7.
#!/bin/bash
set -euo pipefail
LEARN_DIRS="REPLACE_WITH_USER_DIRS"
jq -n --arg dirs "$LEARN_DIRS" '{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": ("Auto-learn: study codebase patterns in these key directories before proceeding: " + $dirs + ". Run /learn focused on these areas to understand conventions, patterns, and utilities.")
}
}'
Replace REPLACE_WITH_USER_DIRS with the directories chosen in Group 10.
4.7 Legacy Migration (conditional)
Only run if Subagent 3 detected .claude/commands/*.md files.
- List all detected legacy commands with content summary
- Ask: "Found N legacy commands. Convert to new skills format?"
- If yes, for each command:
- Propose a verb-based skill name (e.g.,
project__plan.md → plan)
- Ask invocation mode: user-only / Claude-only / both
- Create
.claude/skills/<verb-name>/SKILL.md with proper frontmatter, preserving the original body
- Ask whether to delete old
.claude/commands/ files
- Update
settings.json permissions to include migrated skills
PHASE 5: VERIFICATION
Validate the entire setup. If a check fails, fix and re-verify (feedback loop).
test -s AGENTS.md && echo "OK: AGENTS.md"
LINES=$(wc -l < AGENTS.md)
[ "$LINES" -le 200 ] && echo "OK: AGENTS.md ($LINES lines)" || echo "WARNING: $LINES lines (target: under 200)"
for target in CLAUDE.md .cursorrules .windsurfrules CONVENTIONS.md .github/copilot-instructions.md; do
[ -L "$target" ] && echo "OK: $target → $(readlink "$target")"
done
SKILL_ROOT=".claude/skills"
[ -d ".agents/skills" ] && SKILL_ROOT=".agents/skills"
for skill in "$SKILL_ROOT"/*/SKILL.md; do
echo "--- $skill ---"
head -20 "$skill"
wc -l "$skill"
done
if [ -d ".agents/skills" ]; then
for agent in .claude .cursor .gemini .opencode .openhands .goose .amp .codex .factory .kiro .junie .roo .emdash .mux .firebender .letta .autohand .workshop .ona .trae; do
[ -L "$agent/skills" ] && echo "OK: $agent/skills → $(readlink "$agent/skills")"
done
fi
for hook in .claude/hooks/*.sh; do
test -x "$hook" && echo "OK: $hook" || echo "FAIL: $hook not executable"
done
if command -v jq >/dev/null 2>&1; then
jq empty .claude/settings.json && echo "OK: settings.json (jq)"
elif command -v node >/dev/null 2>&1; then
node -e "JSON.parse(require('fs').readFileSync('.claude/settings.json','utf8'))" && echo "OK: settings.json (node)"
elif command -v deno >/dev/null 2>&1; then
deno eval "JSON.parse(await Deno.readTextFile('.claude/settings.json'))" && echo "OK: settings.json (deno)"
else
python3 -c "import json; json.load(open('.claude/settings.json'))" && echo "OK: settings.json (python3)"
fi
echo '{"tool_response":{"filePath":"test.ts"}}' | .claude/hooks/lint-format.sh
test -f .claude/hooks/learn-on-start.sh && echo '{}' | .claude/hooks/learn-on-start.sh
ls .claude/commands/ 2>/dev/null && echo "WARNING: legacy commands still present" || echo "OK: no legacy commands"
If a check fails: identify → fix → re-run that check → continue.
PHASE 6: SUMMARY
Show all created files grouped by category. Mark conditional skills only if confirmed.
## Setup Complete
**Core:**
- AGENTS.md (source of truth, under 200 lines)
- AGENTS.md symlinks: <only the ones the user selected>
**Skill distribution:**
- Mode: <Claude-only | Agent-agnostic>
- Source: <.claude/skills/ | .agents/skills/>
- Agent symlinks (agent-agnostic mode only): <list of <agent>/skills → .agents/skills entries>
**Skills (in the source directory above):**
- /learn — study code patterns [auto-invoke: Y or N]
- /commit (user-only) — commit with your style
- /add-feature (user-only) — dialogue-first feature implementation
- /review (user-only) — code review [if generated]
- /lint (user-only) — run linters [if generated]
- /brainstorm — exploratory dialogue [if generated]
- /clarify — explain-first handling of confusion [if generated]
**Hooks (.claude/hooks/):**
- lint-format.sh → PostToolUse: Write|Edit [if generated]
- test-changed.sh → Stop [if generated]
- learn-on-start.sh → SessionStart: startup|resume|compact|clear [if generated]
**Config:**
- .claude/settings.json (permissions + hooks)
**Migrated** [if applicable]:
- <legacy command> → /<skill name>
### Next Steps
1. Review AGENTS.md — ensure accuracy, trim if over 200 lines
2. Commit: git add -A && git commit -m "chore: add AI agent configuration"
3. Try /commit on a real change
4. Iterate: add rules as you discover issues using the # shortcut
OPTIONS
/rackup Full interactive setup (all 6 phases)
/rackup --quick Skip interview, generate defaults only (/learn + /commit + /add-feature + lint hook). Detection still runs.
/rackup --update Re-run discovery, update AGENTS.md, detect and offer to migrate legacy commands
/rackup --audit Check setup health: stale AGENTS.md, legacy commands, missing hooks. Offer fixes.
/rackup --help Show documentation
--update and --audit both include legacy command detection. If .claude/commands/ files are found, offer conversion to skills with invocation mode choice.
EXECUTION NOTES
- Use subagents for Phase 1 — 3 parallel Explore agents via the Agent tool, one message
- Be conversational in Phase 2 — skip groups where discovery gave clear answers; prefill defaults
- Show progress with phase indicators
- Confirm before writing — always show the plan before creating files
- Draft AGENTS.md in a focused pass — iterate rather than one-shot; the content comes from discovery + interview, not from a template
- AGENTS.md is source of truth — all other files are symlinks
- Keep it concise — AGENTS.md: under 200 lines; SKILL.md: under 500 lines (with subfolder references for overflow)
- Self-contained — generate everything from scratch per project, no global-skill assumptions
- Be specific — "Use 2-space indent" beats "Format properly"
- Verb names only —
commit, not project__commit; action-oriented naming
- Hook scripts must be executable — always
chmod +x after creation
- Prefer SKILL.md, but commands still work —
.claude/commands/*.md is still supported in current Claude Code; prefer skills for new setups, offer migration but don't force it
- Ask before overwriting — if existing skills or hooks are found, confirm before replacing
- Tailor to project — skill content and hook scripts adapt to detected stack; never emit a template that assumes an ecosystem
- Descriptions in third person — "Prepares a commit…" not "I prepare…" or "You can use this to…"
- Progressive disclosure — keep SKILL.md focused, reference supporting files one level deep (as rackup itself does with
subagents/*.md)
- Validate after generation — feedback loop: verify, fix, re-verify
/learn auto-invocation is interview-driven — the user chooses in Group 7; default suggestion is on, with pros/cons shown
- SessionStart hook is opt-in — only generate when Group 7's auto-invoke answer is Y, and always with explicit matchers (
startup|resume|compact|clear)
- Detect, don't assume — every tool-specific command is filled in from Phase 1 detection; generated scripts never assume an ecosystem
- New frontmatter fields are optional —
effort, allowed-tools, model can be surfaced in the interview for specific skills (e.g., effort: high for /add-feature), but none are forced
- Active-agent detection drives cross-agent default — Subagent 3 determines whether rackup is running under Claude Code or another AgentSkills-compatible agent. When Claude is active and no other agents are detected, Group 12 defaults to "No, Claude-only". Otherwise it defaults to "Yes, agent-agnostic" and presents the symlink list
- Agent-agnostic mode uses symlinks, not copies —
.agents/skills/ is the single source; each selected agent's skills/ directory is a symlink. Edits to any agent's skills/foo/SKILL.md edit the same file. Hooks and settings.json remain Claude-only under .claude/
- Ask before replacing an existing
<agent>/skills/ — if a target skills directory exists and contains files that aren't already a symlink to .agents/skills, prompt the user before overwriting (offer to move existing content into .agents/skills/ first)