Claude Code Advanced Guide (Part 2): Skills, Sub-Agents, MCP, Hooks, and Plugins
In Part 1, we covered the fundamentals of Claude Code, including setup, slash commands, code modifications, context management, CLAUDE.md…
Claude Code Advanced Guide (Part 2): Skills, Sub-Agents, MCP, Hooks, and Plugins
In Part 1, we covered the fundamentals of Claude Code, including setup, slash commands, code modifications, context management, CLAUDE.md, and Plan Mode.
In this guide, we’ll explore the advanced capabilities that transform Claude Code from a coding assistant into a powerful development platform. You’ll learn how to automate workflows with custom slash commands, create reusable skills, build specialized sub-agents, connect external tools through MCP, enforce rules with hooks, and package everything into reusable plugins.

Table of Contents
- Custom Slash Commands
- Skills
- Sub-Agents
- Custom Sub-Agents
- MCP (Model Context Protocol)
- Hooks
- Plugins
1. Custom Slash Commands
What Are Custom Slash Commands?
Custom slash commands are nothing but prompts — prompts you’ve saved somewhere and that get automatically invoked when you type a slash command name inside Claude Code. Just like built-in slash commands, but defined by you.
You use them for any workflow that’s repeatable — something you run again and again across your project. Instead of typing out the same instructions every time, you package them into a single command.
Examples of good candidates:
/review — run a code review on whatever file was just written. Code review is something you do after every feature, so it's a perfect fit.
/commit — generate a Git commit message by reading what changed. Committing is a repeatable step at the end of every feature cycle.
/test — run your test suite against the current code. Testing happens after every feature.
/security-scan — scan the entire codebase for vulnerabilities. Done multiple times across the lifecycle of a project.
/seed-user — insert a dummy user into the database for development testing.
/seed-expense — insert dummy expenses for a specific user with configurable inputs.
/create-spec — generate a full spec document for a new feature automatically.
Custom slash commands are user-defined workflows saved as markdown files and invoked via slash syntax. Automate anything repeatable.
How to Create One
Three steps:
- Create a markdown file describing what the command should do
- Save it inside
.claude/commands/(project-level) or~/.claude/commands/(global) - Restart Claude Code — it auto-detects the new command
The filename becomes the command name. A file called seed-user.md becomes /seed-user. A file called create-spec.md becomes /create-spec.
After creating or editing a command file, always exit and restart Claude Code (
/exit→claude). New commands won't appear until the session restarts.
Two Scopes
Project-scoped — saved inside your project’s .claude/commands/ folder. Only available in this project. Committed to Git, shared with your team. Invoked as /project:commandname.
User-scoped (global) — saved inside ~/.claude/commands/ in your home directory. Available across all projects on your machine. Never shared with teammates.
Project-scopedUser-scopedLocation.claude/commands/ in project root~/.claude/commands/Available inThis project onlyAll projectsShared with team?Yes — lives in GitNo — stays on your machineInvoked as/project:commandname/commandname
Anatomy of a Command File
Every command markdown file has the same structure:
description ← shown in the slash menu when you type /
argument-hint ← hints shown when you type the command + space
allowed-tools ← which tools this command can use
(Read, Write, Glob, Bash(python3:*), Bash(git:*) etc.)
[Body] ← the full prompt: step-by-step instructions telling
Claude exactly what to do when this command runs
Accepting inputs — use $ARGUMENTS in your command body. Whatever the user types after the command name gets passed into $ARGUMENTS. Extract what you need from it at the start of your prompt.
_Example: /seed-expense 1 10 6 → $ARGUMENTS = "1 10 6" → extract userid=1, count=10, months=6
Example 1 — /seed-user
File: .claude/commands/seed-user.md Purpose: Insert one realistic dummy Indian user into the database for development testing.
description Create a single dummy user in the database
allowed-tools Read, Bash(python3:*)
Read database/db.py to understand the users table schema and the get_db() helper.
Then write and run a Python script using Bash that:
Generates a realistic random Indian user using your own knowledge of
common Indian names across regions:
- Name: a realistic Indian first + last name
- Email: derived from the name with a random 2-3 digit number suffix
(e.g. rahul.sharma91@gmail.com)
- Password: "password123" hashed with werkzeug's generate_password_hash
- created_at: current datetime
Checks if the generated email already exists in the users table.
If it does, regenerate until unique.
Inserts the user into the database using the same get_db() pattern found in db.py.
Prints confirmation:
- id
- name
- email
How to invoke: /seed-user — no arguments needed.
Example 2 — /seed-expense
File: .claude/commands/seed-expense.md Purpose: Insert dummy expenses for a specific user, with configurable count and date range.
description Seed realistic dummy expenses for a specific user
argument-hint <user_id> <count> <months>
allowed-tools Read, Bash(python3:*)
Read database/db.py to understand the expenses table schema,
the db connection pattern, and the database file name.
User input: $ARGUMENTS
Step 1 — Parse arguments
Extract from $ARGUMENTS:
- user_id — integer
- count — integer, number of expenses to create
- months — integer, how many past months to spread them across
If any argument is missing or not a valid integer, stop and say:
"Usage: /seed-expense <user_id> <count> <months> Example: /seed-expense 1 50 6"
Step 2 — Verify user exists
Before generating anything, confirm the user_id exists in the users table.
If not, stop and say: "No user found with id <user_id>."
Step 3 — Generate and insert expenses
Write and run a Python script that:
- Spreads expenses randomly across the past <months> months
- Uses these categories with realistic Indian amounts (₹):
Food: ₹50–800
Transport: ₹20–500
Bills: ₹200–3,000
Health: ₹100–2,000
Entertainment: ₹100–1,500
Shopping: ₹200–5,000
Other: ₹50–1,000
- Distributes categories roughly proportionally
(Food most common, Health and Entertainment least)
- Uses the db connection pattern from db.py — do not hardcode the filename
- Uses parameterised queries only — no string formatting in SQL
- Inserts all expenses in a single transaction — roll back if any insert fails
Step 4 — Confirm
Print:
- How many expenses were inserted
- The date range they span
- A sample of 5 inserted records
How to invoke: /seed-expense 2 10 3 — user ID 2, 10 expenses, spread across the last 3 months.
Example 3 — /create-spec
File: .claude/commands/create-spec.md Purpose: Automate the entire spec-document creation process for a new feature — including Git branch creation. Previously this was done manually; this command replaces that entire step.
description Create a spec file and feature branch for the next Spendly step
argument-hint Step number and feature name e.g. 2 registration
allowed-tools Read, Write, Glob, Bash(git:*)
You are a senior developer spinning up a new feature for the Spendly expense tracker.
Always follow the rules in CLAUDE.md.
User input: $ARGUMENTS
Step 1 — Check working directory is clean
Run git status and check for uncommitted, unstaged, or untracked files.
If any exist, stop immediately and tell the user to commit or stash changes
before proceeding. DO NOT CONTINUE until the working directory is clean.
Step 2 — Parse the arguments
From $ARGUMENTS extract:
- step_number — zero-padded to 2 digits: 2 → 02, 11 → 11
- feature_title — human readable title in Title Case
Example: "Registration" or "Login and Logout"
- feature_slug — git and file safe slug
Lowercase, kebab-case. Only a-z, 0-9 and -. Max 40 characters.
Example: registration, login-logout
- branch_name — format: feature/<feature_slug>
Example: feature/registration
If you cannot infer these from $ARGUMENTS, ask the user to clarify before proceeding.
Step 3 — Check branch name is not taken
Run git branch to list existing branches. If branch_name is already taken,
append a number: feature/registration-01, feature/registration-02 etc.
Step 4 — Switch to main and pull latest
Run:
git checkout main
git pull origin main
Step 5 — Create and switch to the feature branch
Run:
git checkout -b <branch_name>
Step 6 — Research the codebase
Read these files before writing the spec:
- CLAUDE.md — roadmap, conventions, schema
- app.py — existing routes and structure
- database/db.py — existing schema and functions
- All files in .claude/specs/ — avoid duplicating existing specs
Check CLAUDE.md to confirm the requested step is not already marked complete.
If it is, warn the user and stop.
Step 7 — Write the spec
Generate a spec document with this exact structure:
Spec: <feature_title>
Overview
One paragraph describing what this feature does and why it exists
at this stage of the Spendly roadmap.
Depends on
Which previous steps this feature requires to be complete.
Routes
Every new route needed:
METHOD /path — description — access level (public/logged-in)
If no new routes: state "No new routes".
Database changes
Any new tables, columns, or constraints. Always verify against database/db.py.
If none: state "No database changes".
Templates
Create: list new templates with their path
Modify: list existing templates and what changes
Files to change
Every file that will be modified.
Files to create
Every new file that will be created.
New dependencies
Any new pip packages. If none: state "No new dependencies".
Rules for implementation
Specific constraints Claude must follow. Always include:
- No SQLAlchemy or ORMs
- Parameterised queries only
- Passwords hashed with werkzeug
- Use CSS variables — never hardcode hex values
- All templates extend base.html
Definition of done
A specific testable checklist. Each item must be verifiable by running the app.
Step 8 — Save the spec
Save to: .claude/specs/<step_number>-<feature_slug>.md
Step 9 — Report to the user
Print a short summary in this exact format:
Branch: <branch_name>
Spec file: .claude/specs/<step_number>-<feature_slug>.md
Title: <feature_title>
Then tell the user:
"Review the spec at .claude/specs/<step_number>-<feature_slug>.md
then enter Plan Mode with Shift+Tab twice to begin implementation."
Do not print the full spec in chat unless explicitly asked.
How to invoke: /create-spec 3 login-and-logout
This single command: checks the working directory is clean → parses the feature name → checks no duplicate branch exists → pulls latest from main → creates and switches to a new feature branch → reads the entire codebase for context → writes a complete spec document → saves it to .claude/specs/ → reports back with branch name and spec path.
Before this command existed, all of these steps were done manually. Now the entire spec creation + branch setup is one command.
The Full Automated Feature Workflow
With these custom commands in place, the full feature development flow looks like this:

