Skip to content
Back to articles
tutorialclaude-codeplugins

How to Use Plugins in Claude Code: From Basics to Building Your Own

Learn how to install, use, and create Claude Code plugins. A practical tutorial with real examples — from user to plugin creator.

9 min read

How to Use Plugins in Claude Code

Out of the box, Claude Code is already impressive. It reads your code, edits files, runs commands, and answers questions about your project. But at some point, you'll want it to do things your way.

Maybe you want a /commit command that follows your team's conventions. Or a hook that blocks commits without tests. Or a specialized agent that runs code reviews with your company's criteria.

That's where plugins come in.

In this article, you'll learn what plugins are, how to install and use existing ones, and how to build your own from scratch. No unnecessary theory — just real examples.

What are plugins

A Claude Code plugin is a folder with a configuration file and a set of components that extend what Claude can do.

Think of it this way: Claude Code is like a new smartphone. It works great out of the box. But when you install apps — a better camera, a photo editor, a task manager — it adapts to your lifestyle. Plugins are Claude Code's apps.

In practice, a plugin is a folder with this minimal structure:

my-plugin/
├── .claude-plugin/
│   └── plugin.json          ← plugin identity
├── skills/                  ← behaviors Claude learns
├── commands/                ← slash commands (/my-command)
├── hooks/                   ← automatic scripts (before/after actions)
└── agents/                  ← specialized sub-agents

The plugin.json is the ID card. It tells Claude Code the plugin's name, what it does, and who made it:

{
  "name": "my-plugin",
  "description": "Automations for my development workflow",
  "author": {
    "name": "Your Name"
  }
}

The rest are optional components. A plugin can have just one command. Or just hooks. Or a combination of everything. You build what you need.

Plugin components

Each component type solves a different problem. Here's what each one does:

Skills — teaching new behaviors

A skill is a Markdown file that teaches Claude how to perform a specific task. When invoked, the skill's content is loaded into the conversation context — as if you had pasted detailed instructions.

Example: a code review skill that defines specific criteria, checklists, and output format. When invoked, Claude knows exactly how to review code the way you want.

Skills are .md files with YAML frontmatter:

---
name: my-skill
description: Use when the user asks to do X
---

# Skill Instructions

Here go the detailed instructions that Claude
will follow when this skill is invoked.

The description field is critical — it's what lets Claude decide when to use the skill automatically.

Commands — slash shortcuts

Commands are custom slash commands. You type /my-command and Claude executes a predefined workflow.

The difference between a command and a skill: commands are explicitly invoked by the user (via /), while skills can be triggered automatically when Claude identifies they're relevant.

Real command examples:

Command What it does
/commit Commit following Conventional Commits
/code-review Code review a pull request
/create-pr Create a PR linked to an issue

Commands are also Markdown files with frontmatter:

---
description: Run a code review on a pull request
allowed-tools: Bash(gh *), Read, Grep, Glob
---

# Code Review

Instructions for Claude to execute the review...

The allowed-tools field defines which tools the command can use — an important security control.

Hooks — invisible automation

Hooks are scripts that run automatically in response to Claude Code events. They're invisible to the user — working behind the scenes.

The main events:

Event When it fires
PreToolUse Before any tool executes
PostToolUse After a tool finishes
UserPromptSubmit When the user sends a message
Stop When Claude finishes a response

Practical example: a PreToolUse hook that checks if a Bash command is destructive (rm -rf, git push --force) and blocks execution with a warning.

Hooks are registered in hooks/hooks.json and executed by scripts (Python, bash, Node.js):

{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.py",
            "timeout": 10
          }
        ]
      }
    ]
  }
}

The ${CLAUDE_PLUGIN_ROOT} variable points to the plugin's root — always use it for relative paths.

Agents — specialized sub-agents

Agents are autonomous sub-processes that Claude can spawn for complex tasks. Think of them as the assistant's assistants.

Example: a code review agent that uses the Haiku model (faster and cheaper) for a first pass, and only escalates to the main model when it finds serious issues.

MCP Servers — connecting to the world

Plugins can include MCP (Model Context Protocol) server configurations, which connect Claude to external tools — databases, APIs, browsers, search services.

Quick comparison

Component Activation Format Typical use
Skill Automatic or manual Markdown Teaching behaviors
Command Manual (/command) Markdown Repeatable workflows
Hook Automatic (event) Script + JSON Validation, security
Agent Via Claude Markdown Complex tasks
MCP Always active JSON config External tools

Installing and using plugins

There are two paths to get plugins in Claude Code: install from a marketplace or add them manually.

Marketplaces

Marketplaces are GitHub repositories that contain plugin collections. The main one is Anthropic's official marketplace (anthropics/claude-plugins-official), but anyone can create their own.

To add a marketplace:

/plugin marketplace add user/repository

To install a plugin from a marketplace:

/plugin install plugin-name

Claude Code downloads the plugin, places it in ~/.claude/plugins/cache/, and registers the installation.

Scope: user vs project

When installing, you choose the scope:

  • User (global): The plugin works across all projects. Ideal for generic tools like code review, git workflows, frontend design.
  • Project: The plugin works only in that project. Ideal for team-specific or stack-specific plugins.

These are real plugins from the anthropics/claude-plugins-official marketplace:

Plugin What it does Recommended scope
code-review Automated PR review with scoring User
hookify Create validation rules without code User
frontend-design High-quality design interfaces User
plugin-dev Tools for creating plugins User
claude-md-management Keep CLAUDE.md organized User
context7 Fetch up-to-date docs for any library User
playwright Browser automation for testing User
firecrawl Web scraping and search Project
stripe Stripe integration Project

Using plugins day to day

Once installed, plugins integrate naturally into Claude Code:

Commands appear as slash commands. Type / and you'll see available commands. Example:

> /code-review 42

This invokes the code-review plugin to review PR #42.

Skills are activated automatically when Claude identifies they're relevant. If you have the frontend-design skill installed and ask "create a login component," Claude will use the skill automatically.

Hooks run in the background. You don't need to do anything — they monitor events and act when needed.

Creating your first plugin

Let's build a real plugin: a /status command that shows a project state summary (git, tests, lint).

Step 1: Create the structure

In your project root (or in ~/.claude/plugins/ for global scope):

mkdir -p my-status-plugin/.claude-plugin
mkdir -p my-status-plugin/commands

Step 2: Create plugin.json

{
  "name": "project-status",
  "description": "Shows a quick summary of the project state",
  "version": "1.0.0",
  "author": {
    "name": "Your Name"
  }
}

Save it to my-status-plugin/.claude-plugin/plugin.json.

Step 3: Create the command

The command is a Markdown file in commands/:

---
description: Show project state summary (git, lint, tests)
allowed-tools: Bash(git *), Bash(pnpm *), Bash(npm *)
---

# Project Status

Generate a concise summary of the current project state:

1. **Git:** current branch, pending commits, modified files
2. **Lint:** run the linter and report errors (if configured)
3. **Tests:** run tests and report results (if configured)

Output format:

## Project Status

- **Branch:** main (2 commits ahead of origin)
- **Modified:** 3 files
- **Lint:** 0 errors, 2 warnings
- **Tests:** 14/14 passing

If a tool isn't configured, mention that instead
of failing silently.

Save as my-status-plugin/commands/status.md.

Step 4: Test it

For local (project) plugins, just place the folder in your project directory. Claude Code automatically detects the .claude-plugin/plugin.json folder.

Open Claude Code in the project and type:

> /status

Claude will read the command, execute the described steps, and present the summary.

Final structure

my-status-plugin/
├── .claude-plugin/
│   └── plugin.json
└── commands/
    └── status.md

Three files. A working plugin.

Hooks: automating behaviors

Hooks are where plugins get really powerful. While commands and skills wait for your action, hooks act on their own.

Anatomy of a hook

A hook needs two things:

  1. Registration in hooks/hooks.json — tells Claude Code when to run it
  2. Script that executes the logic — receives JSON via stdin, returns JSON via stdout

Example: blocking dangerous commands

Let's create a hook that prevents destructive commands like rm -rf / or git push --force to main.

hooks/hooks.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/guard.py",
            "timeout": 5
          }
        ]
      }
    ]
  }
}

hooks/guard.py:

#!/usr/bin/env python3
"""Block destructive commands before execution."""

import json
import sys
import re

DANGEROUS_PATTERNS = [
    r'rm\s+-rf\s+/',
    r'git\s+push\s+.*--force.*\s+main',
    r'git\s+reset\s+--hard',
    r'drop\s+database',
]

def main():
    input_data = json.load(sys.stdin)
    tool_name = input_data.get('tool_name', '')

    if tool_name != 'Bash':
        print(json.dumps({}))
        sys.exit(0)

    command = input_data.get('tool_input', {}).get('command', '')

    for pattern in DANGEROUS_PATTERNS:
        if re.search(pattern, command, re.IGNORECASE):
            result = {
                "decision": "block",
                "reason": f"Command blocked for safety: {command}"
            }
            print(json.dumps(result))
            sys.exit(0)

    print(json.dumps({}))
    sys.exit(0)

if __name__ == '__main__':
    main()

How it works

  1. The user (or Claude) tries to execute a Bash command
  2. Before execution, Claude Code calls guard.py
  3. The script receives command details via stdin (JSON)
  4. If the command matches a dangerous pattern, it returns "decision": "block" — and the command doesn't execute
  5. If the command is safe, it returns {} — and execution proceeds normally

The hook always exits with sys.exit(0). If the hook crashes, Claude Code moves on — it never freezes because of a broken hook.

No code needed: hookify

If you don't want to write Python, the hookify plugin lets you create hook rules using just Markdown. You describe the rule in natural language and hookify handles the execution.

Next steps

Plugins transform Claude Code from a generic tool into your tool. Start simple:

  1. Install 2-3 plugins from the official marketplace and use them for a week
  2. Create a command for a workflow you repeat every day
  3. Add a hook for something that bugs you (e.g., commits without descriptive messages)

The official plugin documentation is constantly evolving. The best examples are the official marketplace plugins — read their code.

And if you want to go further — creating full plugins with agents, MCP servers, and advanced logic — the Curso Claude Code: Criador de Apps course covers this in depth, with real projects and step-by-step guidance.


References