PTENES
MODULE 2.2

🧩 Skills, sub-agents, and MCP in Claude Code

Where the agent’s custom intelligence lives — well-written skills, sub-agents that trigger themselves, MCP servers, and the dynamic injection only Claude has.

7
Topics
35
Minutes
Inter.
Level
Practical
Type

🎯What you get here

Leave knowing how to write a skill that triggers on its own, a sub-agent that the main Claude delegates to at the right time, and how to understand Claude Code-exclusive features (dynamic injection, allowed-tools) that do NOT exist in Codex.

Detailed content

1

📦 Anatomy of a skill

A skill in Claude Code is a folder in .claude/skills/<nome>/ with a conventional structure. The heart is SKILL.md, but there are more pieces, each with a clear purpose.

Complete structure

.claude/skills/minha-skill/
├── SKILL.md              ← obrigatório (frontmatter + body)
├── scripts/             ← scripts auxiliares chamáveis
│   ├── check.sh
│   └── format.py
├── references/          ← docs profundas (lazy-load)
│   ├── api-spec.md
│   └── examples.md
└── assets/              ← imagens, binários, templates
    └── template.html

Complete SKILL.md (real example)

---
name: revisar-pr
description: Use quando o usuário pedir pra revisar uma PR ou diff. Triggers: "revisa PR", "review pull request", "olha o diff".
allowed-tools: Bash(git diff:*), Bash(gh pr:*), Read, Grep, Glob
disable-model-invocation: false
---

# Revisar PR

## Passo a passo

