init-pipeline

Installation
SKILL.md

Init Pipeline

Scaffold pipeline enforcement infrastructure into the current project: Claude Code hooks for skill compliance, git guardrails for safety, and pre-commit hooks for code quality. Detects existing tools before suggesting defaults.

When to use

  • Automatically invoked by /execute Step 0 if .claude/hooks/enforce-classification.sh is missing
  • Manually by the user when setting up a new project for pipeline work

What it sets up

All files are created in the target project, not in the Skill Kit repo.

1. Git guardrails (Claude Code hook)

Invoke /git-guardrails-claude-code with project scope.

This blocks dangerous git commands (git push, git reset --hard, git clean -f, git branch -D, git checkout ., git restore .) via a PreToolUse hook on Bash.

2. TDD classification gate (Claude Code hook)

Create .claude/hooks/enforce-classification.sh and make it executable. This blocks Write/Edit to implementation files unless the /execute Step 3 classification gate has been passed.

The hook checks for either .claude/.tdd-active (TDD invoked) or .claude/.tdd-skipped (visual frontend, explicitly opted out). No path checking beyond the trigger surface — it enforces "did you go through the gate?"

Install-time: ask which file patterns constitute implementation code. Before scaffolding the hook, present the user with the default include list and ask:

"The TDD classification gate fires on Write/Edit of files matching a pattern list. Default: *.ts, *.tsx, *.astro, *.py, *.go, *.rb, *.java, *.rs, *.js, *.jsx, *.vue, *.svelte. Over-gating is acceptable — classification is a quick decision at the top of /execute, though backend/behavior-heavy matches will trigger a full /tdd cycle. Accept the default, or customize for this project?"

Use the confirmed list (default or customized) to populate the IMPL_PATTERNS array in the hook body below. Over-gating is acceptable — the cost of an extra classification prompt is lower than the cost of silent under-fire on a polyglot project. If /init-pipeline is running non-interactively (auto-invoked by /execute Step 0), accept the default list and record that fact in the hook body via a leading comment.

Skip logic stays extension-agnostic. Tests, type declarations, and config files are detected by path substring (*test*, *spec*, .d.ts, .config.*) rather than per-language expansion.

#!/bin/bash
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

# Implementation patterns — populated at install time from the user's answer to
# the /init-pipeline trigger-surface question. Over-gating is intended.
IMPL_PATTERNS=("*.ts" "*.tsx" "*.astro" "*.py" "*.go" "*.rb" "*.java" "*.rs" "*.js" "*.jsx" "*.vue" "*.svelte")

MATCHED=0
for pattern in "${IMPL_PATTERNS[@]}"; do
  if [[ "$FILE_PATH" == $pattern ]]; then MATCHED=1; break; fi
done
if [ $MATCHED -eq 0 ]; then exit 0; fi

# Skip test files and type declarations (extension-agnostic)
if [[ "$FILE_PATH" == *test* || "$FILE_PATH" == *spec* || "$FILE_PATH" == *.d.ts ]]; then
  exit 0
fi
# Skip config files (drizzle.config, vite.config, etc.)
if [[ "$FILE_PATH" == *.config.* ]]; then
  exit 0
fi
# Check for classification markers
if [ ! -f "$CLAUDE_PROJECT_DIR/.claude/.tdd-active" ] && [ ! -f "$CLAUDE_PROJECT_DIR/.claude/.tdd-skipped" ]; then
  echo '{"decision":"block","reason":"BLOCKED: classify work in /execute Step 3 before writing implementation files. Either invoke /tdd (backend/behavior-heavy) or create .claude/.tdd-skipped (visual frontend)."}' >&2
  exit 2
fi
exit 0

After writing, run: chmod +x .claude/hooks/enforce-classification.sh

3. Claude Code settings

Create or merge .claude/settings.json with both hooks:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/enforce-classification.sh"
          }
        ]
      },
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-dangerous-git.sh"
          }
        ]
      }
    ]
  }
}

If .claude/settings.json already exists, merge the hooks.PreToolUse entries — do not overwrite existing settings.

4. Pre-commit hooks and package manager enforcement

Detect before suggesting. Before invoking any setup, check what the project already uses:

# Package manager — check lockfiles
ls pnpm-lock.yaml package-lock.json yarn.lock bun.lockb 2>/dev/null

# Formatter/linter — check deps and configs
grep -E "biome|prettier|eslint|oxlint|dprint" package.json 2>/dev/null
ls biome.json biome.jsonc .prettierrc .prettierrc.* prettier.config.* .eslintrc* eslint.config.* 2>/dev/null

# Hook manager — check for existing setup
ls lefthook.yml .husky 2>/dev/null

Present findings to the user and ask for confirmation:

  • If a formatter/linter is detected → "Found [tool]. I'll use it for pre-commit hooks."
  • If none detected → "No formatter/linter found. I'd suggest Biome (handles both formatting and linting, fast, zero-config). Want Biome, or something else?"
  • If a hook manager is detected → "Found [Lefthook/Husky]. I'll use it." (Suggest migrating Husky to Lefthook if Husky is found.)
  • If none detected → "No hook manager found. I'd suggest Lefthook. OK?"
  • If a package manager lockfile is detected → use that package manager
  • If none detected → "No lockfile found. I'd suggest pnpm. OK?"

After user confirms, invoke /setup-pre-commit with the confirmed tools.