What used to require manually writing spec documents and running Git commands is now a single slash command followed by Plan Mode.
Best Practices
Be very specific in your command body — the more precise your instructions, the more consistent the output. Vague instructions = vague results, just like with any prompt.
Use $ARGUMENTS for flexible commands — any command that needs user input (user ID, feature name, count) should extract it from $ARGUMENTS and validate it before proceeding.
Always restart after creating a command — new command files don’t appear until you exit and relaunch Claude Code.
Keep allowed-tools tight — only grant the tools the command actually needs. Don’t give a read-only command write access.
Use commands for repeatable workflows, not one-offs — if you’re only doing something once, just type the prompt directly. Custom commands earn their place when you’d otherwise type the same thing five or more times across a project.
Quick Reference

2. Skills
The Problem Skills Solve
LLMs like Claude are general-purpose models. They can reason, write, and code across many domains — but there’s a consistent gap between general capability and reliable, high-quality output for a specialized task type.
A concrete example: PPT generation. Claude knows what a PowerPoint is. It knows how to structure slides from a discussion. It knows which Python libraries to use. But it doesn’t know your company’s design guidelines — what layout to use, which fonts to pick, when to use graphs vs. tables vs. charts. Claude has general capability, but not the specialized knowledge your specific task requires.
This problem appears everywhere: front-end design (what does your company’s website style look like?), data analysis (how does your team structure EDA?), document writing (what’s your personal writing style?), code reviews (how does your senior dev actually like to review code?).
LLMs are good at general reasoning — but they don’t do well on specialized, repeatable tasks without extra context.
Why Prompts Aren’t the Answer
The obvious solution is to write a detailed prompt with all the instructions. That works once, but it creates five new problems:
You have to retype it every time — for any repeatable task, this gets tedious and error-prone.
It burns your context window — if you paste it as a system prompt, it occupies context window space whether or not you’re using that skill right now.
You can’t bundle resources — what if the skill needs reference images, design templates, or Python scripts? You can’t attach those to a prompt.
You can’t share, version, or improve a prompt — prompts live in your head. They don’t go to Git. Your teammates can’t collaborate on them or improve them.
Prompts don’t compose — what if one task needs three specialized sub-tasks in sequence (read a PDF → extract tables → generate PPT)? One giant combined prompt confuses the LLM. You can’t chain prompts the way you can chain skills.
Skills solve all five of these problems.
What Are Skills?
Skills are reusable, file-based resources that provide Claude with domain-specific expertise — workflows, context, and best practices — that transform general-purpose agents into specialists.
A skill is a folder inside your project. Inside that folder lives a SKILL.md file, plus any supporting resources the skill needs.
The best part: skills load automatically on demand. If you’re having a normal conversation and haven’t mentioned PPTs, the PPT skill doesn’t load. The moment you ask Claude to create a PPT, it recognizes the need, finds the right skill, loads it, reads the instructions, and executes accordingly.
Skill Folder Structure
.claude/
└── skills/
├── frontend-design/ ← one skill = one folder
│ ├── SKILL.md ← required — the full instruction file
│ ├── templates/ ← optional — reference images, design examples
│ └── scripts/ ← optional — Python/bash scripts the skill uses
│
└── data-analysis/ ← another skill
├── SKILL.md
└── scripts/
└── eda_template.py
Every skill is its own folder. SKILL.md is required — without it, the skill won't work. Supporting folders (templates, scripts, etc.) are optional, added only when the skill needs external resources.
Inside SKILL.md — Two Parts
Every SKILL.md file has the same structure: a YAML front matter at the top, followed by the markdown body.
1. YAML Front Matter
---
name: Frontend Design
description: >
Load this skill whenever the user asks to build, design, or improve
any frontend UI — HTML pages, CSS styling, component design, or
visual layout decisions.
---
The name is how Claude identifies the skill. The description is the trigger — Claude reads all skill descriptions at the start of every session. When a user message matches, Claude loads that skill’s full body. The description is effectively the skill’s activation condition.
Write the description carefully. It’s the only thing Claude reads until the skill is actually needed.
2. Markdown Body
Everything else — the full detailed instructions for how to execute the specialized task. This is where you write:
- Step-by-step workflows
- Design rules and constraints
- Coding patterns and conventions
- What to avoid
- Validation steps
- Links to supporting files in the
scripts/ortemplates/folders
Example link in body: “To plot a distribution chart, use the script at ./scripts/plot_distribution.py."
How Skills Load — Progressive Disclosure
The loading process is called progressive disclosure: don’t present information until the moment it’s needed.
Level 1 — Always loaded: All skill descriptions (YAML front matter only) load at session start. These are tiny — just a name and a description. If you have 10 skills, all 10 descriptions load, so Claude always knows what tools are available.
Level 2 — On demand: When a user message matches a skill’s description, Claude loads the full SKILL.md body for that skill. The body is only read when needed — not upfront.
Level 3 — On demand: If the skill body references external files (scripts, templates), those files are fetched only when the body’s instructions require them.
This is why skills solve the context window problem that prompts don’t — a 20,000-token instruction file stays on disk until it’s actually needed, rather than occupying context window space for the entire session.
Two Types of Skills
Personal skills — saved in ~/.claude/skills/ in your home directory. Available across all your projects on your machine. Use these for your personal coding style, writing style, or design preferences that you want consistent everywhere.
Project skills — saved in .claude/skills/ inside your project folder. Only available in this project. Committed to Git, shareable with teammates, versionable, improvable. Use these for project-specific workflows like your team's front-end design system or your company's data analysis conventions.
Personal SkillsProject SkillsLocation~/.claude/skills/.claude/skills/ in project rootScopeAll your projectsThis project onlyShared with team?NoYes — via GitUse forPersonal style + preferencesProject-specific workflows
Three Ways to Create Skills
-
Manually — Create the folder, create
SKILL.md, write the instructions. Works, but not recommended for beginners — the format takes practice to get right. -
Using Claude’s Skill Creator — In claude.ai, click the
+icon → Skills → Skill Creator. This is itself a skill that Anthropic ships by default, designed to help you build other skills. It asks you three questions: what does the skill do, when should it trigger, and what does success look like? Then it generates the fullSKILL.mdfor you. Copy the output into your project's.claude/skills/<skill-name>/SKILL.md. Recommended approach for beginners. -
From community sources — Search for “Claude skills marketplace” to find skills others have built across different domains (marketing, data, coding). Anthropic also has a public repository of standard skills.
⚠️ Be careful with community skills. Read the full
SKILL.mdbefore using — there have been reported cases of community skills exfiltrating API keys. Anthropic's official repository is the safer source.
Steps to Create a Skill
- Identify the need — only build a skill for tasks that are specialized AND repeatable. Not every workflow needs a skill.
- Create the folder —
mkdir .claude/skills/<skill-name> - Write
SKILL.md— YAML front matter with name + description trigger, then the full instruction body with any resource links. - Add supporting resources — scripts, templates, reference files in subfolders if needed.
- Test it — restart Claude Code (new skills don’t load until restart) and run a task that should trigger the skill. Watch whether it auto-loads correctly.
- Iterate — a first-attempt skill is rarely perfect. Test, find gaps, improve the instructions, test again. Four to five iterations usually yields a usable skill.
After creating or editing a skill, always restart Claude Code. Skills don’t activate in a running session.
Skills vs. Prompts — Head to Head