1. Identifica a PR (número via $ARGUMENTS ou \`gh pr list\`)
2. Lê diff completo com \`gh pr diff <numero>\`
3. Para cada arquivo mudado, verifica:
   - Bugs de correção (não estilo)
   - Edge cases não tratados
   - Vulnerabilidades comuns
4. Consulta \`references/security-checklist.md\` se tocar em auth
5. Retorna findings categorizados por severity (high/med/low)

## Referências
- Checklist completo: \`references/security-checklist.md\`
- Padrões do repo: \`references/repo-conventions.md\`

✓ Well-made skill

  • • Short, direct body (step-by-step)
  • • Details in references/ (lazy)
  • • allowed-tools restricted to what’s necessary
  • • description with real-world triggers
  • • Scripts for deterministic actions

✗ Anti-pattern

  • • 200KB body with EVERYTHING inline
  • • description that just repeats the name
  • • No allowed-tools (anything goes)
  • • Scripts in the body instead of scripts/
  • • Mix multiple responsibilities

Key concepts

Frontmatter
name + description min
Short body
Step-by-step, < 5KB
references/ lazy
Loaded on demand
scripts/ determ.
Actions without an LLM
2

🎯 Description — the art of the trigger

The biggest cause of a “skill not working” is bad description. It’s not a bug—it’s a semantic match failing. Claude reads the descriptions of all skills and chooses the best one for the current context. Your description is competing for attention.

✗ Poor description

description: Skill de revisão

→ Vague. Doesn't say when to use it. No trigger. The skill stays invisibly dormant.

✓ Good description

description: Use quando o usuário pedir
pra revisar PR/diff. Triggers: "revisa
PR #123", "review da branch", "olha o
diff", "code review".

→ Says when. Lists real triggers. Match gets it right.

Recipe for a quality description

1.
"Use when..." — start with the situational trigger
2.
Lists real trigger phrases — phrases the user ACTUALLY writes
3.
Examples — 1–2 concrete scenarios
4.
Avoid repeating the name — description “skill X does X” is wasteful
5.
Says when NOT to use it — if useful, make the counterexample clear

💡Empirical test

After writing it, open Claude Code and simulates 5 real prompts that should activate the skill. If it activates in 4/5, that's fine. If it activates in 2/5, the description is weak. Iterate.

Key concepts

Semantic match
Claude reads and decides
"Use when..."
Trigger standard
Trigger phrases
User phrases
Empirical test
5 real prompts
3

👤 Auto-invocable sub-agents

A sub-agent is a specialized persona with its own system prompt, restricted tool surface, and isolated context. The main Claude reads the description and DELEGATES — on its own, without you asking by name. It’s the feature that most distinguishes Claude from Codex.

Example — .claude/agents/code-reviewer.md

---
name: code-reviewer
description: Use proactively when the user finishes implementing a feature or before merging a PR. Specializes in catching correctness bugs.
tools: Read, Grep, Glob, Bash(git diff:*)
model: claude-opus-4-6
---

You are a senior code reviewer focused on correctness.

## Your role
- Read the diff carefully
- Flag correctness bugs (NOT style — linter handles that)
- Check edge cases (null, empty, off-by-one, race conditions)
- Note security risks (SQLi, XSS, path traversal, auth bypass)

## Output format
A numbered list of findings:
1. **[severity]** file:line — what's wrong, why, suggested fix

Be terse. No fluff.
🎯

Context isolation

A sub-agent opens its own window — it doesn’t clutter the main agent’s context. It returns only the result.

⚡

Parallelism

Claude can launch multiple sub-agents in parallel (Task tool). Useful for research from multiple angles.

🔬

Dedicated model

Each sub-agent can use a different model. Haiku for searches, Opus for analysis. Savings + quality.

Description with “proactively” — the secret

The word “proactively” in the description is a strong signal to the main Claude: “use this WITHOUT the user asking, when the context matches.” Without it, the subagent almost never fires on its own.

description: Use proactively when... // dispara sozinho
description: Use when the user explicitly asks... // só sob pedido

Key concepts

Auto-dispatch
By description
Task tool
Delegation mechanism
Tool subset
tools: [a, b, c]
"proactively"
Keyword
4

🔌 MCP servers — declaration and use

MCP server exposes external tools to Claude. Declared in .mcp.json (project, goes into git) or ~/.claude.json (global). Each exposed tool becomes mcp__servidor__nome-tool.

.mcp.json (project)

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
    },
    "postgres": {
      "command": "uvx",
      "args": ["mcp-server-postgres", "--db-url", "${DATABASE_URL}"]
    },
    "linear": {
      "type": "http",
      "url": "https://mcp.linear.app/sse",
      "headers": { "Authorization": "Bearer ${LINEAR_TOKEN}" }
    }
  }
}

Allowlist in settings.json

{
  "enabledMcpjsonServers": ["github", "postgres"],   // só estes ativam
  "permissions": {
    "allow": [
      "mcp__github",                          // libera tudo do server
      "mcp__postgres__query"                  // libera tool específica
    ]
  }
}

📦 stdio transport

Server runs as a child process via stdin/stdout. More common for local MCP.

Example: npm/uvx starts a process, Claude communicates through a pipe.

🌐 HTTP/SSE transport

Server runs as a remote service. Claude connects via HTTP with Server-Sent Events.

Example: Linear, Slack, SaaS services with an official MCP endpoint.

Key concepts

.mcp.json
Project-level, goes in git
~/.claude.json
Global
stdio vs HTTP
Two transports
Naming
mcp__server__tool
5

🎨 Dynamic injection (backtick-bang) — Claude-only

Claude Code-specific syntax: inside SKILL.md or commands, code between crase-bang (`!comando`) is executed by the shell BEFORE the skill reaches the LLM. The result goes directly into the prompt — no additional tool call.

Practical example

---
name: branch-status
description: Mostra contexto da branch atual antes de propor próxima ação
---

# Status da branch

Branch atual: `!git branch --show-current`
Último commit: `!git log -1 --oneline`

Diff vs main:
`!git diff main...HEAD --stat`

Com base no acima, sugira o próximo passo.

When you invoke /branch-status, Claude already receives an SKILL.md populated with the actual outputs. No need to ask "run git status" — it's already there.

✓ Good use cases

  • • State snapshot (git, version, ENV)
  • • List relevant files/branches
  • • Get the latest log/error
  • • Inject timestamp/date
  • • Idempotent command result

✗ Caution

  • • Destructive commands (rm, drop)
  • • User input interpolated directly (injection)
  • • Slow commands (hold up the skill for seconds)
  • • Huge output (overflows context)
  • • Side effects that change state

⚠️Watch out for portability

Backtick-bang does NOT exist in Codex. A skill that depends on it will fail there. Polyskill rewrites it as fallback prose ("run git status and analyze the result") when compiling for Codex—but loses actual injection.

Key concepts

Build-time
Runs before the prompt
No tool call
Already included in the context
Not portable
Claude only
Polyskill covers
Fallback prose
6

🚦 disable-model-invocation and allowed-tools

Two frontmatter fields that give you fine-grained control about when and how the skill runs. Essential for dangerous or focused skills.

🔒 disable-model-invocation

disable-model-invocation: true

Prevents auto-triggering. Runs only when you explicitly invoke it (/nome-skill).

When to use: destructive skills (drop, deploy, push), skills that cost money (call a paid API), skills that ONLY you invoke intentionally.

🛡️ allowed-tools

allowed-tools: Read, Grep, Bash(git:*)

Restricts which tools the skill can use. Principle of least privilege.

When to use: a read skill should never write, an analysis skill should never open a terminal. Restrict it.

💡Security combo

For a dangerous skill: disable-model-invocation: true + allowed-tools ultra-restricted + description with an explicit warning. Triple guarantee.

Key concepts

Opt-in invoke
disable-model-invoke
Tool surface
allowed-tools
Least privilege
Minimum required
Model override
model: haiku
7

🛍️ Plugins and marketplace

A plugin is a distributable package: bundles skills + agents + commands + hooks into a single versioned bundle. It's how you consume other people's work (claude-mem, context-mode, superpowers, etc.) and publish your own.

plugin.json — manifest

{
  "name": "meu-plugin",
  "version": "1.2.0",
  "description": "Conjunto de skills pra refatorar TypeScript",
  "author": "@meu-handle",
  "skills": ["./skills/ts-refactor", "./skills/ts-test-gen"],
  "agents": ["./agents/ts-reviewer.md"],
  "commands": ["./commands/refactor.md"],
  "hooks": [{ "event": "PostToolUse", "matcher": "Edit", "command": "./scripts/format.sh" }]
}
📦

Namespace

Plugin skills become plugin:skill-name to avoid collisions.

🏪

Marketplace

Plugin index (marketplace.json). Install via /plugins.

🔄

Versioning

npm-style semver. Update via marketplace.

🦜Polyskill as a plugin

Polyskill is distributed as a plugin. You install it once and get the CLI + the meta-skill that drives the CLI in natural language. A plugin is the modern way to distribute software.

Key concepts

plugin.json
Bundle manifest
marketplace.json
Public index
plugin:skill
Namespace
Semver
Versioning

🎯Module summary

✓
Skill = SKILL.md + scripts/ + references/ + assets/ — short body, lazy-loaded details.
✓
Good description = “use when” + real triggers — test empirically.
✓
Sub-agents auto-trigger with "proactively" — isolated context, dedicated model.
✓
MCP via .mcp.json (project) or ~/.claude.json (global) — stdio or HTTP.
✓
Backtick-bang injects shell output into the prompt — Claude-only, NOT portable.
✓
disable-model-invocation + allowed-tools = fine-grained control — security combo.
✓
Plugins distribute skills + agents + commands + hooks — versioned, namespaced.

Next track:

T3 — Anatomy of Codex (AGENTS.md, .codex/, .agents/, openai.yaml)