Recommended Lefthook + Biome config (when both are confirmed):

# Pre-push hook for vitest run should be added after test suite stabilizes.
pre-commit:
  commands:
    check:
      glob: "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}"
      run: pnpm biome check --write --no-errors-on-unmatched --files-ignore-unknown=true --colors=off {staged_files}
      stage_fixed: true

Key flags: --no-errors-on-unmatched prevents false failures when no staged files match, --files-ignore-unknown=true avoids Biome choking on unsupported files, --colors=off gives cleaner hook output. Skip typecheck in pre-commit (too slow) — add it as a pre-push hook later.

Package manager enforcement: If the confirmed package manager is pnpm (detected or chosen), add the only-allow guard:

{
  "scripts": {
    "preinstall": "npx only-allow pnpm"
  }
}

For npm or yarn, skip this step — only-allow is only needed when enforcing pnpm specifically.

5. Quality gate (Claude Code hook — optional)

Ask the user: "Do you want a quality gate hook that runs feedback loops during editing? This catches issues while Claude works, not just at commit time."

If yes, create .claude/hooks/quality-gate.sh and make it executable. This runs as a PostToolUse hook on Write|Edit, providing immediate feedback after each file change.

Detect available feedback loops first. Check package.json scripts for check/lint, tsc/typecheck, and test/vitest. Only include loops that actually exist.

#!/bin/bash
# Quality gate — runs after each Write/Edit to catch issues early.
# Only runs on TypeScript/JavaScript files. Skips test/config files.

INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

# Only gate TypeScript/JavaScript implementation files
if [[ ! "$FILE_PATH" == *.ts && ! "$FILE_PATH" == *.tsx && ! "$FILE_PATH" == *.js && ! "$FILE_PATH" == *.jsx ]]; then
  exit 0
fi
# Skip test files, type declarations, config files
if [[ "$FILE_PATH" == *test* || "$FILE_PATH" == *spec* || "$FILE_PATH" == *.d.ts || "$FILE_PATH" == *.config.* ]]; then
  exit 0
fi

# 1. Biome check (fast — format + lint)
BIOME_OUTPUT=$(pnpm biome check src/ 2>&1)
BIOME_EXIT=$?

# 2. TypeScript type check
TSC_OUTPUT=$(pnpm tsc --noEmit 2>&1)
TSC_EXIT=$?

if [ $BIOME_EXIT -ne 0 ] || [ $TSC_EXIT -ne 0 ]; then
  if [ $BIOME_EXIT -ne 0 ]; then
    echo "Biome errors found:" >&2
    echo "$BIOME_OUTPUT" >&2
    echo "" >&2
  fi
  if [ $TSC_EXIT -ne 0 ]; then
    echo "TypeScript errors found:" >&2
    echo "$TSC_OUTPUT" >&2
  fi
  exit 2
fi

# 3. Run tests for changed files only (vitest import graph analysis)
VITEST_OUTPUT=$(pnpm vitest run --changed 2>&1)
VITEST_EXIT=$?

if [ $VITEST_EXIT -ne 0 ]; then
  echo "Tests failed for changed files:" >&2
  echo "$VITEST_OUTPUT" >&2
  exit 2
fi

exit 0

Project-specific extensions: If the project has domain-specific smoke tests (e.g., RAG agent tests, API health checks), append them after the generic checks. Use git diff --name-only HEAD to scope them to relevant directories.

After writing, run: chmod +x .claude/hooks/quality-gate.sh

Add the PostToolUse hook to .claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/quality-gate.sh"
          }
        ]
      }
    ]
  }
}

Merge into existing settings — do not overwrite.

6. .gitignore additions

Append these lines if not already present:

.claude/.tdd-active
.claude/.tdd-skipped
.claude/.ralph-checked

.claude/.ralph-checked is reserved here but created by /setup-ralph-loop, which is auto-invoked by /execute when a multi-slice task needs AFK bounds or may be run manually. /init-pipeline does not create the marker itself.

Verification

Before considering setup complete, check:

  • .claude/hooks/enforce-classification.sh exists and is executable
  • Hook's IMPL_PATTERNS array matches the project's implementation surface as confirmed during install (default list or customized answer)
  • .claude/hooks/block-dangerous-git.sh exists and is executable
  • .claude/settings.json has both PreToolUse hooks configured
  • If quality gate accepted: .claude/hooks/quality-gate.sh exists, is executable, and PostToolUse hook is in settings
  • Hook manager config exists (e.g. lefthook.yml)
  • Pre-commit hooks run successfully
  • .gitignore has marker entries
  • No existing project settings were overwritten

Handoff

  • Expected input: any project that will use /execute
  • Produces: complete enforcement infrastructure — Claude Code hooks, git guardrails, pre-commit hooks using detected or user-confirmed tools
  • Auto-invoked by: /execute Step 0 when .claude/hooks/enforce-classification.sh is missing
  • Invokes: /git-guardrails-claude-code (project scope), /setup-pre-commit
  • Supports downstream: /tdd (marker creation), /execute (marker cleanup); reserves .claude/.ralph-checked for /setup-ralph-loop, which creates the marker itself (auto-invoked by /execute for multi-slice work, or run manually)
Related skills

More from chrislacey89/skills

Installs
7
GitHub Stars
1
First Seen
Apr 8, 2026