원클릭으로
create-skill
Scaffold, write, and validate a new Claude Code skill — enforces quality standards derived from 250+ review comments
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Scaffold, write, and validate a new Claude Code skill — enforces quality standards derived from 250+ review comments
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Adopt extracted helpers — find dead symbols from forge, wire them into consumers, replace duplicated inline patterns, and gate on dead-symbol delta (Titan Paradigm Phase 4.5)
Adopt extracted helpers — find dead symbols from forge, wire them into consumers, replace duplicated inline patterns, and gate on dead-symbol delta (Titan Paradigm Phase 4.5)
Validate staged changes — codegraph checks + project lint/build/test, auto-rollback on failure, pass/fail commit gate (Titan Paradigm Phase 4)
Audit codebase files against the 4-pillar quality manifesto using RECON work batches, with batch processing and context budget management (Titan Paradigm Phase 2)
Map a codebase's dependency graph, identify hotspots, name logical domains, propose work batches, and produce a ranked priority queue for autonomous cleanup (Titan Paradigm Phase 1)
Local repo maintenance — clean stale worktrees, remove dirt files, sync with main, update codegraph, prune branches, and verify repo health
| name | create-skill |
| description | Scaffold, write, and validate a new Claude Code skill — enforces quality standards derived from 250+ review comments |
| argument-hint | <skill-name> (kebab-case, e.g. deploy-check) |
| allowed-tools | Bash, Read, Write, Edit, Glob, Grep |
Create a new Claude Code skill with correct structure, robust bash, and built-in quality gates. This skill encodes lessons from 250+ Greptile review comments to prevent the most common skill authoring mistakes.
$ARGUMENTS must contain the skill name in kebab-case (e.g. deploy-check)$ARGUMENTS is empty, ask the user for a skill name before proceedingSet SKILL_NAME to the provided name. Validate it is kebab-case (^[a-z][a-z0-9]*(-[a-z0-9]+)*$). Reject otherwise.
Pre-flight: Verify required tools and environment:
for tool in git mktemp; do
# > /dev/null 2>&1: suppress command path on success and shell's "not found" on failure — the || clause provides the error message
command -v "$tool" > /dev/null 2>&1 || { echo "ERROR: required tool '$tool' not found"; exit 1; }
done
# > /dev/null 2>&1: suppress git's own "fatal: not a git repository" — our || message is more actionable
git rev-parse --show-toplevel > /dev/null 2>&1 || { echo "ERROR: not in a git repository — run /create-skill from the repo root"; exit 1; }
Parse $ARGUMENTS per the Arguments section above. If validation fails, abort with a clear error.
Discovery: Before writing anything, gather requirements interactively. Ask the user these questions (all at once, not one-by-one):
--fix, --dry-run, <path>)--start-from or --skip-* flags for long-running pipelines?Wait for the user's answers before proceeding. Do not guess or assume.
Exit condition: Pre-flight passed (git repo confirmed, skill name validated). All 7 questions have answers. Purpose, arguments, phases, tools, artifacts, dangerous ops, and resume support are defined.
Idempotency guard: Before writing, check for an existing skill:
if [ -f ".claude/skills/$SKILL_NAME/SKILL.md" ]; then
echo "WARN: .claude/skills/$SKILL_NAME/SKILL.md already exists."
echo "Proceeding will overwrite it. Confirm (y) or abort (n)."
# STOP — ask the user whether to overwrite before continuing. Exit 1 if they decline.
fi
Create the skill directory and SKILL.md with frontmatter:
mkdir -p ".claude/skills/$SKILL_NAME"
Write the SKILL.md file starting with this structure:
---
name: $SKILL_NAME
description: <one-line from user's purpose>
argument-hint: "<from user's argument design>"
allowed-tools: <from user's tool list>
---
# /$SKILL_NAME — <Title>
<Purpose paragraph from Phase 0>
## Arguments
- `$ARGUMENTS` parsing rules here
- Set state variables: `DRY_RUN`, `AUTO_FIX`, etc.
## Phase 0 — Pre-flight
```bash
for tool in git mktemp; do # replace with the actual shell commands your skill uses (e.g. jq, python, curl)
# > /dev/null 2>&1: suppress command path on success and shell's "not found" on failure — the || clause provides the error message
command -v "$tool" > /dev/null 2>&1 || { echo "ERROR: required tool '$tool' not found"; exit 1; }
done
# > /dev/null 2>&1: suppress git's own "fatal: not a git repository" — our || message is more actionable
git rev-parse --show-toplevel > /dev/null 2>&1 || { echo "ERROR: not in a git repository"; exit 1; }
```
1. Confirm environment (repo root, required runtime/toolchain version, required tools)
2. Parse `$ARGUMENTS` into state variables
3. Validate preconditions
**Exit condition:** <What must be true before Phase 1 starts, e.g. "git repo confirmed, arguments validated, all required tools present">
## Phase N — <Name>
<Steps>
**Exit condition:** <What must be true before the next phase starts>
## Examples
- <Usage examples showing common invocations and expected behavior>
## Rules
- <Hard constraints>
$ARGUMENTS into named state variablesExit condition: .claude/skills/$SKILL_NAME/SKILL.md exists with valid frontmatter, Phase 0, Arguments section, and Rules section.
Write each phase following these 17 mandatory patterns (derived from Greptile review findings across 250+ comments):
Each fenced code block is a separate shell invocation. Variables set in one block do not exist in the next.
Wrong:
```bash
WORK_DIR=$(mktemp -d)
```
Later:
```bash
rm -rf $WORK_DIR # BUG: $WORK_DIR is empty here
```
Correct: Persist state to a file (use your actual skill name, not a variable). First ensure the directory exists:
```bash
mkdir -p .codegraph/deploy-check
mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX" > .codegraph/deploy-check/.tmpdir
```
Later:
```bash
rm -rf "$(cat .codegraph/deploy-check/.tmpdir)"
```
Or keep everything in a single code block if the operations are sequential.
Never use 2>/dev/null without documenting the skip path. Every command that can fail must either:
|| { echo "ERROR: ..."; exit 1; })Wrong:
```bash
git show HEAD:$FILE 2>/dev/null | codegraph where --file -
```
Correct:
```bash
PREV_FILE=$(mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX.js") # adjust extension to match the language of $FILE; template syntax is portable (macOS + Linux)
trap 'rm -f "$PREV_FILE"' EXIT
# $FILE is expected to be set by the surrounding loop, e.g. for FILE in $(git diff --name-only HEAD); do ... done
# 2>/dev/null: suppress git's "fatal: Path X does not exist in HEAD" — the else branch already warns the user
if git show HEAD:"$FILE" > "$PREV_FILE" 2>/dev/null; then
codegraph where --file "$PREV_FILE"
else
echo "WARN: $FILE is new or unreadable in HEAD — skipping before/after comparison"
fi
rm -f "$PREV_FILE"
trap - EXIT
```
Codegraph's language detection is extension-based. Temp files passed to codegraph must have the correct extension:
mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX.js" # NOT just mktemp — template syntax is cross-platform (macOS + Linux)
Use mktemp for temp files, never hardcoded paths like /tmp/skill-output.json. Concurrent sessions or re-runs will collide.
When referencing other steps, use phase names, not numbers. Numbers break when steps are inserted.
Wrong: "Use the results from Step 2" Correct: "Use the diff-impact results from Phase: Impact Analysis"
Every variable or placeholder in pseudocode must have a preceding assignment. If a value requires detection, write the explicit detection script — do not use <detected-value> placeholders.
Wrong: "Run <detected-test-command>"
Correct:
Detect the test runner and run in a single block:
```bash
if [ -f "pnpm-lock.yaml" ]; then TEST_CMD="pnpm test"
elif [ -f "yarn.lock" ]; then TEST_CMD="yarn test"
elif [ -f "package.json" ]; then TEST_CMD="npm test"
else echo "WARN: No recognised test runner found — skipping tests"; TEST_CMD="true"; fi
$TEST_CMD
```
Each decision (pass/fail, rollback/continue, skip/run) must be defined in exactly one place. If two sections describe the same decision path, consolidate them and reference the single source.
Every codegraph command or tool invocation in the procedure must be permitted by the Rules section. Every exception in the Rules must correspond to an actual procedure step. After writing, cross-check both directions.
If a phase runs a codegraph command and stores the result, later phases must reference that result — not re-run the command. Add a note like: "Using impact_report from Phase: Impact Analysis".
If the skill supports --start-from or --skip-*:
For any phase that takes longer than ~10 seconds (file iteration, API calls, batch operations), emit progress:
# $i, $total, and $FILE are loop variables, e.g. i=0; total=$(wc -l < filelist); while read FILE; do i=$((i+1)); ...
echo "Processing file $i/$total: $FILE"
Never leave the user staring at a silent terminal during long operations.
Before running expensive operations (codegraph build, embedding generation, batch analysis), check if usable output already exists (replace deploy-check with your actual skill name):
```bash
if [ -f ".codegraph/deploy-check/results.json" ]; then
echo "Using cached results from previous run"
else
# run expensive operation
fi
```
This supports both idempotent re-runs and resume-after-failure.
Avoid shell constructs that behave differently across platforms:
find ... -name "*.ext" | grep -q . instead of find ... -quit (non-portable) or glob expansion (ls *.ext) which differs between bash versionsmktemp with template syntax (mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX.ext") — GNU flags like --suffix and -p are not available on macOS BSD mktempsed -i.bak instead of sed -i '' (GNU vs BSD incompatibility)# NOTE: requires GNU coreutilsAny phase that creates temp files or modifies repo state must set a cleanup trap. Without it, errors mid-phase leak temp files or leave dirty state:
TMPFILE=$(mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX.json")
trap 'rm -f "$TMPFILE"' EXIT
# ... operations that might fail ...
# Reset when done if more work follows:
trap - EXIT
For phases that cd into a temp directory, clean up both the directory and the working directory change:
WORK_DIR=$(mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX")
# > /dev/null 2>&1: suppress cd's directory-path output — cleanup should be silent
trap 'cd - > /dev/null 2>&1; rm -rf "$WORK_DIR"' EXIT
cd "$WORK_DIR"
# ... operations inside the temp directory ...
# > /dev/null 2>&1: suppress cd's directory-path output — cleanup should be silent
cd - > /dev/null 2>&1
rm -rf "$WORK_DIR"
trap - EXIT
Never rely on $? or stash@{0} after git stash push — modern git (2.16+) returns 0 even when nothing was stashed, and other operations may push to the stash stack between your push and pop.
Wrong:
```bash
git stash push -- package.json
# ... operations ...
git stash pop # BUG: pops wrong entry if stash was no-op or stack changed
```
Correct: Use a named stash with STASH_REF lookup — keep push and pop in one block or persist the ref to a file if other work must happen in between.
Single-block approach (push and pop bracket the work):
```bash
git stash push -m "deploy-check-backup" -- package.json package-lock.json
STASH_REF=$(git stash list --format='%gd %s' | grep 'deploy-check-backup' | head -1 | awk '{print $1}')
# STASH_REF is non-empty only if a stash entry was actually created.
# ... work here ...
[ -n "$STASH_REF" ] && git stash pop "$STASH_REF"
```
If the pop must happen in a later code fence, persist the ref to a file (per Pattern 1):
```bash
mkdir -p .codegraph/deploy-check
git stash push -m "deploy-check-backup" -- package.json package-lock.json
git stash list --format='%gd %s' | grep 'deploy-check-backup' | head -1 | awk '{print $1}' > .codegraph/deploy-check/.stash-ref
```
Later:
```bash
STASH_REF=$(cat .codegraph/deploy-check/.stash-ref)
[ -n "$STASH_REF" ] && git stash pop "$STASH_REF"
rm -f .codegraph/deploy-check/.stash-ref
```
Every arithmetic division or percentage computation must guard against zero denominators. Common in benchmark comparisons, complexity deltas, and ratio calculations:
Wrong:
```bash
DELTA=$(( (CURRENT - BASELINE) * 100 / BASELINE ))
```
Correct:
```bash
# $BASELINE and $CURRENT are expected to be set by the surrounding context (e.g. from codegraph stats output)
if [ "$BASELINE" -gt 0 ]; then
DELTA=$(( (CURRENT - BASELINE) * 100 / BASELINE ))
else
DELTA=0 # no baseline — treat as no change
fi
```
If the skill supports --dry-run, every destructive operation must check the flag at the point of action — not just at phase entry. A single phase often mixes reads (always run) and writes (skip in dry-run):
Wrong:
```bash
# Phase skips entirely in dry-run — but the analysis part is useful
if [ "$DRY_RUN" = "true" ]; then exit 0; fi
# ... 50 lines of analysis ...
rm -rf "$OUTPUT_DIR"
```
Correct:
```bash
# $DRY_RUN is expected to be parsed from $ARGUMENTS in Phase 0; $OUTPUT_DIR is set earlier in this phase
# Analysis always runs
codegraph audit --quick src/
# Only the destructive part checks DRY_RUN
if [ "$DRY_RUN" = "true" ]; then
echo "[DRY RUN] Would remove $OUTPUT_DIR"
else
rm -rf "$OUTPUT_DIR"
fi
```
Exit condition: Every phase body in the SKILL.md follows all 17 patterns. No wrong/correct examples remain as actual instructions — only the correct versions.
If the skill performs dangerous operations (from Phase 0 discovery), add explicit guards:
git add . or git add -A)git reset HEAD~1" or similarrm -i or prompt for confirmation in non---force modeif [ -f "biome.json" ]; then LINT_CMD="npx biome check"
elif find . -maxdepth 1 -name "eslint.config.*" | grep -q .; then LINT_CMD="npx eslint ."
elif [ -f "package.json" ]; then LINT_CMD="npm run lint"
else echo "WARN: No recognised lint runner found — skipping lint"; LINT_CMD="true"; fi
$LINT_CMD
Exit condition: Every dangerous operation identified in Phase: Discovery has a corresponding guard in the SKILL.md.
Before finalizing, audit the SKILL.md against every item below. Do not skip any item. Fix violations before proceeding.
name, description, argument-hint, allowed-toolsname matches the directory name$ARGUMENTS into named variables2>/dev/null without a documented skip rationale. No commands that swallow errorsmktemp, never hardcoded paths<placeholder> has a preceding detection/assignment script--start-from/--skip-* is supported, every skip path validates required artifactsProcessing $i/$total)sed -i '', no unquoted globs, no GNU-only flags without fallback or documentationtrap ... EXIT for cleanup on error pathsgit stash push has a named STASH_REF lookup; every pop/drop is guarded by [ -n "$STASH_REF" ]--dry-run is supported, every destructive operation is gated on the flag at the point of action, not just at phase entrycommand -v git mktemp jq). "Command not found" is caught before Phase 2, not during Phase 3exit 1. No silent early returns that leave the pipeline in an ambiguous state.codegraph/$SKILL_NAME/* files, the skill documents when they're cleaned up or how users remove them (e.g., rm -rf .codegraph/$SKILL_NAME in a cleanup section)git add calls use explicit file paths (never . or -A); git diff --cached --quiet is checked before committing to avoid empty commitsRead through the entire SKILL.md one more time after checking all items. Fix anything found.
Exit condition: All checklist items pass. The SKILL.md has no unresolved structure, anti-pattern, robustness, completeness, or safety violations.
The self-review is purely theoretical — most real issues (wrong paths, shell syntax, missing tools, argument parsing bugs) only surface when you actually try to run the code. Before finalizing, execute these validation steps:
Run both validation scripts against the generated SKILL.md:
LINT_RC=0
bash .claude/skills/create-skill/scripts/lint-skill.sh ".claude/skills/$SKILL_NAME/SKILL.md" || LINT_RC=$?
SMOKE_RC=0
bash .claude/skills/create-skill/scripts/smoke-test-skill.sh ".claude/skills/$SKILL_NAME/SKILL.md" || SMOKE_RC=$?
if [ "$LINT_RC" -ne 0 ] || [ "$SMOKE_RC" -ne 0 ]; then
echo "Validation failed — fix ERRORs before proceeding"; exit 1
fi
lint-skill.sh checks for cross-fence variable bugs, bare 2>/dev/null, hardcoded npm test / npm run test / npm run lint / yarn test / yarn run test / yarn run lint / pnpm test / pnpm run test / pnpm run lint, git add . / git add -- ., missing frontmatter (including name matching directory name), missing Phase 0 / Rules / Examples, missing exit conditions, GNU-only find -quit, hardcoded /tmp/ paths, and sed -i portability issues.smoke-test-skill.sh extracts every bash code block (skipping example regions inside quadruple backticks) and runs bash -n syntax checking on each.Fix all ERROR findings. Review WARN findings — fix or annotate with justification.
Run the skill's Phase 0 (pre-flight) logic in a temporary test directory to verify:
TEST_DIR=$(mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX")
# > /dev/null 2>&1: suppress cd's directory-path output — cleanup should be silent
trap 'cd - > /dev/null 2>&1; rm -rf "$TEST_DIR"' EXIT
cd "$TEST_DIR"
git init --quiet
# --- Happy path: valid skill name and all tools present ---
# Simulate: ARGUMENTS="deploy-check"; run the Phase 0 pre-flight checks
# --- Failure path 1: not in a git repo ---
# (run checks from a non-git directory — expect ERROR message + non-zero exit)
# --- Failure path 2: invalid skill name ---
# ARGUMENTS="BadName!"; run argument validation — expect rejection
# --- Failure path 3: missing required tool ---
# (temporarily hide a required tool — expect clear error message + non-zero exit)
# > /dev/null 2>&1: suppress cd's directory-path output — returning to original directory
cd - > /dev/null 2>&1
rm -rf "$TEST_DIR"
trap - EXIT
Mentally trace a second execution of the skill on the same state:
mktemp paths unique across runs (they should be by default)?Document any idempotency fix applied.
Exit condition: All bash blocks pass bash -n syntax check. Phase 0 logic runs without errors in a test directory. Idempotency is confirmed or fixed.
If the user approves:
.claude/skills/$SKILL_NAME/SKILL.md (and any scripts in .claude/skills/$SKILL_NAME/scripts/ if created)feat(skill): add /$SKILL_NAME skillExit condition: User has approved the skill. .claude/skills/$SKILL_NAME/SKILL.md is committed to the repo.
/create-skill deploy-check — scaffold a deployment validation skill that runs preflight checks before deploying/create-skill review-pr — scaffold a PR review skill with API calls and diff analysis/create-skill db-migrate — scaffold a database migration skill with dangerous-operation guards and rollback pathsnpm test, npm run test, npm run lint, yarn test, yarn run test, yarn run lint, pnpm test, pnpm run test, or pnpm run lint — detect the package manager first.2>/dev/null needs a justification comment in the generated skill.