· Steven Mays · Software Engineering · 12 min read
Optimizing Claude Code: Skills, Plugins, and the Art of Teaching Your AI to Code Like You
Customize Claude Code with skills, plugins, commands, and configuration files that transform a capable coding assistant into one that matches your exact workflow.

Updated January 4, 2026
I spent months using Claude Code wrong.
Not wrong as in bad results—the defaults are solid. Wrong as in treating a customizable system like a fixed tool. I was bending my workflow to fit the AI instead of bending the AI to fit my workflow.
That’s backwards.
Default Claude Code is a talented generalist. Configured Claude Code is someone who’s worked at your company for years. Both write code. Only one knows your team’s exact preferences.
Here’s how I built it.
- The Architecture: How the Pieces Fit Together
- Settings: The Foundation
- CLAUDE.md: Project-Level Instructions
- Skills: Teaching Domain Expertise
- Hooks: Active Enforcement
- Custom Commands: Workflow Shortcuts
- Agent Docs: Reference Material on Demand
- Plugins: Extending Capabilities
- Setting This Up: A Practical Guide
- The Compounding Effect
The Architecture: How the Pieces Fit Together
Claude Code’s customization lives in two places:
~/.claude/
├── settings.json # Global settings (thinking, tokens, plugins)
├── skills/ # Domain expertise (TypeScript patterns, AWS, etc.)
├── commands/ # Workflow shortcuts (/analyze-bug, /simplify)
├── hooks/ # Active enforcement rules (warn/block patterns)
└── plugins/ # External tool integrations (browser, AST)
project/
├── CLAUDE.md # Project-specific instructions
└── .claude/
├── .agent/ # Reference documentation for this project
└── hookify.*.local.md # Project-specific enforcement rulesThe mental model is simple:
- settings — control behavior
- CLAUDE.md — provides project context
- skills — encode domain expertise
- hooks — enforce conventions
- commands — trigger workflows
- .agent/ — provide reference material
- plugins — add capabilities
These layers interact in ways that matter. When Claude Code starts, it reads settings, loads relevant skills based on context, and injects CLAUDE.md into its system prompt. Invoke a command, it triggers a predefined workflow. Mention a topic covered by a skill, Claude applies that expertise automatically. The whole thing compounds.
Settings: The Foundation
My ~/.claude/settings.json is minimal:
{
"includeCoAuthoredBy": false,
"enabledPlugins": {
"frontend-design@claude-code-plugins": true,
"dev-browser@dev-browser-marketplace": true,
"ast-grep@ast-grep-marketplace": true,
"ralph-wiggum@claude-code-plugins": true,
"pg@aiguide": true
},
"env": {
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "64000",
"MAX_THINKING_TOKENS": "31999"
},
"alwaysThinkingEnabled": true
}The tradeoffs:
alwaysThinkingEnabled: true — Extended thinking on every response. You trade latency for quality. Quick questions don’t need it. Complex refactoring does. I keep it on because I’m usually doing substantial engineering work, not asking quick questions.
Token limits — 64000 output tokens prevents truncation on large refactors. 31999 thinking tokens gives Claude room to reason before responding.
includeCoAuthoredBy: false — I don’t need AI attribution in every commit message.
Full settings: dotfiles repo.
CLAUDE.md: Project-Level Instructions
Every project gets a CLAUDE.md at the root. Build commands, directory structure, coding principles, workflow patterns—all of it.
Here’s my template:
# Project Guidelines
## Project Overview
- **Name**: [Project name]
- **Purpose**: [Brief description]
- **Stack**: TypeScript, [framework], [database]
## Commands
npm run build # Build the project
npm run test # Run tests
npm run lint # Lint code
## Directory Structure
src/
├── handlers/ # Entry points (API routes, Lambda handlers)
├── lib/ # Shared business logic
└── scripts/ # Development/build scripts
## Workflow Patterns
**New Feature**
1. Plan → Implement → Test → Review
**Bug Fix**
1. Reproduce → Hypothesize → Fix → Add regression test
2. **Escalation**: After 2 failed fix attempts, stop and use **/analyze-bug**
## Core Principles
1. **Simplicity over cleverness** - Write code that's immediately understandable
2. **Leverage existing solutions** - Use standard libraries, don't reinvent
3. **Single responsibility** - Functions do one thing, under 20 lines
4. **Early returns** - Guard clauses over nested conditionals
5. **Match existing patterns** - Follow the file's conventions exactly
## Before You Start
Read the relevant reference docs in **.claude/.agent/**:
| File | When to Read |
|------|--------------|
| coding-patterns.md | Writing new TypeScript code |
| anti-patterns.md | Before code review or PR |
| error-handling.md | Implementing error handling |The key insight: CLAUDE.md is a system prompt you control.
Every instruction shapes every response. Define escalation patterns that tell Claude to stop thrashing—my Bug Fix workflow triggers a 6-step root cause analysis after two failed fixes. No more watching Claude spiral on the same approach.
Full template: CLAUDE.md in dotfiles
Skills: Teaching Domain Expertise
Skills are markdown files that encode specialized knowledge. Claude loads them automatically when relevant.
I maintain several:
TypeScript Patterns
Team conventions that aren’t in style guides but matter for consistency:
---
name: typescript-patterns
description: TypeScript code patterns for types, interfaces, assertions, and type safety.
---
# TypeScript Patterns Skill
## Core Principles
### Prefer Type Inference Over Explicit Return Types
Let TypeScript infer function return types instead of explicitly specifying them.
// ✅ CORRECT: Inferred return type
function calculateTotal(items: OrderItem[]) {
return items.reduce((sum, item) => sum + item.price, 0);
}
// ❌ WRONG: Explicit return type
function calculateTotal(items: OrderItem[]): number {
return items.reduce((sum, item) => sum + item.price, 0);
}
**Why:** Type inference catches implicit type coercion bugs.
### Interface Naming
Never use **I** prefix or **Data** suffix.
// ✅ CORRECT
export interface Product { ... }
// ❌ WRONG
export interface IProduct { ... }
export interface ProductData { ... }The full skill is 700+ lines. TypeScript has a lot of conventions worth encoding.
Serverless AWS
For Lambda, DynamoDB, and SQS patterns:
---
name: serverless-aws
description: Patterns for AWS Lambda, DynamoDB, SQS, and Secrets Manager.
---
## Lambda Handler Structure
export async function handle(event: AWSLambda.APIGatewayProxyEvent) {
try {
return await handleInternal(event);
} catch (error) {
await trace.error(error, { headers: event.headers, body: event.body });
return createErrorResponse(error);
}
}
## Cold Start Optimization
Initialize clients outside handler:
const dynamoClient = new DynamoDBClient({ region: 'us-east-1' });
let configCache: Config;
export async function handle(event: any) {
if (!configCache) configCache = await loadConfig();
return process(event, configCache);
}Code Review
This one catches AI-generated patterns:
---
name: code-review
description: Review code changes and remove AI-generated patterns.
---
## What to Look For
### Excessive Comments
AI tends to over-comment. Remove comments that:
- State the obvious (e.g., **// increment counter** above **counter++**)
- Repeat the function/variable name
### Gratuitous Defensive Checks
Remove defensive code that doesn't match the codebase style:
- Null checks on values already validated upstream
- Type checks on typed parameters
- Try/catch blocks in trusted codepathsAI models add defensive code and comments that human developers wouldn’t. This skill tells Claude to avoid those patterns. The output feels more natural.
Gemini Image Generator
A recent addition for image generation via Google’s Gemini API:
---
name: gemini-image-generator
description: Generate images using Google Gemini with customizable options
---
# gemini-image-generator
Supports text-to-image, image-to-image with reference, and multiple output sizes (1K, 2K, 4K).# Text-to-image
./scripts/generate.py --prompt "A serene mountain landscape" --output landscape.png
# With reference image for style guidance
./scripts/generate.py --prompt "Same character wearing a party hat" --reference character.png --output party.pngThe tradeoff: requires a Gemini API key and Python dependencies. Worth it if you generate images frequently. I use it for blog post illustrations and UI mockups.
Skills directory: skills in dotfiles
Hooks: Active Enforcement
Skills teach Claude how to code. Hooks enforce that it does.
A skill says “prefer for…of over .forEach()“—but Claude can still forget. A hook catches it in real-time, warning or blocking before the code is written. Training vs guardrails.
I use the hookify plugin for enforcement rules. My active hooks:
| Hook | Action | What It Catches |
|---|---|---|
| warn-any-type | warn | : any, <any>, any[] |
| block-as-any | block | as any casts |
| warn-as-syntax | warn | as Type (prefer <Type>) |
| warn-foreach | warn | .forEach() (prefer for…of) |
| warn-interface-prefix | warn | interface IFoo |
| warn-debug-code | warn | console.log, debugger |
| warn-default-import | warn | Default imports (prefer namespace) |
| block-hardcoded-secrets | block | Hardcoded API keys/passwords |
Creating Hooks
Hooks are markdown files with YAML frontmatter. Here’s an example that blocks as any casts:
---
name: block-as-any
enabled: true
event: file
pattern: as\s+any(?!\w)
action: block
---
🛑 **Unsafe as any cast detected!**
This bypasses type safety entirely. Instead:
- Use a proper type assertion: **<SpecificType>value**
- Create a type guard function
- Fix the underlying type issue
If you truly need to escape the type system, explain why.The action field determines severity:
- warn — Shows message, allows the operation
- block — Prevents the operation entirely
The Skills + Hooks Combo
This is where customization compounds.
TypeScript patterns skill teaches conventions. Hooks enforce them. Claude uses as Type instead of <Type>? Hook catches it before the code is written.
The feedback loop is immediate: Claude sees the warning, adjusts, continues. Since Claude Code is stateless between sessions, hooks provide consistent enforcement every time. Skills inform, hooks enforce.
Hooks directory: hooks in dotfiles
Custom Commands: Workflow Shortcuts
Shell aliases for Claude workflows. Type /analyze-bug instead of a detailed prompt, get a consistent, structured response.
| Command | Purpose |
|---|---|
| /analyze-bug | 6-step root cause analysis for stubborn bugs |
| /simplify | Reduce code complexity while preserving behavior |
| /plan-feature | Break complex features into implementable stages |
| /review-diff | Review code changes against project guidelines |
| /fix-types | Fix TypeScript type errors systematically |
| /take-notes | Capture decisions and context during development |
| /scratchpad | Track work across sessions for continuity |
Commands directory: commands in dotfiles
Agent Docs: Reference Material on Demand
Markdown files in .claude/.agent/ that Claude reads when relevant. Skills encode how to do things. Agent docs provide reference material—what things are.
| Doc | Purpose |
|---|---|
| coding-patterns.md | TypeScript patterns reference |
| anti-patterns.md | What to avoid |
| error-handling.md | Error handling conventions |
| testing-patterns.md | Testing approaches |
| bug-investigation.md | Debugging strategies |
| code-review-checklist.md | PR review checklist |
CLAUDE.md tells Claude when to read each doc. More efficient than stuffing everything into context—docs load on demand.
Agent docs: .agent in dotfiles
Plugins: Extending Capabilities
Plugins add tools and workflows to Claude’s toolkit. I use several:
Core Tools
ast-grep — Structural code search using AST patterns. Better than regex for multi-line patterns or variable formatting. Find all functions returning a Promise without error handling? ast-grep finds them regardless of formatting. Requires the CLI:
# Install the CLI tool
brew install ast-grep
# Add the marketplace and install the Claude Code plugin
/plugin marketplace add ast-grep/claude-skill
/plugin install ast-grepdev-browser — Browser automation. “Go to localhost:3000 and click the login button”—Claude can actually do that.
/plugin marketplace add sawyerhood/dev-browser
/plugin install dev-browser@sawyerhood/dev-browserfrontend-design — UI/UX design assistance for frontend work. Part of the official Claude Code plugins.
/plugin marketplace add anthropics/claude-code
/plugin install frontend-design@claude-code-pluginsWorkflow Automation
hookify — Creates enforcement rules from markdown files. The key plugin for active convention enforcement.
commit-commands — Three git commands:
- /commit — Auto-generates commit messages matching your repo’s style
- /commit-push-pr — Branch → commit → push → PR in one command
- /clean_gone — Removes stale local branches deleted from remote
feature-dev — 7-phase structured workflow for complex features:
- Discovery (clarify requirements)
- Codebase Exploration (launches code-explorer agents)
- Clarifying Questions (fills gaps)
- Architecture Design (launches code-architect agents with options)
- Implementation (with approval gates)
- Quality Review (launches code-reviewer agents)
- Summary
For complex features touching multiple files, /feature-dev ensures nothing is missed.
Code Quality
pr-review-toolkit — Six review agents running in parallel:
| Agent | Focus |
|---|---|
| comment-analyzer | Comment accuracy, documentation completeness |
| pr-test-analyzer | Test coverage gaps, behavioral coverage |
| silent-failure-hunter | Empty catch blocks, swallowed errors |
| type-design-analyzer | Type encapsulation, invariant enforcement |
| code-reviewer | CLAUDE.md compliance, bug detection |
| code-simplifier | Unnecessary complexity, redundant code |
“Review my PR”—six agents analyze different dimensions simultaneously, return prioritized findings.
Autonomous Loops
ralph-wiggum — Iterative self-referential loops for complex tasks. Named after the Simpsons character, it embodies “persistent iteration despite setbacks.”
The mechanism: a stop hook intercepts Claude’s exit attempts and feeds the same prompt back. Each iteration sees modified files and git history. Claude improves by reading its own past work.
/ralph-loop "Build a REST API for todos. Requirements: CRUD, validation, tests.
Output <promise>COMPLETE</promise> when done." --completion-promise "COMPLETE" --max-iterations 50Claude will:
- Implement the API
- Run tests, see failures
- Fix bugs based on test output
- Iterate until requirements met
- Output the completion promise
The tradeoff: you give up control for autonomy. Good for greenfield projects with clear success criteria and automatic verification (tests, linters). Not good for tasks requiring design judgment or unclear goals. Always use --max-iterations as a safety net.
Real results from the technique: 6 repositories generated overnight in Y Combinator testing, one $50k contract completed for $297 in API costs.
Database Tools
pg — PostgreSQL and TimescaleDB expertise via MCP. Semantic search over Postgres docs, hypertable design guidance, migration strategies.
Commands:
- /pg:design-postgres-tables — Schema design with proper types, indexes, constraints
- /pg:setup-timescaledb-hypertables — Partition columns, compression, retention policies
- /pg:find-hypertable-candidates — Analyze existing tables for hypertable conversion
The tradeoff: adds latency for database questions (MCP server calls). Worth it if you’re doing serious Postgres work. Skip it for SQLite or other databases.
Plugin Installation
Official plugins require adding the Anthropic marketplace first:
# Add official marketplace
/plugin marketplace add anthropics/claude-code
# Install official plugins
/plugin install hookify@claude-code-plugins
/plugin install pr-review-toolkit@claude-code-plugins
/plugin install commit-commands@claude-code-plugins
/plugin install feature-dev@claude-code-plugins
/plugin install frontend-design@claude-code-plugins
/plugin install ralph-wiggum@claude-code-plugins
# Third-party plugins (add their marketplace first)
/plugin marketplace add ast-grep/claude-skill
/plugin install ast-grep
/plugin marketplace add sawyerhood/dev-browser
/plugin install dev-browser
# MCP-based plugins
/mcp add pg -- npx -y @anthropic-ai/pg-mcpEnable them in settings.json:
"enabledPlugins": {
"frontend-design@claude-code-plugins": true,
"dev-browser@dev-browser-marketplace": true,
"ast-grep@ast-grep-marketplace": true,
"hookify@claude-code-plugins": true,
"pr-review-toolkit@claude-code-plugins": true,
"commit-commands@claude-code-plugins": true,
"feature-dev@claude-code-plugins": true,
"ralph-wiggum@claude-code-plugins": true,
"pg@aiguide": true
}Setting This Up: A Practical Guide
Quick Start
Install my skills, commands, and hooks:
curl -sL https://raw.githubusercontent.com/stevenmays/dotfiles/master/ai/claude/install.sh | bashSets up ~/.claude/ and prints the plugin commands to run inside Claude Code.
Manual Setup
If you prefer doing it yourself:
1. Create the Directory Structure
mkdir -p ~/.claude/skills
mkdir -p ~/.claude/commands
mkdir -p ~/.claude/hooks2. Add Settings
cat > ~/.claude/settings.json << 'EOF'
{
"alwaysThinkingEnabled": true,
"env": {
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "64000"
}
}
EOF3. Add Skills
Create ~/.claude/skills/typescript-patterns/SKILL.md with your TypeScript conventions. The filename must be SKILL.md and include frontmatter with name and description.
4. Add Commands
Create ~/.claude/commands/analyze-bug.md with your debugging workflow. Commands are invoked with /analyze-bug (the filename becomes the command name).
5. Install Plugins
# Install ast-grep CLI (required for the plugin)
brew install ast-grep
# Add marketplaces
/plugin marketplace add anthropics/claude-code
/plugin marketplace add ast-grep/claude-skill
/plugin marketplace add sawyerhood/dev-browser
# Install plugins
/plugin install hookify@claude-code-plugins
/plugin install pr-review-toolkit@claude-code-plugins
/plugin install commit-commands@claude-code-plugins
/plugin install feature-dev@claude-code-plugins
/plugin install frontend-design@claude-code-plugins
/plugin install ast-grep
/plugin install dev-browser6. Create Hooks
After installing hookify, create enforcement rules:
# Interactive: describe the behavior you want to enforce
/hookify Warn me when I use .forEach() instead of for...of
# Or create manually in ~/.claude/hooks/Hooks take effect immediately—no restart required.
7. Add CLAUDE.md to Projects
Create CLAUDE.md at the root of each project with project-specific instructions.
My complete configuration: github.com/stevenmays/dotfiles/tree/master/ai/claude
The Compounding Effect
These customizations compound. That’s what I didn’t expect.
Skill teaches TypeScript conventions → Claude knows my preferences. Hook enforces those conventions → Claude can’t forget them. Command structures bug investigation → debugging follows a consistent process. Plugin runs six review agents → PR reviews are thorough without being tedious.
Each layer reinforces the others:
| Layer | Function | Example |
|---|---|---|
| Skills | Teach conventions | ”Prefer for…of over .forEach()“ |
| Hooks | Enforce conventions | Warn when .forEach() is used |
| Commands | Trigger workflows | /analyze-bug runs 6-step investigation |
| Plugins | Add capabilities | pr-review-toolkit runs 6 agents in parallel |
A few hours of setup pays dividends on every subsequent session. No more re-explaining preferences. No more correcting patterns. Claude already knows. And when it forgets, the hooks catch it.
The tradeoff is straightforward: accept defaults and work around quirks, or spend a few hours dialing it in.
I know which one I picked.
Resources:
- My Claude Code dotfiles — Skills, commands, hooks, and configuration
- Claude Code documentation
- Claude Code plugins repository
References:
- Writing a Good CLAUDE.md — HumanLayer’s guide on crafting effective CLAUDE.md files with progressive disclosure
- My Experience with Claude Code 2.0 — Sankalp’s guide on getting better at using coding agents
- Boris Cherny on Claude Code workflows



