> ## 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.

# Conexão Remota (chatcli connect)

> Conecte seu terminal a um servidor ChatCLI via gRPC: endereços, tokens e JWTs, TLS e mTLS, modos de credencial LLM, uso one-shot e solução de problemas.

O `chatcli connect` roda o seu ChatCLI local contra um [servidor ChatCLI](/pt/server/server-mode) remoto: as chamadas ao modelo vão para o servidor, que guarda as chaves dos provedores. Todo o resto (o REPL, os loops de `/agent` e `/coder`, as ferramentas `@`, contextos, memória) roda na sua máquina, então as ferramentas leem e alteram os **seus** arquivos.

## Conectar

```bash theme={"system"}
# Endereço como argumento posicional ou com --addr (ou CHATCLI_REMOTE_ADDR)
chatcli connect chatcli.example.com:50051 --tls --token "$CHATCLI_REMOTE_TOKEN"
chatcli connect --addr chatcli.example.com:50051 --tls --token "$CHATCLI_REMOTE_TOKEN"
```

Quando dá certo:

```text theme={"system"}
Connected to ChatCLI server (version: 1.214.0, provider: CLAUDEAI, model: claude-sonnet-5)
```

Quando o servidor roda um [K8s watcher](/pt/kubernetes/k8s-watcher), uma segunda linha avisa, e o contexto dele é somado a todo prompt do lado do servidor.

<Warning>
  A conexão é **TLS por padrão**, com ou sem `--tls`: um servidor com certificado publicamente confiável não precisa de flag, e um assinado por CA privada precisa de `--ca-cert ca.crt` (um arquivo de CA implica `--tls`, então a CA é usada mesmo quando `--tls` é omitido). Texto puro exige desligar explicitamente, com `CHATCLI_ALLOW_INSECURE=true`. Contra um servidor em texto puro (um `chatcli server` local, um chart com `tls.enabled=false` atrás de `kubectl port-forward`) você precisa de:

  ```bash theme={"system"}
  CHATCLI_ALLOW_INSECURE=true chatcli connect localhost:50051 --token "$CHATCLI_REMOTE_TOKEN"
  ```

  Sem isso a conexão falha com `tls: first record does not look like a TLS handshake`.
</Warning>

## Flags