Skills and Commands — Merged
Anthropic has merged commands and skills into a single concept. Going forward, there is no separate commands/ folder structure. Everything lives in skills/.
The file structure is identical — a folder with a SKILL.md file. The difference between a skill and a command is now controlled by a single flag in the YAML front matter:
---
name: Create Spec
description: Create a spec file and feature branch for a new feature.
disable_model_invocation: true ← this makes it behave like a command
---
Without the flag — Claude can auto-invoke the skill whenever it detects relevance. This is standard skill behavior.
With disable_model_invocation: true — Claude will never auto-invoke it. Only you can trigger it explicitly via /skill-name. This is command behavior.
Both can be accessed via slash syntax. The distinction is just whether Claude can decide to load it on its own or only you can.
Going forward: build everything as skills. Use
disable_model_invocation: truefor anything you only want to invoke manually.
Quick Reference

3. Sub-Agents
Why Sub-Agents Exist — The Core Problem
When you chat with an LLM-based coding agent, every new message you send doesn’t just send your current question — it sends your entire conversation history along with it. The LLM is stateless, so the application replays the full context every turn to maintain continuity.
This works fine for chat apps. It breaks badly for coding agents working on large codebases.
The Stateless Problem
LLMs have no memory between API calls. If you ask “What’s the capital of France?” and it replies “Paris,” then immediately ask “What about Germany?” — the LLM has no idea what you’re referring to. The fix is simple: send the entire conversation history with every new message so the LLM always has full context.
This works — until your codebase enters the picture.
The Escalation — A Real Example
Imagine a 30,000-token codebase (15–20 files). You ask your agent to build an auth system.

By turn 8, you’re sending 76,000 tokens per message. Running total across 8 turns: 380,000 tokens. The codebase (30k tokens) is re-sent every single turn, unchanged. After the first turn, the LLM already understood it — but because calls are stateless, you keep paying 30k tokens every message just to carry information the model already processed.
The Two Real Dangers
- Context Window Overflow
Your codebase + conversation can exceed the model’s maximum context window. When it overflows, the model silently drops your oldest code from context. The files it loses, it can no longer see. This is silent, invisible corruption — the model “forgets” key parts of your code and confidently writes new code as if those files don’t exist.
- Lost in the Middle Effect
LLMs pay most attention to the start and end of context. The middle gets foggy. Your critical code files sitting in the middle of a huge context get ignored. The LLM “forgets” key parts of your codebase and confidently writes conflicting or broken new code.
The takeaway: Because LLM calls are stateless, coding assistants must re-send your entire codebase + full conversation history with every single message. This means longer conversations = exponentially more tokens = higher costs, eventual context overflow, and degraded code quality — all without any visible warning.
What Are Sub-Agents?
Sub-agents are specialized AI assistants that run in their own isolated context windows, do heavy lifting in a separate space, and hand back only what matters.
When you’re talking to Claude Code, you’re talking to the main agent. That main agent can spin up completely new agents — sub-agents — each with their own fresh 200K context window. The sub-agent does its work in isolation, returns a compact summary or result, and its context is then destroyed. The main agent only keeps the output, not the full working memory.
This is exactly like a function call in programming — you don’t care what happens inside the function, you care about the return value.
How It Works — The Auth Example
Without a planning sub-agent:
You paste the codebase into chat and ask “Build me an auth system.” The full codebase (30k tokens) stays in context for the entire conversation.

