Como criar um comando personalizado no Claude Code para tarefas que você repete toda semana

criar comando personalizado no Claude Code com arquivo Markdown
Resposta rápida

Criar um comando personalizado no Claude Code é transformar aquele prompt que você cola toda semana em um /comando que aparece quando você digita /. Dá pra fazer de dois jeitos: um arquivo Markdown em .claude/commands/ (o nome do arquivo vira o nome do comando) ou uma skill, que é uma pasta com SKILL.md em .claude/skills/, onde o campo name define o comando. A documentação aponta as skills como caminho recomendado para comandos de várias etapas. Dentro do arquivo você parametriza com $ARGUMENTS, injeta saída de shell com crase e libera a ferramenta em allowed-tools.

Fala aí, beleza? Se toda semana você abre o terminal e cola o MESMO prompt de revisão de PR, de changelog ou de checklist de deploy, esse post é pra você 🙂

O prompt funciona, tu sabe que ele funciona

o problema é que ele mora no seu histórico, num bloco de notas perdido, ou pior, na sua memória

A ideia aqui é simples: pegar esse texto que você repete e transformar num /comando que aparece na lista quando você digita / dentro do Claude Code

E vamos cobrir os dois formatos que fazem isso hoje: o arquivo Markdown em .claude/commands/ e a skill em .claude/skills/, que na prática geram o mesmo /comando

Bora ver na prática?

O que você precisa antes de começar

Lista curta, nada de PC da Nasa aqui haha

  • O Claude Code já em uso no projeto onde o comando vai valer
  • O prompt repetido que vai virar comando (abre o histórico e pega o que você mais colou na última semana)
  • A decisão de ONDE esse comando vai morar

Essa última merece um parágrafo…

Se o comando é do projeto, ele vai em .claude/skills/ ou .claude/commands/ dentro do repositório. Arquivo dentro de .claude/ commitado no git é compartilhado com o time, então o comando deixa de ser truque seu e vira parte do projeto

Domine o Claude Code do básico ao avançado
Pré-inscrição Formação Claude Code

Domine o Claude Code do básico ao avançado

Você vai aprender a criar sistemas completos com Claude Code, sem precisar ser programador. Inscreva-se para ter acesso a um desconto de lançamento e bônus especiais!

Se o comando é seu, ele vai em ~/.claude/skills/ ou ~/.claude/commands/, que é configuração pessoal e vale em todos os projetos

Um aviso pra quem usa o SDK: em skills pessoais e de projeto, o campo allowed-tools do frontmatter vale apenas quando você usa a CLI do Claude Code diretamente. Em sessões via SDK, a aprovação de ferramentas é feita pela opção allowedTools na configuração da query

Ou seja: não adianta liberar no arquivo e esperar que aquilo valha pro SDK também

Passo a passo: do prompt colado ao comando reaproveitável

Vamos montar um exemplo de ponta a ponta: uma skill que pega o diff do PR atual e devolve um resumo pronto pra review

  1. Escolha o local e crie o arquivo

Uma skill é um diretório com um arquivo SKILL.md dentro. Então a estrutura fica assim:

.claude/skills/resumo-pr/SKILL.md

Skill de projeto mora em .claude/skills/<nome>/SKILL.md, skill pessoal mora em ~/.claude/skills/<nome>/SKILL.md

O erro comum deste passo: jogar um SKILL.md solto dentro de .claude/skills/. É pasta com o nome da skill E o arquivo dentro dela, não o arquivo direto

  1. Escreva o frontmatter YAML

O SKILL.md tem duas partes: o frontmatter YAML entre os marcadores --- e o conteúdo Markdown com as instruções que o Claude segue quando a skill roda

---
name: resumo-pr
description: Resume o diff do PR atual em bullets prontos pra review. Use quando pedirem resumo, revisão ou changelog de um pull request
---

O campo name vira o slash command, então esse arquivo já te dá o /resumo-pr

E a description não é enfeite: ela ajuda o Claude a decidir quando carregar a skill sozinho. Os campos de frontmatter disponíveis incluem name, description, model, disable-model-invocation, allowed-tools e arguments

O erro comum deste passo: escrever uma description genérica tipo "ajuda com PRs". Se ela não diz QUANDO usar, o gatilho fica fraco

  1. Escreva o corpo em Markdown

O corpo é o seu prompt de sempre, só que agora com endereço fixo. Nada de mágica, é o texto que você já colava:

Você é o revisor deste PR.

Resuma o que mudou em bullets curtos, aponte risco de quebra
e diga o que o revisor deve olhar primeiro.
  1. Parametrize com argumentos

Aqui o comando para de ser estático. O placeholder $ARGUMENTS é substituído por tudo que o usuário digita depois do nome do comando

E pra pegar por posição, usa $ARGUMENTS[N] ou a forma curta $N, com o índice começando em ZERO. Ou seja, $0 (ou $ARGUMENTS[0]) é o primeiro argumento

Foco desta revisão: $ARGUMENTS

Módulo principal: $0
Severidade mínima a reportar: $1

