> ## Documentation Index
> Fetch the complete documentation index at: https://chatcli.edilsonfreitas.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Slash Commands

> Templates de prompt reutilizáveis e parametrizados em markdown — invocados como /nome em todas as superfícies, com interop de migração zero para 9 CLIs de agente: Claude Code, Devin, Windsurf, Cursor, opencode, Codex, Gemini CLI, Qwen Code e GitHub Copilot.

Slash commands transformam arquivos markdown em **templates de prompt reutilizáveis e parametrizados**: coloque `review-pr.md` em `.chatcli/commands/` e `/review-pr 1326 security` vira um prompt completo expandido — no REPL, dentro de uma sessão `/coder` em andamento, em scripts one-shot `-p`, pelo gateway de mensagens, e via ACP e MCP. A expansão acontece **antes** de o request ser montado, então os comandos funcionam de forma idêntica com todos os providers que o ChatCLI suporta. E se o seu time já mantém comandos para **Claude Code, Devin, Windsurf, Cursor, opencode, Codex, Gemini CLI, Qwen Code ou GitHub Copilot**, esses arquivos funcionam aqui sem mudanças — migração zero.

***

## Comandos vs. skills

| | Skill | Slash command |
| - | - | - |
| O que é | *Conhecimento* — "como fazemos X aqui" | *Ação* — "faça X agora com estes args" |
| Onde entra | Bloco de guidance no system prompt | Vira o próprio turno do usuário |
| Ciclo de vida | Persistente, envelhece, re-ativa | One-shot, consumido |
| Parametrização | Args anexados ao lado | `$ARGUMENTS` / `$1`…`$9` interpolados |

Ambos aparecem no completer e no palette `/menu`.

***

## Onde os comandos moram

Varridos em ordem de precedência — o primeiro nome encontrado vence. Os diretórios nativos do ChatCLI vêm primeiro, depois a **matriz de interop**: se o seu time já usa qualquer uma dessas CLIs de agente, os arquivos de comando delas funcionam no ChatCLI sem mudanças.

| Fonte | Projeto | Global | Formato |
| - | - | - | - |
| **ChatCLI** | `.chatcli/commands/` | `~/.chatcli/commands/` | md |
| **Claude Code** | `.claude/commands/` | — | md |
| **Devin** | `.devin/workflows/` | — | md |
| **Windsurf** | `.windsurf/workflows/` | — | md |
| **Cursor** | `.cursor/commands/` | `~/.cursor/commands/` | md |
| **opencode** | `.opencode/commands/` | `~/.config/opencode/commands/` | md |
| **Codex (OpenAI)** | — | `~/.codex/prompts/` (só top-level) | md |
| **Gemini CLI** | `.gemini/commands/` | `~/.gemini/commands/` | TOML |
| **Qwen Code** | `.qwen/commands/` | `~/.qwen/commands/` | TOML |
| **GitHub Copilot** | `.github/prompts/*.prompt.md` | — | md |

Subdiretórios viram namespaces: `frontend/deploy.md` → `/frontend:deploy` (o `git/commit.toml` do Gemini → `/git:commit`). Chaves de frontmatter alheias (`agent`, `subtask`, `auto_execute_steps`) são toleradas; o `model` do opencode mapeia pro hint de modelo do ChatCLI, e `mode` é uma chave first-class do ChatCLI (veja a seção de modo de execução abaixo). Frontmatter que nem YAML válido é — como o formato `argument-hint: [FILES=<paths>]` documentado pelo próprio Codex — cai num parse linha a linha em vez de descartar o arquivo. Um comando nunca pode fazer shadow de um comando built-in — arquivos chamados `session.md`, `config.md` etc. são recusados e reportados em `/config commands`.

***

## Anatomia de um comando

```markdown theme={"system"}
---
description: Revisa um pull request com um foco específico
argument-hint: <numero-do-pr> [foco]
model: claude-sonnet-5
effort: high
allowed-tools: read, search
---
! gh pr view $1 --json title,body

Revise o PR $1 com foco em $ARGUMENTS.
Fundamente cada apontamento no diff acima.
```

