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

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
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
- 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
- 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
- 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.
- 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
- 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
- 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)
- 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 diffliberado emallowed-tools, saída do shell entrando pronta no prompt - Revisão de um arquivo específico: corpo com
@caminho/do/arquivofixo e$ARGUMENTSpra 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.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
As diferenças de var, let e const
Como fazer redirecionamento com PHP
Neste artigo você vai aprender a como fazer redirecionamento com PHP, utilizaremos abordagens fáceis de entender e de aplicar Fala programador(a), beleza? Bora aprender mais […]
Checklist de segurança n8n VPS pública: guia essencial para proteger sua instalação
Checklist de segurança n8n VPS pública: guia essencial para proteger sua instalação A popularidade da automação de processos com o n8n está em alta, principalmente […]