Precisa de um cifrão literal antes de um dígito ou antes de ARGUMENTS? Escapa com barra invertida: \$1.00 gera $1.00 no texto

O erro comum deste passo: contar os argumentos a partir de 1, do jeito que a maioria das linguagens de shell faz. Aqui o índice é base zero, então $1 é o SEGUNDO argumento

  1. Injete dado real do shell

Essa é a parte insana 😀

A sintaxe com ! e crase roda um comando de shell ANTES do conteúdo ser enviado ao Claude, e a saída substitui o placeholder. O modelo não recebe a instrução "rode o gh", ele recebe o diff já pronto

A documentação mostra exatamente esse caso, uma skill de resumo de PR que roda !gh pr diff:

---
name: resumo-pr
description: Resume o diff do PR atual em bullets prontos pra review
allowed-tools: Bash(gh *)
---

Diff do PR atual:

!`gh pr diff`

Resuma em bullets o que mudou, o risco de quebra e o que olhar primeiro.
Foco pedido: $ARGUMENTS

Tome cuidado com duas coisas aqui

Primeira: comando injetado exige liberação no campo allowed-tools do frontmatter. Sem isso, o comando de shell não roda e você fica olhando pro prompt vazio se perguntando o que aconteceu

Segunda: a substituição roda uma única vez sobre o arquivo original. A saída entra como texto puro e não é re-escaneada, então um comando NÃO pode gerar outro placeholder pra uma passagem seguinte. Nada de recursão esperta

  1. Referencie arquivos com @

Dá pra apontar um arquivo direto de dentro do comando usando a sintaxe @, por exemplo @src/utils/helpers.js

Compare o diff com as convenções que estão em @src/utils/helpers.js

Útil quando o comando sempre precisa do mesmo arquivo de referência (guia de estilo, schema, checklist do repo)

  1. Rode e veja aparecer

Na interface do Claude Code, digitar / mostra os comandos disponíveis, e digitar / seguido de algumas letras filtra a lista

Digita /res e o /resumo-pr tem que estar ali

Se não estiver, calma: o suspeito número um é o local do arquivo, e a seção "Meu comando não aparece ou não funciona: o que checar", aqui embaixo, destrincha o resto

Arquivo em .claude/commands/ ou skill em .claude/skills/: qual usar

Essa é a dúvida que trava todo mundo, então vamos separar 🙂

Critério Arquivo em .claude/commands/ Skill em .claude/skills/
Formato um arquivo .md único um diretório com o arquivo SKILL.md
Nome do comando vem do nome do arquivo, sem a extensão (revisao.md gera /revisao) vem do campo name do frontmatter
Campos de configuração frontmatter do arquivo de comando name, description, model, disable-model-invocation, allowed-tools, arguments
Status na documentação forma mais antiga, segue funcionando caminho recomendado pra comandos de várias etapas

E tem a segunda decisão, que é independente dessa: projeto ou pessoal

Onde mora Alcance Pra quem serve
.claude/skills/ ou .claude/commands/ só naquele projeto versionado no git, compartilhado com o time
~/.claude/skills/ ou ~/.claude/commands/ todos os projetos configuração pessoal, te acompanha entre repos

Agora o detalhe que resolve a discussão: um arquivo em .claude/commands/deploy.md e uma skill em .claude/skills/deploy/SKILL.md criam o mesmo comando /deploy e se comportam da mesma forma

As duas coisas convergiram na mesma superfície de barra

Se você quer entender melhor onde cada peça se encaixa, vale ler sobre a diferença entre skills, comandos e subagentes antes de sair criando arquivo

Tarefas semanais que valem virar comando

A régua é simples: se você colou o mesmo texto três vezes, ele já deveria ser um comando

Alguns casos que se encaixam direto nos recursos que a gente viu:

  • Resumo de PR: skill com !gh pr diff liberado em allowed-tools, saída do shell entrando pronta no prompt
  • Revisão de um arquivo específico: corpo com @caminho/do/arquivo fixo e $ARGUMENTS pra dizer o foco da vez. Esse é o mesmo espírito de quando você precisa revisar código gerado no DeepSeek antes de abrir o PR, só que agora sem reescrever a instrução toda vez
  • Checklist de release: comando de projeto que lê o checklist que já existe no repo com a sintaxe @, versionado junto com o código
  • Comando pessoal de rotina: aquele seu prompt de "me explica esse repo" mora em ~/.claude/skills/, e aí ele existe em qualquer projeto que você abrir

E tem uma escolha de comportamento em cada um deles

Quando você QUER que o Claude puxe a skill sozinho, capricha na description, porque é ela que ajuda o modelo a decidir quando carregar

Quando você quer o contrário, ou seja, manter a skill pessoal ou de projeto disponível mas sem o Claude invocar por conta própria, define disable-model-invocation: true no frontmatter

Útil pra comando que mexe em coisa séria, tipo deploy

Meu comando não aparece ou não funciona: o que checar

Criou o arquivo e o / não mostra nada? Se liga nos suspeitos de sempre