| Frontmatter | Efeito |
| - | - |
| `description` | Aparece no completer, `/menu`, e nas listagens ACP e MCP |
| `argument-hint` | Dica de uso mostrada quando invocado sem args |
| `model` / `effort` | Roteiam o turno expandido (mesmo encanamento cross-provider das skills) |
| `allowed-tools` | Restringe as tools durante o run iniciado pelo comando (veja abaixo) |
| `mode` | `chat` ou `coder` — onde o corpo expandido deve rodar (veja abaixo). Ausente: inferido, `allowed-tools` presente ⇒ `coder` |

**Placeholders** (a sintaxe de cada dialeto funciona em qualquer arquivo):

| Placeholder | Significado |
| - | - |
| `$ARGUMENTS` | String de argumentos crua, verbatim |
| `{{args}}` | Alias Gemini/Qwen do mesmo |
| `$1`…`$9` | Argumentos posicionais (tokens `KEY=value` ficam de fora) |
| `$KEY` | Argumento nomeado estilo Codex: invoque com `/draftpr FILES="a b" PR_TITLE="Add hero"` |
| `$$` | Um `$` literal |

`$PALAVRAS` desconhecidas passam intactas.

***

## Linhas de pré-execução (`!`)

Uma linha começando com `!` executa um comando shell e embute o output no prompt expandido. Os dialetos inline também funcionam — o `!{cmd}` do Gemini e o `` !`cmd` `` do opencode substituem no meio da frase. Toda ocorrência, linha inteira ou inline, passa pelo **mesmo gate de segurança das tools do coder**:

1. Comandos safety-immune (`rm -rf`, `sudo`, …) sempre exigem aprovação interativa — nunca auto-aprovados, nem pelo automode.
2. Suas regras de `/policy` se aplicam (allow / ask / deny), e decisões de aprovação podem persistir regras novas (allow-always / deny-forever).
3. Em superfícies unattended (gateway, MCP, ACP, scheduler — e runs one-shot via pipe, onde o stdin não pode responder um prompt) um "ask" resolve via `/policy automode` — ou **cai em deny fail-safe**. Uma linha negada é substituída por um marcador explícito para o modelo saber que o output está faltando, nunca silenciosamente vazio. Uma regra **allow** explícita dispensa automode: roda headless (veja a seção de pipelines abaixo).

Linhas dentro de code fences **nunca** são executadas — documentação continua documentação.

***

## `allowed-tools`

Quando definido, o run iniciado pelo comando ganha um overlay efêmero no gate de segurança: uma tool fora da lista escala de *allow* para **ask** — o humano (ou o policy automode) arbitra a exceção. Nunca amplia permissões silenciosamente e nunca nega silenciosamente.

O matching é case-insensitive e o `@` inicial é opcional (`coder` ≡ `@coder`). Os nomes são comparados **exatamente** contra os nomes de tool abaixo — um nome fora do catálogo nunca casa, o que significa que toda chamada de tool naquele run escala para ask. Em particular, os nomes de tool do Claude Code (`Read`, `Write`, `Edit`, `Bash`) **não existem no ChatCLI** — não os copie para o frontmatter de um comando.

### Nomes de tool disponíveis

O engine do coder é **uma única tool, `@coder`** — `read`, `write`, `patch`, `multipatch`, `search`, `tree`, `exec`, `git-status`, `git-diff`, `git-log`, `test`, `rollback` e afins são *subcomandos* dela, não tools independentes. Permitir `@coder` permite todos eles (cada execução continua passando pelo `/policy` e pelo gate interativo).