The codebase (30k tokens) is re-sent every single turn, unchanged.
With a planning sub-agent:
Step 1 — Main agent spawns a planning sub-agent as a separate, one-shot LLM call. Input: full codebase (30k tokens). Task: analyze and produce a structured auth implementation plan. This call costs ~30k tokens — one time only.
The sub-agent returns an Auth Implementation Plan (~2,000 tokens):
- Add users table (id, email, hash, role)
- JWT middleware in middleware.js — use existing errorHandler pattern
- Auth routes: POST /login, /register, /refresh
- Guard existing routes via middleware chain
- Rate limit on /login (existing Redis config)
Step 2 — Main agent works from the plan — not the codebase.

~28,000 tokens saved per turn. The context stays lean for every subsequent turn.
Advantages of Sub-Agents
Context Isolation (core advantage) — each sub-agent gets a fresh isolated context window. Without sub-agents, your growing conversation carries the full codebase every turn. With a sub-agent, analysis happens in its own space and only a concise summary returns to the main agent. The main conversation stays clean and small.
Specialization — each agent gets its own toolkit. An Auditor, a Writer, a Researcher — each configured with exactly the tools, model, and prompt it needs. Nothing more, nothing less.
Modularity — different stages of the development lifecycle become separate agents, just like functions in code:
analyze(codebase) → returns insights
implement(plan) → returns code
review(code) → returns feedback
test(implementation) → returns results
Parallelism — sequential vs parallel execution:
Sequential: Task A → Task B → Task C (total: A + B + C time)
Parallel: Task A
Task B (all at once)
Task C
(total: max(A, B, C) time)
Multiple sub-agents run simultaneously on independent tasks. Three services that don’t depend on each other? Three sub-agents build them in parallel.
Top Use Cases
1. Codebase Exploration
Any time Claude needs to understand a large codebase, an explore sub-agent handles it. The sub-agent scans all files in its own isolated workspace — auth.ts, routes.ts, models.py, utils.ts, config.yaml, schema.sql, db.ts — spending ~30k tokens doing thorough analysis. It returns only the findings to the main agent:
“12 Express routes, no auth middleware. Prisma ORM, no User model yet. Redis configured, can use for sessions.”
Context destroyed after — 30k tokens freed. Main agent carries only the compact findings going forward.
Claude Code triggers this automatically. You don’t need to ask.
2. Independent Code Review
The main agent wrote the code — it knows the trade-offs considered, knows the rejected approaches, knows the assumptions made. This creates inherent bias.
A review sub-agent starts fresh — sees only the final code, has no context about past decisions, evaluates purely on code quality. It catches what the author missed: blind spots the original agent couldn’t see because of its own assumptions.
3. Testing
Same logic as code review. The agent that implemented the feature tends to write tests that validate its own assumptions. A separate testing sub-agent with no knowledge of the implementation writes more thorough, less biased tests.
4. Multi-Stage Pipelines
When output from one stage becomes input to the next:
Stage 1 — Design Stage 2 — Implement Stage 3 — Test
POST /login → authController.ts → login flow
POST /register jwtMiddleware.ts token refresh
POST /refresh tokenModel.ts auth guard
↓ outputs: API contract ↓ outputs: working code ↓ outputs: integration tests
Each stage is a separate sub-agent. Handoffs between agents are clean. Each stage only sees what it needs.
5. Parallel Independent Tasks
When tasks don’t depend on each other, run them simultaneously:
“Investigate outage across 3 services”
→ auth-service (analyzing logs)
→ payment-service (analyzing logs) ← all running at the same time → 3x faster
→ user-service (analyzing logs)
↓ combined incident timeline
vs. sequential execution where you wait for each one to finish before starting the next.
6. Security Auditing
The Builder wrote the code. The Breaker looks for vulnerabilities.
Builder (main agent) Breaker (security sub-agent)
focused on implementation → focused on finding flaws
authController.ts → SQL injection in user lookup query
jwtMiddleware.ts → JWT secret hardcoded in config
A dedicated security agent reviews with fresh eyes — no bias from knowing how or why the code was written.
How Sub-Agents Get Triggered
Two ways:
Automatic — Claude recognizes the task needs a sub-agent and delegates on its own. “Add auth” → Claude spawns Explore first without you asking.
Explicit — you tell Claude which sub-agent to use by name. “Use code-reviewer agent on auth” — Claude follows your instruction directly.
Types of Sub-Agents
Built-in Sub-Agents
Claude Code ships with three built-in sub-agents:
Explore sub-agent — triggered for codebase exploration. Reads and maps the full codebase, returns a compact summary to the main agent.
Plan sub-agent — triggered in Plan Mode. Takes a spec document, analyzes the codebase, produces a structured implementation plan.
General-purpose sub-agent — triggered for read and write tasks the main agent decides to delegate.
Custom Sub-Agents
Sub-agents you define yourself using markdown files with YAML front matter.
Where they live:
LocationScope.claude/agents/Project-level — shared with team via Git~/.claude/agents/User-level — personal, all projects
What you configure:
- Tools — exactly which tools the agent can access
- Prompt — the agent’s system prompt and specialization
- Model — which Claude model it uses
- Permissions — what operations it can perform
- Hooks — event-based triggers
- Skills — which skills it has access to
Three example custom agents:
Security Reviewer
Tools: Read, Grep, Glob
Model: Opus (high quality)
Prompt: "Review for injection, auth bypass,
and data exposure vulnerabilities."
Research Agent
Tools: Read, Grep, Glob, WebFetch, WebSearch
Model: Sonnet (balanced)
Prompt: "Research best practices and patterns."
Code Writer
Tools: Read, Write, Edit, Bash, Grep
Model: Sonnet (balanced)
Prompt: "Implement clean, tested, typed code."
Compose these three elements — tools + prompt + model — to create exactly the agent you need.
Observing Sub-Agents in Action
Claude Code doesn’t visually show you when sub-agents fire by default. To see them in real time, use the agents-observe library — an open-source real-time observability dashboard built using Claude Code’s hooks feature.
# After installing agents-observe
observe start
Navigate to the dashboard URL and you’ll see your main agent and any sub-agents as they spawn, work, and stop — in real time, with every tool call visible.
When you run “explore the codebase,” you’ll see an explore sub-agent appear, fire a series of Read tool calls across your files, then stop — control returns to the main agent.
When you run Plan Mode, you’ll typically see: explore sub-agents first (to understand the codebase), then a plan sub-agent (to generate the plan), then one or more general-purpose sub-agents to implement it.
Parallel Sub-Agents in Practice
When tasks are independent — different files, different services, different datasets — instruct Claude to split work explicitly in your prompt:
Read .claude/specs/05-backend-routes.md and generate an implementation plan.
While implementing the plan, split the work across three parallel sub-agents:
- Sub-agent 1: implement the summary stats routes
- Sub-agent 2: implement the transaction history table routes
- Sub-agent 3: implement the category breakdown routes
Claude spawns all three, runs them simultaneously, then the main agent integrates their outputs.
Best practice: parallel sub-agents work cleanest when each agent works on different files. Having multiple agents modify the same file simultaneously requires the main agent to reconcile conflicts — which reduces the efficiency gain.
Quick Reference

4. Custom Sub-Agents
Why Custom Sub-Agents When Built-ins Exist?
Built-in sub-agents (Explore, Plan, General-purpose) have generic knowledge. They can do a security audit — but they don’t know your company’s specific checklist. They can write tests — but they don’t know your team’s testing conventions. They can review code — but they don’t know your project’s rules.
Custom sub-agents solve this. Whenever you need a specialized task done in a way that’s tailored to your codebase, you build your own sub-agent instead of relying on the built-in ones.
Example: a security audit sub-agent that follows your exact company checklist — not a generic one.
Whenever there’s a need for specialization, create your own sub-agent rather than relying on built-in ones.
How to Create a Custom Sub-Agent
A custom sub-agent is nothing but a markdown file with a YAML front matter. Save it in the right folder and Claude Code detects it automatically.
Two ways to create:
Method 1 — Using Claude Code’s /agents command (recommended for beginners)
/agents → Agents tab → Create new agent → Project level
→ Choose "Generate with Claude"
→ Describe what the agent should do
→ Select tools, model, color
→ Review and save the generated file
Method 2 — Create the markdown file manually Go to .claude/agents/ in your project root, create a new .md file, and write the YAML front matter + body yourself.
File location:
.claude/
└── agents/
├── spendly-test-writer.md
├── spendly-test-runner.md
├── spendly-security-reviewer.md
└── spendly-quality-reviewer.md
After creating or modifying agent files, always exit and restart Claude Code. New agents won’t be visible until the session restarts.
Anatomy of an Agent Markdown File
---
name: Spendly Test Writer
description: >
Use this agent to write pytest test cases for Spendly features.
Invoke after implementing any feature to generate tests based
on feature specs — not the implementation.
tools:
- Read
- Edit
model: claude-sonnet-4-5
color: red
---
[Body: full detailed instructions for how this agent should work]
YAML front matter fields you can configure:
name— how Claude identifies this agentdescription— the trigger: Claude reads this to know when to auto-invoke the agenttools— which tools the agent can access (Read, Edit, Write, Bash, Grep, Glob, WebSearch, WebFetch, etc.)model— which Claude model runs this agent (Opus for complex tasks, Sonnet for standard)color— visual identifier when watching agents in the observability dashboardmemory— optional persistent memory for the agentskills— which skills the agent has access tohooks— event-based triggers
Body — detailed step-by-step instructions telling the agent exactly how to do its job. This is its system prompt.
How Custom Sub-Agents Get Triggered
Automatically — Claude reads the description field and decides on its own when to invoke the agent. If you ask for something that matches an agent’s description, it fires without you asking.
Manually — you explicitly tell Claude to use a specific agent by name in your prompt. Or better: create a custom slash command that orchestrates the agent automatically as part of a workflow.
Most experienced developers prefer manual triggering — wiring sub-agents into slash commands so the entire workflow fires predictably with a single command.
Real-World Example: Testing + Code Review Workflow
Here is a complete example of using four custom sub-agents to add testing and code review stages to every feature deployment. Two slash commands orchestrate them.
The new workflow (added after every feature is implemented):

The two testing agents run sequentially — Test Runner needs the files Test Writer produces. The two review agents run in parallel — their tasks are completely independent.
Agent 1 — Test Writer
File: .claude/agents/spendly-test-writer.md
---
name: Spendly Test Writer
description: >
Use this agent to write pytest test cases for Spendly features.
Invoke after implementing any feature to generate tests based
on feature specs — not the implementation.
tools:
- Read
- Edit
model: claude-sonnet-4-5
color: red
---
What it does: Reads the spec document for the current feature, understands what the feature should do, and writes test cases from that spec — not from reading the generated code.
Why spec-based, not code-based? Generated code might be wrong. The spec is always the source of truth. Tests written from specs catch bugs. Tests written from code just validate whatever was written — including the bugs.
Test coverage: happy path tests, validation checks, HTTP semantics, edge cases, auth guard verification (logged-out users can’t access protected routes).
Output: Creates a tests/ folder with test_<feature_name>.py containing all test cases.
Agent 2 — Test Runner
File: .claude/agents/spendly-test-runner.md
---
name: Spendly Test Runner
description: >
Runs pytest test cases for a Spendly feature and generates
a structured report. Invoke after Test Writer completes.
tools:
- Read
- Bash
model: claude-sonnet-4-5
color: green
---
What it does: Verifies test files exist, runs them, and produces a structured report.
Why a separate agent from the writer? An agent that writes tests tends to also validate its own assumptions when running them. A fresh agent with no knowledge of how the tests were written runs them more objectively and catches more issues.
Report format:

Example result: 76 tests run → 73 passed → 3 failed → all 3 are test assertion issues, not implementation bugs.
Agent 3 — Security Reviewer
File: .claude/agents/spendly-security-reviewer.md
---
name: Spendly Security Reviewer
description: >
Performs a security audit on newly implemented Spendly features.
Checks for SQL injection, exposed secrets, auth bypasses,
and other vulnerabilities.
tools:
- Read
- Grep
- Glob
model: claude-opus-4-6
color: yellow
---
What it does: Reads all changed files, checks them against the project’s implementation rules (from CLAUDE.md), and flags security violations.
Primary checks: SQL injection via f-string formatting (violates “parameterized queries only” rule), hardcoded secrets or API keys, auth bypass possibilities, data exposure vulnerabilities.
Runs in parallel with the Quality Reviewer — these two tasks are independent so there’s no reason to wait for one before starting the other.
Agent 4 — Quality Reviewer
File: .claude/agents/spendly-quality-reviewer.md
---
name: Spendly Quality Reviewer
description: >
Reviews code quality for newly implemented Spendly features.
Checks for best practices, code style, and adherence to
project conventions defined in CLAUDE.md.
tools:
- Read
- Grep
- Glob
model: claude-sonnet-4-5
color: blue
---
What it does: Reviews all changed code for quality against the project’s coding standards. Checks that CSS variables are used (not hardcoded hex values), templates extend base.html, no ORMs are used, and code is clean and readable.
Slash Command 1 — /test-feature
File: .claude/commands/test-feature.md
description Writes and runs tests for a specific Spendly feature
argument-hint <spec-name> e.g. 06-date-filter-profile
allowed-tools Read, Write, Edit, Bash
Step 1 — Write tests
Use the Spendly Test Writer agent to write test cases based on
the spec at .claude/specs/$ARGUMENTS.md
Step 2 — Run tests
Use the Spendly Test Runner agent to run the generated tests
and produce a report.
Step 3 — Final output
Show a summary table:
| Test Suite | Total | Passed | Failed | Verdict |
How to invoke: /test-feature 06-date-filter-profile
The two agents run sequentially — Test Writer first, Test Runner second, because the runner needs the files the writer creates.
Slash Command 2 — /code-review-feature
File: .claude/commands/code-review-feature.md
description Runs security and quality review for a Spendly feature
argument-hint <spec-name> e.g. 06-date-filter-profile
allowed-tools Read, Grep, Glob
Step 1 — Parallel review
Launch both reviewers simultaneously:
- Spendly Security Reviewer
- Spendly Quality Reviewer
Step 2 — Unified report
Merge both reports into one consolidated code review.
Step 3 — Apply changes
If critical issues are found (e.g. f-string SQL pattern),
ask for approval before making fixes.
How to invoke: /code-review-feature 06-date-filter-profile
The two agents run in parallel — Security and Quality reviews are independent tasks that can happen simultaneously.
The Complete Feature Development Flow
With these custom sub-agents in place, every feature now goes through a full automated quality pipeline before being pushed to Git:

