· 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.

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

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 rules

The 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 codepaths

AI 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.png

The 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:

HookActionWhat It Catches
warn-any-typewarn: any, <any>, any[]
block-as-anyblockas any casts
warn-as-syntaxwarnas Type (prefer <Type>)
warn-foreachwarn.forEach() (prefer for…of)
warn-interface-prefixwarninterface IFoo
warn-debug-codewarnconsole.log, debugger
warn-default-importwarnDefault imports (prefer namespace)
block-hardcoded-secretsblockHardcoded 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: **&lt;SpecificType&gt;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.

CommandPurpose
/analyze-bug6-step root cause analysis for stubborn bugs
/simplifyReduce code complexity while preserving behavior
/plan-featureBreak complex features into implementable stages
/review-diffReview code changes against project guidelines
/fix-typesFix TypeScript type errors systematically
/take-notesCapture decisions and context during development
/scratchpadTrack 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.

DocPurpose
coding-patterns.mdTypeScript patterns reference
anti-patterns.mdWhat to avoid
error-handling.mdError handling conventions
testing-patterns.mdTesting approaches
bug-investigation.mdDebugging strategies
code-review-checklist.mdPR 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-grep

dev-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-browser

frontend-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-plugins

Workflow 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:

  1. Discovery (clarify requirements)
  2. Codebase Exploration (launches code-explorer agents)
  3. Clarifying Questions (fills gaps)
  4. Architecture Design (launches code-architect agents with options)
  5. Implementation (with approval gates)
  6. Quality Review (launches code-reviewer agents)
  7. Summary

For complex features touching multiple files, /feature-dev ensures nothing is missed.

Code Quality

pr-review-toolkit — Six review agents running in parallel:

AgentFocus
comment-analyzerComment accuracy, documentation completeness
pr-test-analyzerTest coverage gaps, behavioral coverage
silent-failure-hunterEmpty catch blocks, swallowed errors
type-design-analyzerType encapsulation, invariant enforcement
code-reviewerCLAUDE.md compliance, bug detection
code-simplifierUnnecessary 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 50

Claude will:

  1. Implement the API
  2. Run tests, see failures
  3. Fix bugs based on test output
  4. Iterate until requirements met
  5. 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-mcp

Enable 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 | bash

Sets 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/hooks

2. Add Settings

cat > ~/.claude/settings.json << 'EOF'
{
  "alwaysThinkingEnabled": true,
  "env": {
    "CLAUDE_CODE_MAX_OUTPUT_TOKENS": "64000"
  }
}
EOF

3. 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-browser

6. 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:

LayerFunctionExample
SkillsTeach conventions”Prefer for…of over .forEach()“
HooksEnforce conventionsWarn when .forEach() is used
CommandsTrigger workflows/analyze-bug runs 6-step investigation
PluginsAdd capabilitiespr-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:

References:

Back to Blog

Related Posts

View All Posts »