| Flag | Variável | Descrição |
| - | - | - |
| `--addr <host:porta>` (ou posicional) | `CHATCLI_REMOTE_ADDR` | Endereço do servidor. Resolução `dns:///`: todo endereço para o qual o nome resolve é usado em round-robin |
| `--token <string>` | `CHATCLI_REMOTE_TOKEN` | Enviado como `authorization: Bearer <token>`: o token compartilhado do servidor **ou** um JWT |
| `--tls` | — | TLS 1.3 com as CAs do sistema, ou `--ca-cert`; sem ela o cliente continua discando TLS com as CAs do sistema, a menos que `CHATCLI_ALLOW_INSECURE=true` |
| `--ca-cert <caminho>` | — | Bundle da CA que assinou o certificado do servidor; implica `--tls` |
| `--provider <nome>` | — | Sobrescreve o provedor do servidor: `OPENAI`, `OPENAI_ASSISTANT`, `CLAUDEAI`, `BEDROCK`, `GOOGLEAI`, `XAI`, `ZAI`, `MINIMAX`, `MOONSHOT`, `STACKSPOT`, `OLLAMA`, `COPILOT`, `OPENROUTER`. `DEVIN` não é oferecido: a imagem do servidor não tem o Devin CLI |
| `--model <nome>` | — | Sobrescreve o modelo do servidor |
| `--llm-key <string>` | `CHATCLI_CLIENT_API_KEY` | Sua chave de API ou token OAuth do provedor, repassado ao servidor |
| `--use-local-auth` | — | Repassa a credencial OAuth de `~/.chatcli/auth-profiles.json` |
| `--client-id`, `--client-key`, `--realm`, `--agent-id` | — | Credenciais da StackSpot |
| `--ollama-url <url>` | — | URL base do Ollama para a requisição (veja [Ollama](#modos-de-credencial-llm)) |
| `-p <prompt>` | — | One-shot: envia um prompt, imprime a resposta e sai |
| `--raw` | — | Com `-p`: sem formatação Markdown/ANSI |
| `--max-tokens <n>` | — | Limite de tokens da resposta; sem ele, o servidor usa o `*_MAX_TOKENS` do provedor, senão o teto do catálogo do modelo |

Só por variável de ambiente no cliente (sem flag):

| Variável | Significado |
| - | - |
| `CHATCLI_ALLOW_INSECURE=true` | Disca em texto puro quando `--tls` não é passado |
| `CHATCLI_TLS_CLIENT_CERT`, `CHATCLI_TLS_CLIENT_KEY` | Certificado de cliente para mTLS; usado **só com `--tls`** |

Não existe flag `--server` nem override do nome do servidor TLS: o nome discado precisa estar no certificado do servidor.

## TLS e mTLS

```bash theme={"system"}
# TLS, CA privada
chatcli connect chatcli.example.com:50051 --tls --ca-cert ca.crt --token "$CHATCLI_REMOTE_TOKEN"

# TLS, certificado de CA pública (por exemplo atrás de um ingress na 443)
chatcli connect chatcli.example.com:443 --tls --token "$CHATCLI_REMOTE_TOKEN"

# TLS mútuo: o certificado é a credencial (role vinda do CHATCLI_MTLS_ROLE do servidor)
CHATCLI_TLS_CLIENT_CERT=alice.crt CHATCLI_TLS_CLIENT_KEY=alice.key \
  chatcli connect chatcli.example.com:50051 --tls --ca-cert ca.crt

# TLS mútuo mais JWT: identidade e role do JWT vencem as do certificado
CHATCLI_TLS_CLIENT_CERT=alice.crt CHATCLI_TLS_CLIENT_KEY=alice.key \
  chatcli connect chatcli.example.com:50051 --tls --ca-cert ca.crt --token "$JWT"
```

Pelo `kubectl port-forward` você disca `localhost`, então o certificado do servidor precisa de `localhost` (e `127.0.0.1`) nos SANs.

## Modos de credencial LLM

<Tabs>
  <Tab title="Credenciais do servidor">
    Sem flags de credencial: o servidor usa o próprio provedor e as próprias chaves.

    ```bash theme={"system"}
    chatcli connect chatcli.example.com:50051 --tls --token "$CHATCLI_REMOTE_TOKEN"
    ```

    Requisições que não nomeiam provedor nem modelo passam pela [cadeia de fallback](/pt/server/server-mode#cadeia-de-fallback) do servidor, quando existe.
  </Tab>

  <Tab title="Sua chave de API">
    ```bash theme={"system"}
    chatcli connect chatcli.example.com:50051 --tls --token "$CHATCLI_REMOTE_TOKEN" \
      --provider OPENAI --llm-key sk-xxx
    ```

    A chave viaja com cada requisição e só vale para ela; o servidor nunca a renova.
  </Tab>

  <Tab title="OAuth local">
    ```bash theme={"system"}
    # Uma vez, dentro do chatcli: /auth login anthropic   (ou openai-codex, github-copilot)
    chatcli connect chatcli.example.com:50051 --tls --token "$CHATCLI_REMOTE_TOKEN" --use-local-auth
    chatcli connect chatcli.example.com:50051 --tls --token "$CHATCLI_REMOTE_TOKEN" --use-local-auth --provider COPILOT
    ```

    Sem `--provider`, tenta Anthropic, depois OpenAI, depois GitHub Copilot. Só `CLAUDEAI`, `OPENAI` e `COPILOT` são provedores OAuth; os outros precisam de `--llm-key`.
  </Tab>

  <Tab title="StackSpot">
    ```bash theme={"system"}
    chatcli connect chatcli.example.com:50051 --tls --token "$CHATCLI_REMOTE_TOKEN" \
      --provider STACKSPOT --client-id <id> --client-key <key> --realm <realm> --agent-id <agent>
    ```
  </Tab>

  <Tab title="Ollama">
    Uma URL enviada pelo cliente precisa ser HTTPS num endereço público, senão o servidor recusa ([proteção contra SSRF](/pt/server/server-mode#proteção-contra-ssrf)):

    ```bash theme={"system"}
    chatcli connect chatcli.example.com:50051 --tls --token "$CHATCLI_REMOTE_TOKEN" \
      --provider OLLAMA --ollama-url https://ollama.example.com
    ```

    Para um Ollama em rede privada, configure-o no **servidor** (`OLLAMA_ENABLED=true`, `OLLAMA_BASE_URL=http://ollama:11434`) e conecte só com `--provider OLLAMA`.
  </Tab>
</Tabs>

## Modo one-shot

```bash theme={"system"}
chatcli connect chatcli.example.com:50051 --tls --token "$CHATCLI_REMOTE_TOKEN" \
  -p "Explique pod disruption budgets no Kubernetes"

# Saída para scripts
chatcli connect chatcli.example.com:50051 --tls --token "$CHATCLI_REMOTE_TOKEN" \
  --provider GOOGLEAI --llm-key "$GOOGLEAI_API_KEY" --model gemini-3.8-flash \
  -p "Resuma este diff: $(git diff HEAD~1)" --raw
```

O `-p` envia um `SendPrompt` e sai com status diferente de zero em caso de erro. Cada execução abre uma conexão nova e autentica de novo; um loop apertado não tem problema, porque o [limitador de falhas de autenticação](/pt/server/server-mode#limitador-de-falhas-de-autenticação) do servidor só conta autenticações que falham.

## Modo interativo

Sem `-p`, você ganha o REPL completo com o modelo remoto:

```bash theme={"system"}
chatcli connect chatcli.example.com:50051 --tls --token "$CHATCLI_REMOTE_TOKEN"
```

* `/agent`, `/coder`, `@file`, `@git`, `@command` e as outras ferramentas rodam **localmente**; só as chamadas ao modelo vão para o servidor.
* `/switch` troca provedor ou modelo; `/cost` precifica o uso real de tokens que o servidor informa em cada resposta.
* As respostas chegam em streaming conforme o provedor gera (`StreamPrompt`); a mensagem final traz o usage, o motivo de parada, e o provedor e o modelo que responderam.

### Plugins remotos, sessões e status do watcher

O `chatcli connect` vincula a sessão ao servidor exatamente como o comando `/connect` **dentro do REPL**, que troca uma sessão local já em execução:

```text theme={"system"}
/connect chatcli.example.com:50051 --tls --ca-cert ca.crt --token <token>
```

| Recurso | `/connect` dentro do REPL | `chatcli connect` |
| - | - | - |
| Plugins do servidor no `/plugin list`, executados no servidor | sim | sim |
| `/agent list` e `/agent skills` somam os agentes e skills do servidor (`Agentes no servidor (<endereço>)`, `Skills no servidor (<endereço>)`) depois dos locais | sim | sim |
| `/session save` / `/session load` oferecem local, remoto ou ambos | sim | sim |
| `/watch status` consulta o watcher do servidor | sim | sim |
| `/disconnect` volta ao provedor local | sim | sim |
| Linha `Server has N plugins, N agents, N skills available` | sim | não |

O servidor lista e executa plugins só para chamadores `user` e `admin`: uma credencial `readonly` não vê plugins remotos e não consegue baixar nenhum (`PermissionDenied`).

O `/connect` aceita `--token`, `--tls`, `--ca-cert` (que aqui também implica `--tls`), `--provider`, `--model`, `--llm-key`, `--use-local-auth` e as flags de StackSpot/Ollama. Ele não lê `CHATCLI_REMOTE_TOKEN`; passe `--token`. `CHATCLI_ALLOW_INSECURE` e as variáveis de mTLS valem como no `chatcli connect`.

O `/watch status` num servidor remoto imprime:

```text theme={"system"}
 K8s Watcher (remote): Watching 3 targets: 2 healthy, 1 warning, 0 critical
   Target: multi/3 targets | Pods: 9 | Alerts: 1 | Snapshots: 42
```

## Padrões por variável de ambiente

```bash theme={"system"}
export CHATCLI_REMOTE_ADDR=chatcli.example.com:50051
export CHATCLI_REMOTE_TOKEN=<token ou JWT>
chatcli connect --tls --ca-cert ca.crt
```

## Múltiplas réplicas

O cliente resolve o endereço com `dns:///` e balanceia em round-robin entre todos os endereços, mandando ping em cada conexão a cada 30 segundos (timeout de 5 segundos) para descartar pods mortos. Contra um servidor no Kubernetes com mais de uma réplica, aponte para um Service headless (`service.headless: true` no chart; automático no operator quando `spec.replicas > 1`).

## Solução de problemas

| Mensagem | Causa | Correção |
| - | - | - |
| `server address is required (use --addr or positional argument)` | Sem endereço | Passe um, ou defina `CHATCLI_REMOTE_ADDR` |
| `transport: authentication handshake failed: tls: first record does not look like a TLS handshake` | Servidor em texto puro, cliente discou TLS | `CHATCLI_ALLOW_INSECURE=true`, ou ligue TLS no servidor |
| `x509: certificate signed by unknown authority` | CA privada não confiável | `--tls --ca-cert ca.crt` |
| `x509: certificate is valid for …, not …` | Nome discado fora dos SANs do certificado | Disque um nome dos SANs, ou reemita o certificado |
| `error reading server preface: remote error: tls: certificate required` | O servidor exige mTLS | `CHATCLI_TLS_CLIENT_CERT`/`CHATCLI_TLS_CLIENT_KEY` com `--tls` |
| `CHATCLI_TLS_CLIENT_CERT set but CHATCLI_TLS_CLIENT_KEY is missing` | Metade do par de chaves | Defina as duas |
| `failed to read CA certificate: …` / `failed to parse CA certificate` | Caminho do `--ca-cert` errado ou não é PEM | Aponte para o arquivo PEM da CA |
| `connect: connection refused` | Nada escutando nesse endereço | Confira endereço, porta, port-forward e o bind do servidor |
| `Connected … (… provider: remote, model: remote)` seguido de `authentication failed` | O servidor recusou o token (o health não exige token, o `GetServerInfo` exige) | Use o token certo; confira o `exp` se for JWT |
| `authentication failed` em toda chamada de um host com token válido; o log do servidor mostra `auth failure rate limit exceeded` | Outro chamador no mesmo host esgotou a cota de falhas do host (5 autenticações falhas, depois uma a cada 12 s) | Corrija a credencial desse chamador; credenciais válidas nunca são limitadas e a cota repõe sozinha |
| `token expired` | JWT passou do `exp` | Gere um novo |
| `rate limit exceeded, retry after N seconds` | Acima do rate limit por chamador do servidor | Espere N segundos (no mínimo 1; o mesmo valor vem no header `retry-after`), ou peça `CHATCLI_RATE_LIMIT_*` maiores |
| `invalid provider configuration: … non-HTTPS provider URLs are blocked …` | `--ollama-url http://…` | URL HTTPS, ou configure o Ollama no servidor |
| `--use-local-auth only supports OAuth providers (CLAUDEAI, OPENAI, COPILOT) …` | Outro provedor com `--use-local-auth` | Use `--llm-key` |
| `no local OAuth credentials found. Run 'chatcli' then '/auth login anthropic' …` | Nenhum login OAuth salvo | Rode `/auth login …` antes |

## Próximos passos

<CardGroup cols={2}>
  <Card title="Modo Servidor" icon="server" href="/pt/server/server-mode">
    Configure e opere o servidor
  </Card>

  <Card title="Docker e Kubernetes" icon="docker" href="/pt/start/docker-deployment">
    Faça o deploy
  </Card>

  <Card title="K8s Watcher" icon="binoculars" href="/pt/kubernetes/k8s-watcher">
    Contexto do Kubernetes em todo prompt
  </Card>
</CardGroup>


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