Best Practices
Always review generated agent files — after Claude auto-generates an agent markdown file, read it carefully. Use Claude.ai or ChatGPT to cross-check the generated instructions against your project’s context. Don’t use a generated file blindly.
Separate writers from runners — never have a single agent both write and execute something (tests, scripts, audits). Two agents doing separate jobs produce less biased, more thorough results.
Use sequential for dependent tasks — Test Writer → Test Runner must be sequential because the runner needs the writer’s output. Don’t try to parallelize dependent steps.
Use parallel for independent tasks — Security review and quality review don’t depend on each other. Always run them simultaneously.
Wire sub-agents into slash commands — don’t trigger sub-agents manually every time. Build slash commands that orchestrate them automatically so the workflow is one command, not a multi-step manual process.
Commit agent files to Git — your .claude/agents/ folder is part of the project. It should be committed so your whole team benefits from the same custom agents.
Quick Reference

5. MCP — Model Context Protocol
What Is MCP?
MCP stands for Model Context Protocol — a standardized, open way to connect any external tool, service, or data source to an LLM. It was created by Anthropic roughly a year and a half ago and has since become the industry standard. Every major player now uses it.
Before MCP, connecting an external service to an LLM required custom code — code that wasn’t standardized and broke every time the service provider changed their API. MCP solved this by providing a universal connector.
MCP is an open standard created by Anthropic that acts as a universal connector between Claude Code and external tools, services, and data sources.
Why MCP Matters for Claude Code
Right now, Claude Code’s built-in tools are: Read (read files from the filesystem), Write (create and write to files), and Bash (execute command-line commands). That’s it.
Claude Code cannot, on its own:
- Read your GitHub repos, open issues, or pull requests
- Fetch a document from Google Drive
- Pull tickets from your Jira board
- Read Slack messages or post to channels
- Query your database without writing Python
MCP changes all of this. By adding MCP servers, you give Claude Code new capabilities — directly querying your database, reading Figma designs, interacting with GitHub, and more. Claude Code becomes substantially more powerful because it now has more context about your actual work environment.
MCP servers bring additional context into Claude Code — what’s happening in your Git repo, what tickets are in Jira, what messages are in Slack — without you having to manually provide any of it.
Adding and Removing MCP Servers
To add a server — run the MCP server’s install command in your terminal (each server provides its own command). Then restart Claude Code. After restart, run /mcp to see all connected servers and their status.
To remove a server:
claude mcp remove <server-name>
To check which tools a server provides: Run /mcp, select the server, then select "View Tools". Each tool will show a full description of what it does.
Important warning: Don’t blindly add every MCP server you find. Every connected server loads its tool descriptions into your context window at the start of every session. Too many servers = unnecessary context bloat = degraded model performance. Only keep servers you regularly use.
Practical MCP Server 1 — SQLite Database
What it does: Lets you query your SQLite database directly in plain English. No SQL, no Python scripts.
Why it’s useful: In a real project with 10–20 tables, understanding schema and relationships normally requires running queries manually. With this server, you just ask.
How to add it:
Run this command in your terminal, replacing the path with your actual database file path:
# Example command with your database path
# Replace the path with your actual .db file location
After restarting Claude Code, verify it’s connected:
/mcp → sqlite: connected ✓
What you can do:
List all the tables in the Spendly database
Show me the schema of the expenses table
Show total spending grouped by category
Claude reads the database directly — no code needed. Works with SQLite, MySQL, and PostgreSQL.
Practical MCP Server 2 — Figma
What it does: Reads a Figma design and converts it directly into code — matching the layout, fonts, colors, and structure.
The typical company workflow without MCP:
- Designer creates wireframes in Figma
- Exports or shares the design with the dev team
- Dev team studies the design manually and replicates it in code
With Figma MCP:
- Designer creates the design in Figma
- Developer gives Claude Code the Figma design URL
- Claude reads the design and generates the code — accurately
How to add it:
Install the Figma plugin for Claude Code via terminal:
# Install the Figma plugin
# (copy the install command from the Figma MCP docs page)
Then in Claude Code: /plugins → Installed → Figma → Authenticate with your Figma account.
The Figma plugin bundles both an MCP server and skills for common Figma workflows.
How to use it:
Right-click any frame in Figma → Copy link. Then in Claude Code:
Here is the Figma design for the Coming Soon page: <figma-url>
Please do the following:
- Read the Figma design and convert it to a Jinja2 HTML template
- Add an Analytics menu item to the nav bar
- Create a Flask route in app.py that renders the Coming Soon page
- Protect this route so only logged-in users can access it
Claude reads the design, matches fonts and layout, and generates the full implementation.
Practical MCP Server 3 — GitHub
What it does: Connects Claude Code directly to your GitHub account. Read repos, issues, pull requests, and — with the right permissions — create PRs, merge them, and manage branches.
How to add it:
Step 1 — Create a personal access token:
- Go to github.com → Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token
- Give it a name, set an expiry, and add permissions (repos, issues, pull requests)
Step 2 — Run the setup commands in your terminal:
# Command 1: set the token as an environment variable
export GITHUB_PERSONAL_ACCESS_TOKEN=<your-token>
# Command 2: add the GitHub MCP server
# (copy from GitHub MCP docs)
After restarting Claude: /mcp → GitHub: connected ✓
What you can do:
Which is my most starred repository?
Are there any open issues on this repo? Summarize them for me.
Are there any open pull requests?
The real power — automating the Git workflow:
Every feature development cycle ends with the same repetitive steps: commit → push → create PR → merge → switch to main → pull → delete branch. With GitHub MCP, you can automate all of this with a single prompt:
Commit all changes with an appropriate conventional commit message.
Push to the current feature branch.
Create a pull request into main with a proper title and description based on the spec.
Merge it using squash merge.
Switch to main, pull latest, and delete the feature branch locally.
Note: Make sure your token has PR creation and merge permissions. If it doesn’t, Claude will push the branch but you’ll need to create/merge the PR manually.
Top MCP Servers for Developers
Beyond the three demonstrated above, here are the most useful MCP servers for a software development workflow:
Context7 — pulls live, up-to-date documentation for any library or framework directly into Claude’s context while you’re coding. LLMs have a training cutoff — if a library released a new version after that cutoff, Claude doesn’t know about it. Context7 fixes this. Almost every serious Claude Code user has this connected.
# Example prompt enabled by Context7:
Read the latest FastAPI docs and implement a JWT auth middleware
Jira — connects to your Jira board. Instead of manually reading and copying ticket details, Claude reads them directly.
Read this Jira ticket and implement the feature.
Find all open bug tickets in the Spendly project and fix the highest priority one.
Notion — connects to your Notion workspace where your team stores PRDs, API design docs, and specs.
Read the product requirements doc for the Analytics module in Notion and implement the feature.
Read the API design document in Notion and scaffold all the endpoints in app.py.
Slack — connects to your team’s Slack workspace. Read channels, post messages, share PR links.
Push this fix to Git, open a PR, and post the PR link in the #code-reviews channel with a summary of what was changed.
Check the #incidents channel for the latest production error, find the bug in the codebase, and fix it.
AWS — connects to your AWS account. Deploy, monitor logs, manage infrastructure.
Deploy the latest build of Spendly to the EC2 instance and verify it's running.
Check CloudWatch logs for the Spendly app from the last 2 hours and find what's causing the 500 errors.
Docker — connects to Docker. Generate Dockerfiles, optimize image sizes, manage containers.
Read my Spendly Flask app and generate an optimized Dockerfile for it.
My Docker image is 2GB. Analyze the Dockerfile and reduce the image size.
Quick Reference

6. Hooks
What Is Claude Code, Really? — First Principles
Before understanding hooks, it helps to understand what Claude Code actually is under the hood.
The Claude LLM is raw intelligence — unpredictable, stateless, non-deterministic, disconnected from the real world, and unable to act safely on its own. It cannot read your files, run commands, or do anything beyond generating text.
Claude Code is a coding harness around that LLM. Just as a horse harness is a set of straps and equipment used to control and direct the power of something strong, a coding harness takes raw LLM power and makes it useful through a structured interface.
Core idea: raw power becomes useful only when controlled through a structured interface.
The coding harness is what handles everything the LLM cannot do on its own:
- reading your filesystem
- displaying terminal output
- managing conversation history
- tracking context window usage
- sending API requests to Anthropic
- parsing the model’s tool calls
- asking you for permission before running commands
- executing those commands when approved
- memory management
- slash commands
- spawning sub-agents
- extensibility through MCP, plugins, etc.
The LLM decides what to do. The harness decides how to do it safely.
The Agent Loop
Every time you send a prompt to Claude Code, the following cycle runs:

Example — “Add the expense deletion route”:

The loop repeats for every tool call. The model never directly touches your filesystem — it requests an action, the harness executes it, and the result comes back.
Session Lifecycle
Session lifecycle — the full lifespan of one Claude Code session from the moment you launch it (claude) to the moment you close it (/exit).
Each tool call goes through three stages: pre tool use, tool executes, post tool use. This is where hooks plug in.

What Are Hooks?
Hooks are custom scripts written by the programmer that the harness automatically executes at specific events during a session’s lifecycle.
Hooks give you programmatic control over the agent loop. Without hooks, the loop runs entirely under Claude’s control. With hooks, you can intercept any tool call before or after it executes — inspect what Claude wants to do, decide whether to allow it, modify behavior, or block it entirely.
The hook fires, runs your script, and the harness reads the exit code to decide what happens next:
- Exit 0 — all clear, proceed normally
- Exit 2 — block this tool call, do not execute, send the error message back to the model
Hook Use Cases
Six primary ways hooks are used in practice:
-
Auto-formatting and linting — after Claude writes code to a file, automatically run a formatter. The
code-formathook fires on file write → runs your linter → Claude Code reads the reformatted result. This ensures every file Claude writes adheres to your team's style automatically. -
Blocking dangerous shell commands — before any Bash command runs, check if it targets a protected file or uses a dangerous pattern. Block it if so.
-
Protecting sensitive files — prevent Claude from ever reading or modifying
.env,spendly.db,migrations/, or any other files you've declared off-limits. -
Notification — trigger a desktop notification, send a Slack message, or ping you when Claude finishes a long task.
-
Telemetry — log every tool call Claude makes to a file for audit purposes — what was read, what was written, what commands were run.
-
Generating summaries — after a session ends, automatically generate and save a summary of what was done.
How Hooks Work — Step by Step
Scenario: You ask Claude to “clean up the Spendly project.” Claude decides to run rm spendly.db.
Here is exactly what happens with a PreToolUse hook configured on Bash:
- You ask Claude to “clean up the Spendly project”
- Claude enters the agent loop and decides:
Bash: rm spendly.db - The harness sees a Bash tool call and checks — is there a
PreToolUsehook with a matcher that matches "Bash"? Yes - The harness runs your script, piping in JSON that contains the command
rm spendly.db - Your script reads the JSON, sees
rmtargetingspendly.db, prints "Cannot delete the database file" to stderr, and exits with code 2 - The harness reads exit code 2 — block. It does not run the command
- The harness sends the error message “Cannot delete the database file” back to the model
- The model reads the error, understands, and moves on to something else
- The agent loop continues. Your database is safe.
Hook Configuration — settings.json
Hooks are configured in .claude/settings.json:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "python3 .claude/hooks/block-dangerous.py"
}
]
}
]
}
}
PreToolUse— the event type (fires before a tool executes)matcher: "Bash"— only fire this hook when the tool being called is Bashcommand— the script to run when the hook fires
The harness pipes a JSON payload into your script via stdin. Your script reads it, checks whatever it needs to check, and exits with 0 (allow) or 2 (block).
Practical Example — File Protection Hook
File: .claude/hooks/block-dangerous.py
# Step 1: Read the JSON that the harness sends via stdin
data = json.load(sys.stdin)
# Step 2: Extract the bash command the model wants to run
command = data.get("tool_input", {}).get("command", "")
# Step 3: Define what we want to protect
protected_files = ["spendly.db", ".env", "migrations/"]
# Step 4: Define what counts as dangerous
dangerous_commands = ["rm ", "rm -", "unlink ", "> ", "truncate "]
# Step 5: Check if the command is dangerous AND targets a protected file
for dangerous in dangerous_commands:
if dangerous in command:
for protected in protected_files:
if protected in command:
# Block it: exit 2 + error message on stderr
print(
f"BLOCKED: cannot run '{command}' — "
f"'{protected}' is a protected file",
file=sys.stderr
)
sys.exit(2)
# Step 6: If we get here, the command is fine — exit 0
What this protects: any rm, unlink, > (redirect/overwrite), or truncate command that targets spendly.db, .env, or migrations/. Everything else proceeds normally.
The model receives the error message on blocking, understands the constraint, and finds another approach.
Quick Reference

7. Plugins
The Problem Plugins Solve
Everything in this playlist up to now — skills, slash commands, hooks, sub-agents, MCP servers — represents work you do once and then benefit from indefinitely. But there’s a problem: sharing it.
Consider a senior data scientist who has spent six months deeply integrating Claude Code into his workflow:
- An EDA skill that runs credit risk-specific exploratory analysis — checks dataset shape, dtypes, missing value heatmaps, flags skewed features (skewness above 1.5 or below -1.5 for log transform candidates), flags rare categories below 5% representation (problematic for stratified splits), checks for target leakage at 0.95+ correlation, and generates a full summary table with a “keep / transform / investigate” recommendation per column.
- A feature engineering skill that extracts recency features from datetime columns, enforces target encoding with 5-fold cross-validation for high-cardinality features (never one-hot), and runs a VIF check — flagging anything above 10 for multicollinearity.
- A
/model-evalslash command that generates a styled confusion matrix (company colour scheme), classification report with precision/recall/F1 plus Gini coefficient and KS statistic (standard credit risk metrics), ROC and precision-recall curves side by side, and SHAP feature importances. - A data science-specific hook that intercepts any code before it writes, and blocks:
df.dropna()without column names (can wipe 60% of data in 50-column datasets), fitting scalers or encoders on the full dataset instead of train-only (data leakage), hardcoded file paths (breaks on other machines), and accuracy as a metric for imbalanced classification (5–10% default rate means "predict no default" achieves 90% accuracy while being useless). - An experiment tracking MCP server that connects Claude Code to the team’s internal MLflow or similar tool — logging trained models and querying past results directly from the terminal.
This entire setup took six months to build. Now a junior data scientist joins the team. How do they get it?
The manual way — share each file individually, explain where each goes, hope they configure hooks correctly — is fragile and slow. One missed step and the setup is broken.
Plugins are the solution. A plugin packages everything — skills, slash commands, hooks, sub-agents, MCP configuration — into a single distributable unit. Install the plugin, get the entire workflow.
What Is a Plugin?
A plugin is a folder that bundles your skills, custom slash commands, hooks, sub-agents, and MCP tools into a single installable package.
When someone installs your plugin, they get an exact replica of your setup — automatically, with no manual configuration.
Plugin folder structure:
rahul-ds-toolkit/
├── .claude-plugin/
│ └── plugin.json ← required manifest file
├── skills/
│ ├── eda-credit-risk.md
│ ├── feature-engineering.md
│ └── model-documentation.md
├── hooks/
│ ├── linter-check.js
│ └── production-guard.js
├── commands/
│ └── model-eval/
│ └── command.md
└── .mcp.json
The only required file is plugin.json inside a .claude-plugin/ folder. Without it, the folder is not recognized as a valid plugin.
plugin.json (manifest file):
{
"name": "rahul-ds-toolkit",
"version": "1.0.0",
"description": "Credit risk data science toolkit — EDA, feature engineering, model evaluation, and experiment tracking for the risk modeling team",
"author": {
"name": "Rahul Sharma",
"url": "https://github.com/rahul-sharma"
},
"repository": "https://github.com/rahul-sharma/rahul-ds-toolkit",
"license": "MIT"
}
Marketplaces
A marketplace is where plugins are stored and discovered — analogous to an app store.
Just as a phone has an app store where apps live, Claude Code has marketplaces where plugins live. And just as multiple app stores exist (Google Play, App Store, Samsung Store), multiple marketplaces exist.
Technically: a marketplace is just a GitHub repository containing a marketplace.json file that lists which plugins are available.
marketplace.json:
{
"name": "rahul-ds-marketplace",
"owner": {
"name": "Rahul Sharma"
},
"plugins": [
{
"name": "rahul-ds-toolkit",
"source": "./plugins/rahul-ds-toolkit",
"description": "Credit risk data science toolkit"
},
{
"name": "nlp-starter",
"source": "./plugins/nlp-starter",
"description": "NLP preprocessing and evaluation"
}
]
}
Two types of marketplaces:
Official marketplace (claude-plugins-official) — pre-installed with Claude Code, curated by Anthropic. Contains first-party plugins and vetted partner plugins — Vercel, Railway, GitHub, Supabase, Figma, Context7, and others. 172+ plugins available.
Third-party marketplaces — any GitHub repo with a marketplace.json. A team, a company, or any individual can create one. To use a third-party marketplace's plugins, you first install the marketplace, then install the plugin from it.
Installing Plugins
Step 1 — Open the plugin browser:
/plugins
This shows three tabs: Discover, Installed, Marketplaces.
Step 2 — For official plugins: Go to Discover → browse or search → install. No marketplace setup needed.
Step 3 — For third-party marketplace plugins: Go to Marketplaces → Add marketplace → paste the GitHub repo URL → enter. The marketplace installs. Then go to Discover, find the plugin, install it.
Command-line install alternative:
# Install a marketplace
claude plugin marketplace add <github-url>
# Install a plugin
claude plugin install <plugin-name>
When installing, you choose scope: user-level (all projects) or project-level (this repo only).
Practical Example — Deploying with the Railway Plugin
Railway is a deployment platform well-suited for Flask applications (Vercel is better for Next.js/frontend frameworks — it runs Flask apps as serverless functions, which breaks session state).
Setup flow:
# 1. Create a Railway account (sign in with GitHub)
# 2. Install the Railway CLI
npm install -g @railway/cli
# 3. Authenticate
railway login
# 4. Install the Railway Claude Code plugin
# (via /plugins → Marketplaces → Add marketplace → Railway marketplace URL)
# Then install the Railway plugin from Discover
Deploy with one prompt:
Deploy this Flask application to Railway and give me a public URL.
The Railway plugin handles everything behind the scenes — creates a Procfile, adds gunicorn to requirements.txt, initializes the Railway project, configures environment variables, builds and deploys. You get a live URL.
Note: SQLite databases reset on every redeploy because the file doesn’t persist across Railway’s ephemeral filesystem. Use PostgreSQL or MySQL for production persistence.
Recommended Plugins
A few worth installing from the official marketplace:
Superpowers — improves overall software development workflow with additional tools and automation.
Frontend Design — improves the quality of AI-generated frontend UI.
Context7 — pulls live, up-to-date documentation for any library directly into Claude’s context. Essential if you work with rapidly evolving libraries.
Code Simplifier — refactors and simplifies generated code for better readability.
Skill Creator — helps you build new skills using Claude’s Skill Creator workflow.
GitHub — full GitHub integration (covered in the MCP video, also available as a plugin).
Playwright — browser automation.
Don’t install everything — each installed plugin loads its descriptions into your context window at session start. Install only what you regularly use.
Quick Reference

Credit: This guide is based on my learnings from the Claude Code tutorial playlist below. I’ve organized the material into notes and explanations in my own words. For the complete walkthroughs, please support the original creator:
https://www.youtube.com/playlist?list=PLKnIA16_RmvaYH3poI0oJvbDF4zEvpq8W
메타데이터
- post_id
- 8085ee17dcbc
- slug
- claude-code-advanced-guide-part-2-skills-sub-agents-mcp-hooks-and-plugins-8085ee17dcbc
- url
- https://medium.com/@onlinelearner01learn/claude-code-advanced-guide-part-2-skills-sub-agents-mcp-hooks-and-plugins-8085ee17dcbc
- canonical_url
- https://medium.com/@onlinelearner01learn/claude-code-advanced-guide-part-2-skills-sub-agents-mcp-hooks-and-plugins-8085ee17dcbc
- author_url
- https://medium.com/@onlinelearner01learn
- status
- ok
- fetched_at
- 2026-06-20 20:29:01