| Categoria | Tools |
| - | - |
| Engine do coder | `@coder` (operações de arquivo, shell, git, testes — tudo subcomando) |
| Tools atômicas de arquivo | `@read` · `@search` · `@tree` · `@todo` |
| Interação com o usuário | `@ask` |
| Web & pesquisa | `@webfetch` · `@websearch` · `@wikipedia` · `@http` · `@api-explorer` · `@osv` |
| Conhecimento & memória | `@context` · `@knowledge` · `@memory` · `@recall` · `@session` · `@compress` · `@registry-tags` · `@docs-flatten` |
| Agents & orquestração | `@agents` · `@moa` · `@board` · `@mail` · `@channels` · `@send` · `@park` · `@scheduler` · `@proc` |
| Mídia & visual | `@image` · `@diagram` · `@graphview` · `@speak` · `@voice` |
| Dev & meta | `@lsp` · `@model` · `@commands` · `@tools` · `@skill` · `@mcp-login` |
| Slash-as-tool | `@cmd:help` · `@cmd:version` · `@cmd:session-list` |

Plugins externos de `~/.chatcli/plugins` participam com seus próprios nomes (ex. `@docker-ps`). `@model` só é registrado enquanto a tool de roteamento de modelo está habilitada (`CHATCLI_AGENT_MODEL_TOOL`).

### Tools MCP

Tools de [servidores MCP](/pt/extensions/mcp-integration) conectados aparecem como `mcp_` + o nome da tool exatamente como o servidor declarou — **sem prefixo de servidor**. Um servidor chamado `github` que declara `create_issue` vira `mcp_create_issue`. Exemplo:

```markdown theme={"system"}
---
description: Abrir uma issue no GitHub para os testes que falharam
mode: coder
allowed-tools: @coder, @read, mcp_create_issue
---
Rode a suíte de testes, extraia as falhas e abra uma issue no GitHub
resumindo tudo com passos de reprodução.
```

Qualquer outra tool MCP que o modelo tentar usar durante esse run escala para um ask interativo em vez de rodar silenciosamente.

***

## Modo de execução e o auto-route do chat

O chat mode é sem tools por design — um comando cujo corpo usa tools seria simplesmente recusado ali. A chave `mode:` declara onde o comando deve rodar, e o dispatcher do chat honra isso:

* **`mode: coder`** (ou inferido de um `allowed-tools` não-vazio): invocado no chat do REPL, o comando imprime um aviso (`⚡ /deploy executa com tools…`) e é **auto-roteado por um run one-shot do coder** — mesmo engine, gate de segurança e overlay de `allowed-tools` de um `/coder` manual, voltando ao prompt do chat quando o loop chega à resposta final. `chatcli -p "/deploy prod"` roteia do mesmo jeito (aviso no stderr).
* **`mode: chat`** explícito veta a inferência — o comando continua um turno puramente conversacional mesmo declarando `allowed-tools`.
* Valores ausentes ou não reconhecidos nunca invalidam o arquivo: a resolução cai na inferência e, por fim, em `chat`.

Arquivos interop do Claude Code e afins que trazem `allowed-tools` portanto rodam corretamente com **zero edições**. Comandos roteados ganham o marcador `[coder]` no completer, no `/menu` e em `/config commands`.

Superfícies headless (gateway, ACP, MCP, scheduler) mantêm o comportamento existente — o auto-route só dispara no REPL interativo e no one-shot `-p`. Opt-out global com `CHATCLI_COMMANDS_AUTOROUTE=off`.

***

## Superfícies

| Superfície | Comportamento |
| - | - |
| REPL chat | `/nome args` despacha como qualquer comando; comando mode coder auto-roteia por um coder one-shot; completer + `/menu` listam o catálogo |
| `/coder` mid-run | Follow-ups e type-ahead também expandem; `allowed-tools` re-arma o escopo, `model`/`effort` são ignorados mid-loop |
| One-shot | `chatcli -p "/review-pr 1326"` expande antes do roteamento; stdin de pipe vira parte de `$ARGUMENTS`; comandos mode coder rodam pelo engine do coder |
| Gateway | Uma mensagem de canal `/deploy prod` expande antes de o coder engine ver o texto |
| ACP (IDEs) | Comandos são anunciados via `available_commands_update` com hints de input, e expandem no fluxo de prompt |
| MCP server | Servidos pela primitive `prompts` — `prompts/list` traz o campo `arguments` do spec, `prompts/get` aceita `{"args": "..."}` |
| O próprio modelo | O builtin `@commands` deixa o agent descobrir (`list`) e expandir (`get`) os playbooks do time mid-task |

***

## Pipelines & automação headless

Slash commands compõem com pipes do shell: o stdin do pipe é anexado ao prompt antes da resolução, então uma **invocação bare** funciona e o corpo inteiro do pipe cai em `$ARGUMENTS`:

```bash theme={"system"}
git diff | chatcli -p "/review"                # corpo do pipe → $ARGUMENTS
kubectl logs deploy/api | chatcli -p "/triage" # funciona com qualquer comando
```

Se o comando é `mode: coder`, o auto-route dispara aqui também — o modelo não só lê o pipe, ele pode **agir sobre ele** com o coder engine completo (editar arquivos, rodar testes) antes de a pipeline seguir.

### Pre-execution sem prompts

Um run via pipe não tem terminal para responder um prompt de aprovação, então linhas `!` resolvem só pela sua [política de segurança](/pt/coder/coder-security). Para automatizar um comando headless — cron, CI, scripts — adicione uma regra **allow** explícita para exatamente o que ele executa em `~/.chatcli/coder_policy.json`:

```json theme={"system"}
{
  "rules": [
    { "pattern": "exec git log", "action": "allow" }
  ]
}
```

Com essa regra, o exemplo de standup abaixo roda de ponta a ponta numa pipeline com zero interação:

```bash theme={"system"}
chatcli --no-anim -p "/standup 3" >> standup-notes.md
```

As garantias do gate não se dobram para automação: **deny sempre vence allow**, comandos safety-immune (`rm -rf`, `sudo`, …) continuam exigindo um humano interativo, e o que nenhuma regra casa cai em deny fail-safe. Escope os patterns com precisão — `exec git log` em vez de `exec git` — para a regra allow cobrir só o que o comando realmente precisa. `/policy automode on` é a alternativa mais grosseira (auto-aprova todo "ask" não-immune na sessão); prefira regras allow estreitas para pipelines unattended.

***

## Gerenciando

```bash theme={"system"}
/config commands          # painel de diagnóstico (abaixo)
/config commands reload   # força um re-scan (edições de arquivo também são detectadas automaticamente)
/reload                   # também re-escaneia o catálogo
```

O painel agrupa o catálogo por fonte com contagens e hints de argumento, depois os ledgers de falha — comandos **recusados** por shadow de built-in e arquivos **pulados** com o motivo do parse — e cada diretório varrido com marcador `✓`/`–` de existência:

```
⌘ Slash Commands ─────────────────────────
  9 comando(s) de 4 fonte(s)

  ▸ Projeto (.chatcli/commands) (2)
    /deploy       Deploy service          <env>
    /review-pr    Review a PR             <pr> [foco]

  ▸ Gemini CLI (1)
    /git:commit   Writes a conventional commit

  ⚠ Pulados (falha de parse — corrija o arquivo e ele carrega no próximo scan):
    ~/.gemini/commands/broken.toml
      unterminated """ string

  Diretórios varridos (ordem de precedência):
    ✓ ~/projeto/.chatcli/commands
    – ~/projeto/.claude/commands
```

O catálogo é servido de um cache com fingerprint por stat: lookups são gratuitos até um arquivo realmente mudar.

| Variável de ambiente | Default | Efeito |
| - | - | - |
| `CHATCLI_COMMANDS` | `true` | Chave mestra da feature inteira |
| `CHATCLI_COMMANDS_AUTOROUTE` | `true` | Auto-roteia comandos mode coder do chat para um run one-shot do coder |

***

## Exemplo: standup do time

```bash theme={"system"}
mkdir -p .chatcli/commands
cat > .chatcli/commands/standup.md <<'EOF'
---
description: Resumo de standup a partir dos commits recentes
argument-hint: [dias]
---
! git log --oneline --since="$1 days ago" | head -20

Com base nos commits acima, escreva um resumo de standup em 3 bullets.
EOF
```

Commite — todo o time (e os agents, via `@commands`) agora tem `/standup 2`.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.