O comando não aparece na lista

Skills de projeto são carregadas de .claude/skills/ no diretório onde o Claude Code é iniciado e em todos os diretórios pais até a raiz do repositório

Ou seja, o carregamento SOBE, não desce

Skills em pastas .claude/skills/ aninhadas abaixo do diretório inicial não são carregadas na inicialização. Elas carregam na primeira vez que o Claude lê ou edita um arquivo dentro daquele subdiretório, e a partir daí ficam disponíveis pelo resto da sessão

Então em monorepo, o comando do pacote packages/web pode simplesmente não estar ali no começo da sessão

Dois comandos com o mesmo nome

Acontece: você tem um /deploy pessoal e o projeto também tem um

Quando skills têm o mesmo nome em níveis diferentes, vence a de maior prioridade, e a pessoal está acima da de projeto nessa ordem

Já skills vindas de plugin usam o namespace nome-do-plugin:nome-da-skill, então elas não colidem com as skills por diretório

A correção é chata mas óbvia: nome específico. /deploy-web machuca menos que /deploy

O placeholder aparece literal no prompt

Viu um $2 cru no meio do texto enviado?

É porque um placeholder indexado sem argumento correspondente permanece no conteúdo sem alteração

Ou você passou menos argumentos do que o comando espera, ou contou o índice a partir de 1 (de novo: a contagem começa em zero)

O comando de shell injetado não roda

Quase sempre é falta de liberação no allowed-tools do frontmatter

O exemplo documentado da skill de resumo de PR usa allowed-tools: Bash(gh *) justamente pra permitir o !gh pr diff

E se você está rodando via SDK, lembra do que falamos lá em cima: allowed-tools do frontmatter vale pra CLI, no SDK a liberação é pela opção allowedTools da query

Como prevenir tudo isso

Três hábitos e você para de apanhar:

  • Nomeia com cuidado, pensando em colisão
  • Versiona no git o que é do projeto, pra não existir só na sua máquina
  • Testa digitando / logo depois de criar, não daqui a duas semanas quando você precisar de verdade

Conclusão

O ganho real de criar um comando personalizado no Claude Code não é economizar Ctrl+V

É que o prompt sai da sua cabeça e vira ativo do projeto

Quando o arquivo entra no git dentro de .claude/, ele passa a valer pro time inteiro: mesma revisão, mesmo checklist, mesmo padrão, sem depender de quem lembrou de colar o texto certo

O próximo passo é bem concreto: abre o histórico, pega o prompt que você mais repetiu na última semana e cria a skill correspondente com name e description

Só isso já resolve

Depois você evolui: coloca $ARGUMENTS pra ele aceitar variação, e por último injeta dado real do shell pra ele chegar no Claude já com o contexto na mão

Começa simples, que o resto vem…

até o próximo post! 😀

Perguntas frequentes

Um comando de projeto funciona pra qualquer pessoa que clonar o repositório?

Sim, se o arquivo estiver dentro de .claude/ e for commitado no git, ele fica compartilhado com todo mundo que tiver aquele repositório. É essa a diferença entre comando de projeto e comando pessoal: o de projeto vira parte do código, o pessoal em ~/.claude fica só na sua máquina e vale em todos os projetos que você abrir.

Os arquivos em .claude/commands/ ficaram obsoletos depois das skills?

Não exatamente. A documentação atual trata os arquivos em .claude/commands/ como a forma mais antiga e aponta as skills como o caminho recomendado pra empacotar comandos de várias etapas, mas os arquivos em .claude/commands/ continuam funcionando normalmente.

Dá pra impedir que o Claude carregue uma skill sozinho e só rodar ela quando eu chamar?

Dá sim. Basta colocar disable-model-invocation: true no frontmatter da skill: ela continua existindo e aparecendo na lista quando você digita /, só que o Claude para de decidir sozinho quando carregá-la, e passa a rodar apenas quando chamada direto.

O que acontece se eu chamar o comando sem passar todos os argumentos que ele espera?

O placeholder que ficou sem argumento correspondente permanece literal no texto. Ou seja, se o comando espera $2 e você só passou dois argumentos, o $2 aparece do jeito que foi escrito no arquivo, sem virar vazio nem quebrar a execução.

Uma skill dentro de uma subpasta de .claude/skills/ carrega junto com as outras assim que eu abro o Claude Code?

Não. Skills em pastas .claude/skills/ aninhadas abaixo do diretório onde você iniciou o Claude Code não carregam na inicialização. Elas só carregam na primeira vez que o Claude lê ou edita um arquivo dentro daquele subdiretório, e a partir daí ficam disponíveis pelo resto da sessão.

Se eu tiver uma skill pessoal e uma de projeto com o mesmo nome, qual das duas vale?

Vale a pessoal. Quando skills têm o mesmo nome em níveis diferentes, vence a de maior prioridade, e a pessoal fica acima da de projeto nessa ordem. Pra evitar a confusão de vez, o melhor é dar nome específico pra cada uma, tipo /deploy-web em vez de /deploy.



Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares