Compound Engineering

Build Your Own Pipeline

Hands-on25 min

The capstone

You've learned the pieces: CLAUDE.md for context, hooks for automation, skills for reusable workflows, MCP for external tools, sub-agents for parallel work. Now you'll wire them together into a complete compound engineering pipeline.

By the end of this exercise, you'll have a project with:

  • A CLAUDE.md that encodes your project's rules
  • Hooks that enforce quality automatically
  • Skills that chain into a pipeline: /plan > /build > /review > /deploy
  • MCP connections for external tools
  • Sub-agents for parallel review

Step 1: Set up the project with CLAUDE.md

Create a project directory and write a CLAUDE.md that teaches Claude your conventions.

mkdir -p ~/pipeline-demo && cd ~/pipeline-demo
git init
CLAUDE.md
# Pipeline Demo
 
## Tech Stack
- Node.js + TypeScript
- Express API
- Jest for testing
 
## Conventions
- Use `snake_case` for database columns, `camelCase` for TypeScript
- All API routes require authentication middleware
- Every endpoint needs input validation with zod
- Tests live next to source files: `foo.ts` + `foo.test.ts`
 
## Commands
- `npm test` - run all tests
- `npm run lint` - check code style
- `npm run build` - compile TypeScript
 
## Learnings
<!-- Updated automatically by /codify -->
Your CLAUDE.md is a living document

This file grows over time. Every codify step adds to the Learnings section. Every bug you fix adds a convention. Start lean and let it compound.

Step 2: Add hooks for quality gates

Hooks run automatically at specific points in Claude's workflow. Use them to enforce standards without thinking about it.

Create a .claude/settings.json in your project:

.claude/settings.json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "command": "npx eslint --fix $CLAUDE_FILE_PATH 2>/dev/null || true"
      }
    ],
    "Stop": [
      {
        "command": "npm test 2>&1 | tail -5"
      }
    ]
  }
}

This does two things:

  • After every file edit: auto-format with ESLint
  • When Claude finishes: run tests and show the result
Hooks are guardrails, not gates

Keep hooks fast (under 5 seconds). They should catch obvious issues, not run your full CI suite. If a hook takes too long, Claude's workflow feels sluggish.

Step 3: Create skills

Skills are reusable commands stored in .claude/commands/. Each one is a markdown file with instructions Claude follows.

The /plan skill

.claude/commands/plan.md
Analyze the user's request and create a structured implementation plan.
 
## Steps
 
1. Restate the requirement in your own words
2. List the files that will be created or modified
3. Identify dependencies and potential risks
4. Define acceptance criteria (testable, specific)
5. Write the plan to `docs/plans/[feature-name].md`
 
## Output format
 
```markdown
# Plan: [Feature Name]
 
## Goal
[One sentence]
 
## Files
- [ ] `path/to/file.ts` - [what changes]
 
## Acceptance Criteria
- [ ] [Specific, testable criterion]
 
## Risks
- [Risk and mitigation]

Wait for user approval before proceeding to implementation.


### The /build skill

```markdown title=".claude/commands/build.md"
Implement the most recent plan from `docs/plans/`.

## Steps

1. Read the latest plan from `docs/plans/`
2. Implement each file change listed in the plan
3. After each file, run the relevant tests
4. Check off acceptance criteria as they're met
5. If a criterion fails, fix the issue before moving on

## Rules

- Follow all conventions in CLAUDE.md
- Write tests alongside implementation, not after
- Commit after each logical unit of work

The /review skill

.claude/commands/review.md
Run a multi-perspective code review on recent changes.
 
## Review from these perspectives
 
### Security
- Input validation on all endpoints
- Authentication/authorization checks
- No secrets in code or logs
- SQL injection, XSS, SSRF prevention
 
### Performance
- No N+1 queries
- Appropriate indexing
- No unnecessary re-renders (if frontend)
- Batch operations where possible
 
### Correctness
- Edge cases handled (empty arrays, null values, concurrent access)
- Error handling with meaningful messages
- Types are accurate, no `any` escape hatches
 
### Maintainability
- Functions under 50 lines
- Clear naming
- No duplicated logic
- Tests cover the critical paths
 
## Output format
 
For each finding:
- **Severity**: P1 (must fix) / P2 (should fix) / P3 (consider)
- **Category**: security / performance / correctness / maintainability
- **File**: path and line
- **Issue**: what's wrong
- **Fix**: how to fix it

The /deploy skill

.claude/commands/deploy.md
Deploy the current branch to production.
 
## Pre-deploy checks
 
1. Run `npm test` - all tests must pass
2. Run `npm run build` - build must succeed
3. Check git status - working tree must be clean
4. Verify branch is up to date with remote
 
If any check fails, stop and report the issue.
 
## Deploy steps
 
1. Push to the deploy branch: `git push origin main`
2. Verify the deployment completed (check deploy URL)
3. Run a smoke test against the live endpoint
 
## Dynamic context
 
Current git status: !`git status --short`
Current branch: !`git branch --show-current`
Last commit: !`git log --oneline -1`
Dynamic context with shell commands

The ! backtick syntax in skills pulls live data at execution time. !`git status --short`` injects the current git status into the prompt. Use this to give Claude real-time awareness.

Step 4: Wire up MCP

Add an MCP server for external tool access. This example connects a filesystem MCP so Claude can manage files outside the project directory, but you can connect any MCP - databases, APIs, deployment tools.

.mcp.json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/path/to/your/project"
      ]
    }
  }
}

In a real pipeline, you might connect:

  • A GitHub MCP for PR management
  • A database MCP for schema inspection
  • A monitoring MCP to check production health before deploys

Step 5: Sub-agents for parallel review

Sub-agents let Claude spawn parallel workers. Your /review skill can use them to run all four review perspectives simultaneously instead of sequentially.

When Claude encounters the review skill, it can dispatch sub-agents:

# Claude internally spawns these in parallel:
# Sub-agent 1: Security review of changed files
# Sub-agent 2: Performance review of changed files
# Sub-agent 3: Correctness review of changed files
# Sub-agent 4: Maintainability review of changed files
# Results merge into a single report

To enable this, update your settings:

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__filesystem__read_file",
      "mcp__filesystem__write_file"
    ]
  }
}

Pre-approving safe tools means sub-agents can work without asking for permission on every file read.


Exercises

Ex

Build the /review skill with multi-perspective checks

Create the /review skill from Step 3 in your own project. Then test it:

  1. Write a simple Express endpoint with a deliberate security issue (no input validation)
  2. Run claude "/review"
  3. Verify it catches the security issue
Start with a route like app.get("/users/:id", (req, res) => db.query("SELECT * FROM users WHERE id = " + req.params.id)) - this has SQL injection, no auth, and no input validation.

Create .claude/commands/review.md with the review skill content from Step 3. Then:

# Create a deliberately vulnerable endpoint
mkdir -p src && cat > src/server.ts << 'EOF'
import express from "express";
const app = express();
 
app.get("/users/:id", (req, res) => {
  // SQL injection: string concatenation
  const query = "SELECT * FROM users WHERE id = " + req.params.id;
  // No auth check
  // No input validation
  res.json({ query });
});
EOF
 
# Run the review
claude "/review"

Claude should flag: SQL injection (P1), missing authentication (P1), no input validation (P2), and no error handling (P2).

Ex

Create a /deploy skill that pushes to production

Build the /deploy skill with pre-deploy checks. The skill should:

  1. Verify tests pass before allowing deploy
  2. Check for a clean git working tree
  3. Use dynamic context (! backtick syntax) for live git status
Use the template from Step 3. The key is the dynamic context lines: !`git status --short`and!\npm test 2>&1 | tail -3`` inject real output into the prompt at runtime.

Create .claude/commands/deploy.md with the deploy skill content from Step 3. Test the pre-deploy checks:

# Make a change without committing
echo "// wip" >> src/server.ts
 
# Try to deploy - should fail on dirty working tree
claude "/deploy"
 
# Claude should refuse: "Working tree is not clean.
# Please commit or stash changes before deploying."
 
# Clean up and try again
git checkout -- src/server.ts
claude "/deploy"
Ex

Chain skills into a pipeline

Chain all four skills into a single workflow. Ask Claude to:

  1. Plan a new feature (add a health check endpoint)
  2. Build it following the plan
  3. Review the implementation
  4. Deploy it
You can chain skills in a single prompt: claude "Use /plan to design a /healthz endpoint, then /build to implement it, then /review to check it, then /deploy to ship it"
claude "I need a /healthz endpoint that returns the app version
and uptime. Use /plan to design it, /build to implement it,
/review to check the implementation, then /deploy to ship it."

Claude will:

  1. Run /plan - create docs/plans/healthz-endpoint.md with acceptance criteria
  2. Run /build - implement the endpoint, write tests, check criteria
  3. Run /review - scan for security, performance, correctness issues
  4. Run /deploy - verify tests pass, check clean tree, push

This is the compound loop in action: PLAN > WORK > REVIEW, with DEEPEN and CODIFY available as needed.