@nio-cli/cli 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/.env.example +118 -114
  2. package/Dockerfile.gateway +20 -20
  3. package/README.md +539 -539
  4. package/dist/adapters/pg/auth-event-repository.js +4 -4
  5. package/dist/adapters/pg/auth-session-repository.js +2 -2
  6. package/dist/adapters/pg/client.js +62 -8
  7. package/dist/adapters/pg/client.js.map +1 -1
  8. package/dist/adapters/pg/dependency-event-repository.js +4 -4
  9. package/dist/adapters/pg/login-challenge-repository.js +2 -2
  10. package/dist/adapters/pg/login-ip-repository.js +3 -3
  11. package/dist/adapters/pg/session-repository.js +3 -3
  12. package/dist/cli/commands/auth.js +38 -16
  13. package/dist/cli/commands/auth.js.map +1 -1
  14. package/dist/cli/commands/completion.js +28 -28
  15. package/dist/cli/commands/docs/html.js +78 -78
  16. package/dist/cli/copy/auth.json +13 -13
  17. package/dist/cli/copy/flows.json +5 -5
  18. package/dist/cli/copy/init.json +15 -15
  19. package/dist/cli/copy/sync.json +3 -3
  20. package/dist/cli.js +3 -7
  21. package/dist/cli.js.map +1 -1
  22. package/dist/gateway/index.js +11 -1
  23. package/dist/gateway/index.js.map +1 -1
  24. package/dist/lib/auth/gateway-process.js +59 -2
  25. package/dist/lib/auth/gateway-process.js.map +1 -1
  26. package/dist/lib/auth/nio-config.js +58 -14
  27. package/dist/lib/auth/nio-config.js.map +1 -1
  28. package/dist/lib/clients/client-configs.js +7 -3
  29. package/dist/lib/clients/client-configs.js.map +1 -1
  30. package/dist/lib/clients/nio-oc-config.js +84 -0
  31. package/dist/lib/clients/nio-oc-config.js.map +1 -0
  32. package/dist/lib/exec/plan-delegate.js.map +1 -1
  33. package/dist/lib/exec/qwen-client.js +39 -24
  34. package/dist/lib/exec/qwen-client.js.map +1 -1
  35. package/dist/lib/shutdown.js +25 -0
  36. package/dist/lib/shutdown.js.map +1 -0
  37. package/dist/mcp-server-lang.js +0 -0
  38. package/dist/mcp-server.js +0 -0
  39. package/dist/profiles/analyst.js +1 -0
  40. package/dist/profiles/analyst.js.map +1 -1
  41. package/dist/profiles/bi.js +1 -0
  42. package/dist/profiles/bi.js.map +1 -1
  43. package/dist/profiles/dba.js +3 -2
  44. package/dist/profiles/dba.js.map +1 -1
  45. package/dist/profiles/mcps.js.map +1 -1
  46. package/dist/profiles/scientist.js +3 -1
  47. package/dist/profiles/scientist.js.map +1 -1
  48. package/dist/tui/app.js +44 -13
  49. package/dist/tui/app.js.map +1 -1
  50. package/dist/tui/components.js +9 -8
  51. package/dist/tui/components.js.map +1 -1
  52. package/dist/tui/launch.js +16 -2
  53. package/dist/tui/launch.js.map +1 -1
  54. package/dist/tui/opencode.js +17 -0
  55. package/dist/tui/opencode.js.map +1 -1
  56. package/dist/tui/palette.js +29 -0
  57. package/dist/tui/palette.js.map +1 -1
  58. package/dist/tui/state.js +146 -92
  59. package/dist/tui/state.js.map +1 -1
  60. package/docker/docker-compose.yml +114 -114
  61. package/docker/kong.yml +59 -55
  62. package/package.json +97 -97
package/README.md CHANGED
@@ -1,339 +1,339 @@
1
- # NIO-CLI
2
-
3
- **Orquestrador de ambientes de desenvolvimento.** Você escolhe um perfil,
4
- responde um wizard, e a CLI — com auxílio de IA via MCP — materializa o ambiente:
5
- toolchains, linguagens, frameworks, dotfiles, aliases e IDE. A entidade central é
6
- a **Sessão**: um ambiente isolado, com UUID, persistido no Postgres.
7
-
8
- > **Guia rápido de uso:** `nio --help` (primeiros passos + como usar a interface do `nio ai`).
9
- > **Manual completo:** `nio docs` no terminal · `nio docs --html --open` como página.
10
-
11
- ---
12
-
13
- ## Como funciona
14
-
15
- ```
16
- você → nio (CLI) ──► nio-gateway ──► Postgres (login: senha + JWT, 2º fator opcional)
17
-
18
- ├──► SessionManager / EnvironmentBuilder (materializa toolchains, MCPs, dotfiles)
19
-
20
- └──► opencode.json ──► OpenCode (operador de IA)
21
- └── MCP `nio` (tools nio_*) ──► SessionManager ──► Postgres
22
- ```
23
-
24
- 1. **Você se autentica** (`nio register` / `nio login`). O `nio-gateway` — um
25
- serviço HTTP loopback — verifica a senha (argon2id), dispara o 2º fator se
26
- estiver ativo, e devolve um **JWT** salvo em `~/.nio/session.json`.
27
- 2. **Você monta uma sessão** (`nio init`). O wizard pergunta perfil + recipe, e o
28
- `EnvironmentBuilder` garante os toolchains, resolve os MCPs e grava o `config`
29
- materializado na linha `sessions` do Postgres. A sessão é isolada, tem UUID e
30
- pode ser reativada depois (`nio sessions`).
31
- 3. **`nio ai` abre a interface NIO** — o `opencode serve` headless
32
- (`opencode/big-pickle`, MCP `nio` + MCPs do perfil) e o chat do NIO em Ink
33
- (fluxo em linha estilo Claude Code, paleta `/`, `Tab` troca de modo). O
34
- Headroom foi desativado ([ADR 0010](docs/adr/0010-headroom-desativado.md)) — o
35
- client fala direto no LLM, **não precisa de Docker**. Com IDE, roda num
36
- terminal integrado dela. A partir daí o agente tem as tools `nio_*` —
37
- criar/ativar sessão, re-materializar ambiente, delegar execução. Detalhe de
38
- uso: **[Interface do `nio ai`](#interface-do-nio-ai-tui)**.
39
-
40
- O **Postgres é a fonte da verdade** do domínio (usuários, sessões, trilha de
41
- auth). A CLI e o gateway só falam com o banco que **você** configurar — não há
42
- default, não há banco embutido.
43
-
44
- ---
45
-
46
- ## Instalação
47
-
48
- Precisa de **Node.js 20.12+**. Instala como pacote global:
49
-
50
- ```bash
51
- npm i -g @nio-cli/cli
52
- ```
53
-
54
- Ficam no PATH: `nio` (CLI), `nio-gateway` (serviço de auth), `nio-cli` e
55
- `nio-lang` (servidores MCP).
56
-
57
- ### Pré-requisitos de runtime
58
-
59
- | Requisito | Pra quê | Como |
60
- |---|---|---|
61
- | **PostgreSQL** alcançável | fonte da verdade (sessões, usuários) | schema em `db/schema.sql` aplicado uma vez |
62
- | **`JWT_SECRET`** (segredo do time) | assinar/validar as sessões | mesmo valor em toda máquina |
63
- | **OpenCode** | operador de IA | o `nio init` oferece instalar (`npm i -g opencode-ai`) |
64
- | **Docker** | **não é necessário** pro `nio ai` (Headroom desativado, ADR 0010 — client fala direto no LLM). Ainda usado por `nio docker` (toolkit/cluster) e pelo gateway conteinerizado | `docker compose version` |
65
- | *(opcional)* WhatsApp Business API (Meta Graph) | 2º fator | `WHATSAPP_ENDPOINT_URL` + `WHATSAPP_TOKEN` (+ template) |
66
-
67
- ---
68
-
69
- ## Configuração
70
-
71
- **Você não precisa exportar nada no shell.** Rode `nio config setup` — o wizard
72
- pede o `NIO_DATABASE_URL` (que o time te passa) e o `JWT_SECRET`, **testa a
73
- conexão** e grava em `~/.nio/config.env` (chmod 600, nunca commitado). O `nio init`,
74
- `nio register` e `nio login` disparam esse wizard sozinhos se a config faltar; se
75
- estiver presente mas errada, param com uma mensagem dizendo exatamente o quê.
76
-
77
- ```bash
78
- nio config setup # wizard interativo (cola os valores, testa, salva)
79
- nio config check # confere: completa? banco responde? (--json pra CI)
80
- nio config path # ~/.nio/config.env
81
- ```
82
-
83
- A CLI carrega as variáveis nesta precedência (shell sempre vence os arquivos):
84
-
85
- ```
86
- env do shell > $NIO_ENV_FILE > ./.env > ~/.nio/config.env
87
- ```
88
-
89
- Conteúdo de `~/.nio/config.env` (o wizard gera; dá pra editar à mão):
90
-
91
- ```bash
92
- NIO_DATABASE_URL=postgres://usuario:senha@HOST:5432/nio_cli
93
- # NIO_DATABASE_SSL=true # só se o banco exigir TLS (gerenciado/nuvem)
94
- JWT_SECRET=<mesmo-valor-do-time>
95
-
96
- # 2º fator (WhatsApp OTP via Meta Graph) — opcional, só no lado do gateway
97
- # WHATSAPP_ENDPOINT_URL=https://graph.facebook.com/v25.0/1076830002188066/messages
98
- # WHATSAPP_TOKEN=<bearer da Meta Graph> # app secret; rotaciona ~24h
99
- # WHATSAPP_TEMPLATE_NAME=autenticao # template de autenticação aprovado
100
- # WHATSAPP_TEMPLATE_LANGUAGE=pt_BR # variação do template
101
- #
102
- # DEV: se WHATSAPP_ENDPOINT_URL for loopback (127.0.0.1/localhost — o mock
103
- # `bun run dev:whatsapp-echo`), o gateway entra em "modo echo": NENHUM WhatsApp real sai.
104
- # A CLI avisa e mostra o código direto; `nio security status` mostra o backend.
105
- ```
106
-
107
- > Alternativa pra time: gere o `~/.nio/config.env` uma vez e distribua o arquivo
108
- > (é só `KEY=value`) — a CLI valida no primeiro comando.
109
-
110
- | Variável | Prefixo | Lida por |
111
- |---|---|---|
112
- | `NIO_DATABASE_URL` / `NIO_DATABASE_SSL` | `NIO_` | tudo que toca o banco |
113
- | `JWT_SECRET` / `JWT_EXPIRES_IN` | **sem** prefixo (segredo do time) | `nio-gateway` + `nio-cli` |
114
- | `WHATSAPP_ENDPOINT_URL` / `WHATSAPP_TOKEN` (+ `WHATSAPP_TEMPLATE_NAME` / `WHATSAPP_TEMPLATE_LANGUAGE`) | **sem** prefixo | `nio-gateway` |
115
- | `NIO_GATEWAY_HOST` (default `127.0.0.1`) | `NIO_` | `nio-gateway` — `0.0.0.0` p/ Kong em container |
116
- | `NIO_GATEWAY_URL` (default `http://127.0.0.1:3000`) | `NIO_` | a CLI acha o nio-gateway (Kong na frente = aponta :8000) |
117
-
118
- O schema de conexão é sempre `postgres://…`; um destino inválido falha explícito,
119
- nunca cai num default silencioso.
120
-
121
- ### Backend de IA próprio (uso fora da rede NIO)
122
-
123
- O motor de IA (`nio ai`/`exec`/`plan`) fala com um backend OpenAI-compatível
124
- (`/v1`). **O default aponta pra infra interna** (`http://192.168.0.140:8001/v1`,
125
- modelo `RedHatAI/Qwen3.8-27B-INT4`) — fora dessa rede, suba seu próprio
126
- vLLM (ou compatível) e aponte a CLI pra ele em `~/.nio/config.env`
127
- (`nio config path`; `NIO_AI_*` **não** valem no `.env` do projeto):
128
-
129
- ```bash
130
- NIO_AI_BASE_URL=https://seu-vllm:8000/v1 # raiz /v1 (o SDK anexa /chat/completions)
131
- NIO_AI_MODEL=seu-org/seu-modelo # id EXATO que o backend serve em /v1/models
132
- NIO_AI_CONTEXT=65536 # max_model_len do backend; 0 = usa catálogo
133
- NIO_AI_OUTPUT=2048 # teto de saída (input + output ≤ contexto!)
134
- NIO_AI_MAX_INPUT=32000 # trava de input por prompt (0 = desativa)
135
- ```
136
-
137
- Confira com `nio config check` — ele sonda `GET <base>/models` e avisa (sem
138
- reprovar) se o backend está fora do ar ou não serve o modelo configurado.
139
-
140
- ---
141
-
142
- ## Primeiros passos
143
-
144
- Um comando só:
145
-
146
- ```bash
147
- nio # (ou `nio start`) — a esteira guiada
148
- ```
149
-
150
- A esteira detecta em que ponto você está e conduz — **config → gateway → login →
151
- sessão → handoff pro OpenCode** —, perguntando antes de cada passo. Ela sobe o
152
- `nio-gateway` sozinha se faltar. Se você sair no meio, ela imprime a linha exata
153
- pra retomar (`nio start`); nada morre no silêncio.
154
-
155
- Por dentro, é isto (cada um roda na mão também):
156
-
157
- ```bash
158
- nio config setup # cola NIO_DATABASE_URL + JWT_SECRET (o time te passa), testa, salva
159
- nio-gateway # gateway de auth (a esteira sobe sozinha se faltar)
160
- nio register # cria seu usuário na base compartilhada → cai no login
161
- nio login # autentica (salva o JWT em ~/.nio/session.json)
162
- nio security enable-2fa # (opcional) 2º fator
163
- nio init # monta o ambiente da sessão → `nio ai` (opencode serve + chat NIO, num terminal da IDE)
164
- ```
165
-
166
- O `nio-gateway` só é necessário pros comandos de auth (`login`/`logout`/
167
- `verify-2fa`/`security`). Todo o resto — `init`, `sessions`, as tools MCP —
168
- fala com o Postgres direto usando o JWT local. Rode `nio debug` a qualquer
169
- momento pra ver o que está ok e o que falta.
170
-
171
- ---
172
-
173
- ## Arquitetura
174
-
175
- Hexagonal. O núcleo não conhece IO; os adapters implementam os contratos.
176
-
177
- ```
178
- entrypoints: src/cli.ts (nio) src/gateway/index.ts (nio-gateway)
179
- src/mcp-server.ts (nio-cli) src/mcp-server-lang.ts (nio-lang)
180
- app: SessionManager · EnvironmentBuilder · DependencyWatcher · DockerManager
181
- core/: types.ts (entidades + enums) + ports por domínio, sem IO:
182
- repositories.ts · environment.ts · docker.ts · messaging.ts · lang.ts
183
- adapters/: pg/ (Postgres) ide/ (vscode) pkg/ (npm,pip,…) docker/ sms/ skills/ lang/
184
- profiles/: catálogo dos 6 perfis (fixos no fonte)
185
- ```
186
-
187
- - **Runtime:** Node 20.12+ é o alvo. Bun roda o projeto em dev, mas **nada**
188
- depende de API exclusiva do Bun — só as equivalentes de `node:*`.
189
- - **Build:** `tsc` puro → `dist/`. Sem bundler.
190
- - **Banco:** `pg` + um `Pool` único (`src/adapters/pg/client.ts`). Sem Supabase,
191
- sem PostgREST, sem `Bun.sql`.
192
- - **Gateway:** `http.createServer` nativo, loopback, atrás do Kong OSS (opcional,
193
- pra rate-limiting). JWT HS256, `jti` = id da `auth_session`. Trilha de auth em
194
- stderr estruturado — nunca a senha nem o OTP em texto puro.
195
- - **Contrato "nunca lança"** nos ports de IO (`ToolchainGateway`, `IdeGateway`,
196
- `DockerGateway`, `SmsSender`): falha vira um resultado `{ status, error? }`.
197
-
198
- Detalhes: [`docs/arch/`](docs/arch/) (uma `ARQUITETURA-*.md` por camada) e os
199
- [ADRs](docs/adr/). Histórico cronológico: [`docs/PROGRESSO.md`](docs/PROGRESSO.md).
200
-
201
- ### Perfis
202
-
203
- Fixos no fonte (`src/core/types.ts`) — novos perfis só entram alterando o código:
204
-
205
- `fullstack` · `analyst` · `scientist` · `dba` · `qa` · `bi`
206
-
207
- ---
208
-
209
- ## Autenticação
210
-
211
- ```bash
212
- nio register # cria o usuário (user_cli), senha com hash argon2id
213
- nio login # autentica via nio-gateway e salva o JWT em ~/.nio/session.json
214
- nio whoami # mostra quem está logado (--json pra saída estável)
215
- nio logout # revoga a auth_session no banco e limpa a sessão local
216
- ```
217
-
218
- ### 2º fator (WhatsApp)
219
-
220
- Opt-in por conta. Com `auth_2` ativo, o `nio login` pede um código de 6 dígitos
221
- enviado por WhatsApp (template de autenticação da Meta Graph); se a mensagem não
222
- chega, vale um dos 10 **códigos de backup** (mostrados uma vez no `enable-2fa`).
223
-
224
- ```bash
225
- nio security enable-2fa # cadastra o celular, confirma via WhatsApp, mostra os backups
226
- nio security status # ativo? número (mascarado)? quantos backups restam?
227
- nio security disable-2fa
228
- nio security regenerate-backup-codes
229
- ```
230
-
231
- O gateway gera/valida o OTP em processo (sem Twilio, sem broker), guarda só o
232
- **HMAC** do código (TTL 5 min, 3 tentativas, uso único) e manda a mensagem pela
233
- **WhatsApp Business API (Meta Graph)**. Sem `WHATSAPP_ENDPOINT_URL`/`WHATSAPP_TOKEN`
234
- no ambiente, o login com `auth_2` responde `503 "2FA não configurado"` — o login
235
- de 1 fator segue normal.
236
- Detalhes: [spec 0004](docs/specs/auth/0004-login-2fa-sms-otp.md) ·
237
- [ADR 0006](docs/adr/0006-2fa-sms-otp.md) ·
238
- [`docs/arch/ARQUITETURA-GATEWAY.md`](docs/arch/ARQUITETURA-GATEWAY.md).
239
-
240
- Pra testar sem WhatsApp real, o repo traz um mock: `bun run dev:whatsapp-echo` sobe
241
- um endpoint local que imprime o código no terminal (aponte `WHATSAPP_ENDPOINT_URL` pra ele).
242
-
243
- ---
244
-
245
- ## Operador de IA (`nio ai`)
246
-
247
- No fim do `nio init` a CLI sobe o **client de IA** da sessão — e o mesmo `nio ai`
248
- retoma a qualquer momento. Ele:
249
-
250
- 1. **Prepara o `opencode.json`** — grava o provider `opencode` **direto no OpenCode Zen**
251
- (sem `baseURL` de proxy), junto do `model: opencode/big-pickle`, do MCP `nio`, dos MCPs
252
- do perfil e de um bloco `permission` semeado (allowlist só-leitura → `allow`, resto →
253
- `ask`). O **Headroom foi desativado** ([ADR 0010](docs/adr/0010-headroom-desativado.md)):
254
- o client fala direto no LLM, sem compressão — **não precisa de Docker** pro `nio ai`.
255
- (O `nio docker headroom` continua existindo, dormente, pra quem quiser subir manualmente.)
256
- 2. **Sobe o `opencode serve` headless e abre a interface NIO** (Ink). O motor é o
257
- `opencode/big-pickle`; a casca é nossa. Se a sessão tem IDE (VS Code / Cursor), o
258
- `nio init` grava um `.vscode/tasks.json` (task `NIO`, `runOn: folderOpen`) e o
259
- `nio ai` sobe num **terminal integrado da IDE** — uma superfície, não duas. Sem
260
- IDE, roda no terminal atual. Sem TTY → recusa com mensagem; sem `opencode` no
261
- PATH → cai na TUI do OpenCode.
262
-
263
- Ver [`docs/arch/ARQUITETURA-CLIENTE-IA.md`](docs/arch/ARQUITETURA-CLIENTE-IA.md),
264
- [`docs/arch/ARQUITETURA-TUI-UX-SPRINTS.md`](docs/arch/ARQUITETURA-TUI-UX-SPRINTS.md) e
265
- [`docs/arch/ARQUITETURA-TUI-INTERACOES-MOTOR.md`](docs/arch/ARQUITETURA-TUI-INTERACOES-MOTOR.md).
266
-
267
- ### Interface do `nio ai` (TUI)
268
-
269
- Chat no terminal (Ink) sobre o `opencode/big-pickle`, **em uma superfície só** — no
270
- estilo do Claude Code. O que o motor faz aparece **em linha**, conforme acontece:
271
- o raciocínio (`✻`), cada ferramenta (`● nome(args)` + `⎿` a saída), o checklist
272
- (`☑ ◐ ☐`), os arquivos tocados, o diff da rodada (`✎ N arquivo(s) +x −y`) e os
273
- tokens/custo no rodapé de cada resposta. Sem sidebar, sem janela extra.
274
-
275
- **Digitar & enviar**
276
-
277
- | Tecla | Faz |
278
- |---|---|
279
- | `Enter` | envia o prompt |
280
- | `\` + `Enter` · `Ctrl-J` | quebra linha — o prompt é multi-linha e cresce sozinho |
281
- | `←` `→` `↑` `↓` | move o cursor dentro do texto |
282
- | `Ctrl-A` / `Ctrl-E` | início / fim da linha |
283
- | `Ctrl-W` / `Ctrl-U` / `Ctrl-K` | apaga a palavra anterior / até o início / até o fim |
284
- | colar um bloco | entra literal (várias linhas **não** enviam sozinhas) |
285
-
286
- **Modos** — o modo troca o comportamento do agente
287
-
288
- | Tecla | Faz |
289
- |---|---|
290
- | `Tab` | alterna entre os agentes primários do `opencode.json` (`build` → `plan` → …) |
291
- | `build` | o agente **executa** (edita, roda comando) |
292
- | `plan` | o agente **só propõe** — não toca nada |
293
-
294
- O modo atual fica no rodapé: `[build]`.
295
-
296
- **Paleta de comandos**
297
-
298
- | Tecla | Faz |
299
- |---|---|
300
- | `/` | abre a lista inline — comandos do `nio` + capacidades do operador |
301
- | `↑` `↓` + `Enter` | roda o comando / manda a capacidade pro agente / abre o painel |
302
- | `Esc` | fecha a lista — o texto que você já digitou **continua lá** |
303
-
304
- **Quando o agente te interrompe**
305
-
306
- - **Permissão** (rodar shell, editar arquivo, chamar MCP…) → modal:
307
- `a`/`Enter` permite uma vez · `s` permite **sempre** (salva a regra no `opencode.json`) · `d`/`Esc` nega.
308
- Pedidos em paralelo entram numa **fila** (`+N na fila`); um sub-agente travado é
309
- reconciliado sozinho em ~4s — não trava mais em "processando".
310
- - **Pergunta aberta** — o agente termina com "?" → o cue `↳ o nio perguntou` aparece acima do input.
311
- - **Lista de opções** — o agente listou `1./2./3.` → menu `↑`/`↓`+`Enter` pra escolher; ou ignore e escreva livre.
312
-
313
- **Acompanhar & controlar**
314
-
315
- | Tecla | Faz |
316
- |---|---|
317
- | `Ctrl-R` | expande / colapsa o raciocínio (`✻`) — ver o agente "pensar" ao vivo |
318
- | `Esc` | durante o processamento: **aborta o turno** |
319
-
320
- `NIO_DEBUG=1 nio ai` grava cada evento cru do motor em `~/.nio/tui.log` (nunca no
321
- terminal — corromperia o render).
322
-
323
- > A interface NIO (Ink) está na **fatia 2a** ([ADR 0008](docs/adr/0008-interface-nio-ink.md)).
324
- > A paridade completa com o OpenCode (diff viewer, file tree, seletor de modelo…) é a 2b.
325
- > Multi-cliente (OpenCode | Codex) e o ladder de failover entre modelos seguem
326
- > parkeados em
327
- > [`docs/arch/ARQUITETURA-CLIENTES-MULTI-FUTURO.md`](docs/arch/ARQUITETURA-CLIENTES-MULTI-FUTURO.md)
328
- > ([ADR 0004](docs/adr/0004-operador-ia-unico.md)).
329
-
330
- ---
331
-
332
- ## Comandos do CLI
333
-
334
- Operações do CLI, **sem o binário na frente** (declarado no cabeçalho da tabela).
335
- Gerada da fonte por `npm run gen:docs`. Ajuda de qualquer comando: `nio <cmd> --help`.
336
-
1
+ # NIO-CLI
2
+
3
+ **Orquestrador de ambientes de desenvolvimento.** Você escolhe um perfil,
4
+ responde um wizard, e a CLI — com auxílio de IA via MCP — materializa o ambiente:
5
+ toolchains, linguagens, frameworks, dotfiles, aliases e IDE. A entidade central é
6
+ a **Sessão**: um ambiente isolado, com UUID, persistido no Postgres.
7
+
8
+ > **Guia rápido de uso:** `nio --help` (primeiros passos + como usar a interface do `nio ai`).
9
+ > **Manual completo:** `nio docs` no terminal · `nio docs --html --open` como página.
10
+
11
+ ---
12
+
13
+ ## Como funciona
14
+
15
+ ```
16
+ você → nio (CLI) ──► nio-gateway ──► Postgres (login: senha + JWT, 2º fator opcional)
17
+
18
+ ├──► SessionManager / EnvironmentBuilder (materializa toolchains, MCPs, dotfiles)
19
+
20
+ └──► opencode.json ──► OpenCode (operador de IA)
21
+ └── MCP `nio` (tools nio_*) ──► SessionManager ──► Postgres
22
+ ```
23
+
24
+ 1. **Você se autentica** (`nio register` / `nio login`). O `nio-gateway` — um
25
+ serviço HTTP loopback — verifica a senha (argon2id), dispara o 2º fator se
26
+ estiver ativo, e devolve um **JWT** salvo em `~/.nio/session.json`.
27
+ 2. **Você monta uma sessão** (`nio init`). O wizard pergunta perfil + recipe, e o
28
+ `EnvironmentBuilder` garante os toolchains, resolve os MCPs e grava o `config`
29
+ materializado na linha `sessions` do Postgres. A sessão é isolada, tem UUID e
30
+ pode ser reativada depois (`nio sessions`).
31
+ 3. **`nio ai` abre a interface NIO** — o `opencode serve` headless
32
+ (`opencode/big-pickle`, MCP `nio` + MCPs do perfil) e o chat do NIO em Ink
33
+ (fluxo em linha estilo Claude Code, paleta `/`, `Tab` troca de modo). O
34
+ Headroom foi desativado ([ADR 0010](docs/adr/0010-headroom-desativado.md)) — o
35
+ client fala direto no LLM, **não precisa de Docker**. Com IDE, roda num
36
+ terminal integrado dela. A partir daí o agente tem as tools `nio_*` —
37
+ criar/ativar sessão, re-materializar ambiente, delegar execução. Detalhe de
38
+ uso: **[Interface do `nio ai`](#interface-do-nio-ai-tui)**.
39
+
40
+ O **Postgres é a fonte da verdade** do domínio (usuários, sessões, trilha de
41
+ auth). A CLI e o gateway só falam com o banco que **você** configurar — não há
42
+ default, não há banco embutido.
43
+
44
+ ---
45
+
46
+ ## Instalação
47
+
48
+ Precisa de **Node.js 20.12+**. Instala como pacote global:
49
+
50
+ ```bash
51
+ npm i -g @nio-cli/cli
52
+ ```
53
+
54
+ Ficam no PATH: `nio` (CLI), `nio-gateway` (serviço de auth), `nio-cli` e
55
+ `nio-lang` (servidores MCP).
56
+
57
+ ### Pré-requisitos de runtime
58
+
59
+ | Requisito | Pra quê | Como |
60
+ |---|---|---|
61
+ | **PostgreSQL** alcançável | fonte da verdade (sessões, usuários) | schema em `db/schema.sql` aplicado uma vez |
62
+ | **`JWT_SECRET`** (segredo do time) | assinar/validar as sessões | mesmo valor em toda máquina |
63
+ | **OpenCode** | operador de IA | o `nio init` oferece instalar (`npm i -g opencode-ai`) |
64
+ | **Docker** | **não é necessário** pro `nio ai` (Headroom desativado, ADR 0010 — client fala direto no LLM). Ainda usado por `nio docker` (toolkit/cluster) e pelo gateway conteinerizado | `docker compose version` |
65
+ | *(opcional)* WhatsApp Business API (Meta Graph) | 2º fator | `WHATSAPP_ENDPOINT_URL` + `WHATSAPP_TOKEN` (+ template) |
66
+
67
+ ---
68
+
69
+ ## Configuração
70
+
71
+ **Você não precisa exportar nada no shell.** Rode `nio config setup` — o wizard
72
+ pede o `NIO_DATABASE_URL` (que o time te passa) e o `JWT_SECRET`, **testa a
73
+ conexão** e grava em `~/.nio/config.env` (chmod 600, nunca commitado). O `nio init`,
74
+ `nio register` e `nio login` disparam esse wizard sozinhos se a config faltar; se
75
+ estiver presente mas errada, param com uma mensagem dizendo exatamente o quê.
76
+
77
+ ```bash
78
+ nio config setup # wizard interativo (cola os valores, testa, salva)
79
+ nio config check # confere: completa? banco responde? (--json pra CI)
80
+ nio config path # ~/.nio/config.env
81
+ ```
82
+
83
+ A CLI carrega as variáveis nesta precedência (shell sempre vence os arquivos):
84
+
85
+ ```
86
+ env do shell > $NIO_ENV_FILE > ./.env > ~/.nio/config.env
87
+ ```
88
+
89
+ Conteúdo de `~/.nio/config.env` (o wizard gera; dá pra editar à mão):
90
+
91
+ ```bash
92
+ NIO_DATABASE_URL=postgres://usuario:senha@HOST:5432/nio_cli
93
+ # NIO_DATABASE_SSL=true # só se o banco exigir TLS (gerenciado/nuvem)
94
+ JWT_SECRET=<mesmo-valor-do-time>
95
+
96
+ # 2º fator (WhatsApp OTP via Meta Graph) — opcional, só no lado do gateway
97
+ # WHATSAPP_ENDPOINT_URL=https://graph.facebook.com/v25.0/1076830002188066/messages
98
+ # WHATSAPP_TOKEN=<bearer da Meta Graph> # app secret; rotaciona ~24h
99
+ # WHATSAPP_TEMPLATE_NAME=autenticao # template de autenticação aprovado
100
+ # WHATSAPP_TEMPLATE_LANGUAGE=pt_BR # variação do template
101
+ #
102
+ # DEV: se WHATSAPP_ENDPOINT_URL for loopback (127.0.0.1/localhost — o mock
103
+ # `bun run dev:whatsapp-echo`), o gateway entra em "modo echo": NENHUM WhatsApp real sai.
104
+ # A CLI avisa e mostra o código direto; `nio security status` mostra o backend.
105
+ ```
106
+
107
+ > Alternativa pra time: gere o `~/.nio/config.env` uma vez e distribua o arquivo
108
+ > (é só `KEY=value`) — a CLI valida no primeiro comando.
109
+
110
+ | Variável | Prefixo | Lida por |
111
+ |---|---|---|
112
+ | `NIO_DATABASE_URL` / `NIO_DATABASE_SSL` | `NIO_` | tudo que toca o banco |
113
+ | `JWT_SECRET` / `JWT_EXPIRES_IN` | **sem** prefixo (segredo do time) | `nio-gateway` + `nio-cli` |
114
+ | `WHATSAPP_ENDPOINT_URL` / `WHATSAPP_TOKEN` (+ `WHATSAPP_TEMPLATE_NAME` / `WHATSAPP_TEMPLATE_LANGUAGE`) | **sem** prefixo | `nio-gateway` |
115
+ | `NIO_GATEWAY_HOST` (default `127.0.0.1`) | `NIO_` | `nio-gateway` — `0.0.0.0` p/ Kong em container |
116
+ | `NIO_GATEWAY_URL` (default `http://127.0.0.1:3000`) | `NIO_` | a CLI acha o nio-gateway (Kong na frente = aponta :8000) |
117
+
118
+ O schema de conexão é sempre `postgres://…`; um destino inválido falha explícito,
119
+ nunca cai num default silencioso.
120
+
121
+ ### Backend de IA próprio (uso fora da rede NIO)
122
+
123
+ O motor de IA (`nio ai`/`exec`/`plan`) fala com um backend OpenAI-compatível
124
+ (`/v1`). **O default aponta pra infra interna** (`http://192.168.0.140:8001/v1`,
125
+ modelo `RedHatAI/Qwen3.8-27B-INT4`) — fora dessa rede, suba seu próprio
126
+ vLLM (ou compatível) e aponte a CLI pra ele em `~/.nio/config.env`
127
+ (`nio config path`; `NIO_AI_*` **não** valem no `.env` do projeto):
128
+
129
+ ```bash
130
+ NIO_AI_BASE_URL=https://seu-vllm:8000/v1 # raiz /v1 (o SDK anexa /chat/completions)
131
+ NIO_AI_MODEL=seu-org/seu-modelo # id EXATO que o backend serve em /v1/models
132
+ NIO_AI_CONTEXT=65536 # max_model_len do backend; 0 = usa catálogo
133
+ NIO_AI_OUTPUT=2048 # teto de saída (input + output ≤ contexto!)
134
+ NIO_AI_MAX_INPUT=32000 # trava de input por prompt (0 = desativa)
135
+ ```
136
+
137
+ Confira com `nio config check` — ele sonda `GET <base>/models` e avisa (sem
138
+ reprovar) se o backend está fora do ar ou não serve o modelo configurado.
139
+
140
+ ---
141
+
142
+ ## Primeiros passos
143
+
144
+ Um comando só:
145
+
146
+ ```bash
147
+ nio # (ou `nio start`) — a esteira guiada
148
+ ```
149
+
150
+ A esteira detecta em que ponto você está e conduz — **config → gateway → login →
151
+ sessão → handoff pro OpenCode** —, perguntando antes de cada passo. Ela sobe o
152
+ `nio-gateway` sozinha se faltar. Se você sair no meio, ela imprime a linha exata
153
+ pra retomar (`nio start`); nada morre no silêncio.
154
+
155
+ Por dentro, é isto (cada um roda na mão também):
156
+
157
+ ```bash
158
+ nio config setup # cola NIO_DATABASE_URL + JWT_SECRET (o time te passa), testa, salva
159
+ nio-gateway # gateway de auth (a esteira sobe sozinha se faltar)
160
+ nio register # cria seu usuário na base compartilhada → cai no login
161
+ nio login # autentica (salva o JWT em ~/.nio/session.json)
162
+ nio security enable-2fa # (opcional) 2º fator
163
+ nio init # monta o ambiente da sessão → `nio ai` (opencode serve + chat NIO, num terminal da IDE)
164
+ ```
165
+
166
+ O `nio-gateway` só é necessário pros comandos de auth (`login`/`logout`/
167
+ `verify-2fa`/`security`). Todo o resto — `init`, `sessions`, as tools MCP —
168
+ fala com o Postgres direto usando o JWT local. Rode `nio debug` a qualquer
169
+ momento pra ver o que está ok e o que falta.
170
+
171
+ ---
172
+
173
+ ## Arquitetura
174
+
175
+ Hexagonal. O núcleo não conhece IO; os adapters implementam os contratos.
176
+
177
+ ```
178
+ entrypoints: src/cli.ts (nio) src/gateway/index.ts (nio-gateway)
179
+ src/mcp-server.ts (nio-cli) src/mcp-server-lang.ts (nio-lang)
180
+ app: SessionManager · EnvironmentBuilder · DependencyWatcher · DockerManager
181
+ core/: types.ts (entidades + enums) + ports por domínio, sem IO:
182
+ repositories.ts · environment.ts · docker.ts · messaging.ts · lang.ts
183
+ adapters/: pg/ (Postgres) ide/ (vscode) pkg/ (npm,pip,…) docker/ sms/ skills/ lang/
184
+ profiles/: catálogo dos 6 perfis (fixos no fonte)
185
+ ```
186
+
187
+ - **Runtime:** Node 20.12+ é o alvo. Bun roda o projeto em dev, mas **nada**
188
+ depende de API exclusiva do Bun — só as equivalentes de `node:*`.
189
+ - **Build:** `tsc` puro → `dist/`. Sem bundler.
190
+ - **Banco:** `pg` + um `Pool` único (`src/adapters/pg/client.ts`). Sem Supabase,
191
+ sem PostgREST, sem `Bun.sql`.
192
+ - **Gateway:** `http.createServer` nativo, loopback, atrás do Kong OSS (opcional,
193
+ pra rate-limiting). JWT HS256, `jti` = id da `auth_session`. Trilha de auth em
194
+ stderr estruturado — nunca a senha nem o OTP em texto puro.
195
+ - **Contrato "nunca lança"** nos ports de IO (`ToolchainGateway`, `IdeGateway`,
196
+ `DockerGateway`, `SmsSender`): falha vira um resultado `{ status, error? }`.
197
+
198
+ Detalhes: [`docs/arch/`](docs/arch/) (uma `ARQUITETURA-*.md` por camada) e os
199
+ [ADRs](docs/adr/). Histórico cronológico: [`docs/PROGRESSO.md`](docs/PROGRESSO.md).
200
+
201
+ ### Perfis
202
+
203
+ Fixos no fonte (`src/core/types.ts`) — novos perfis só entram alterando o código:
204
+
205
+ `fullstack` · `analyst` · `scientist` · `dba` · `qa` · `bi`
206
+
207
+ ---
208
+
209
+ ## Autenticação
210
+
211
+ ```bash
212
+ nio register # cria o usuário (user_cli), senha com hash argon2id
213
+ nio login # autentica via nio-gateway e salva o JWT em ~/.nio/session.json
214
+ nio whoami # mostra quem está logado (--json pra saída estável)
215
+ nio logout # revoga a auth_session no banco e limpa a sessão local
216
+ ```
217
+
218
+ ### 2º fator (WhatsApp)
219
+
220
+ Opt-in por conta. Com `auth_2` ativo, o `nio login` pede um código de 6 dígitos
221
+ enviado por WhatsApp (template de autenticação da Meta Graph); se a mensagem não
222
+ chega, vale um dos 10 **códigos de backup** (mostrados uma vez no `enable-2fa`).
223
+
224
+ ```bash
225
+ nio security enable-2fa # cadastra o celular, confirma via WhatsApp, mostra os backups
226
+ nio security status # ativo? número (mascarado)? quantos backups restam?
227
+ nio security disable-2fa
228
+ nio security regenerate-backup-codes
229
+ ```
230
+
231
+ O gateway gera/valida o OTP em processo (sem Twilio, sem broker), guarda só o
232
+ **HMAC** do código (TTL 5 min, 3 tentativas, uso único) e manda a mensagem pela
233
+ **WhatsApp Business API (Meta Graph)**. Sem `WHATSAPP_ENDPOINT_URL`/`WHATSAPP_TOKEN`
234
+ no ambiente, o login com `auth_2` responde `503 "2FA não configurado"` — o login
235
+ de 1 fator segue normal.
236
+ Detalhes: [spec 0004](docs/specs/auth/0004-login-2fa-sms-otp.md) ·
237
+ [ADR 0006](docs/adr/0006-2fa-sms-otp.md) ·
238
+ [`docs/arch/ARQUITETURA-GATEWAY.md`](docs/arch/ARQUITETURA-GATEWAY.md).
239
+
240
+ Pra testar sem WhatsApp real, o repo traz um mock: `bun run dev:whatsapp-echo` sobe
241
+ um endpoint local que imprime o código no terminal (aponte `WHATSAPP_ENDPOINT_URL` pra ele).
242
+
243
+ ---
244
+
245
+ ## Operador de IA (`nio ai`)
246
+
247
+ No fim do `nio init` a CLI sobe o **client de IA** da sessão — e o mesmo `nio ai`
248
+ retoma a qualquer momento. Ele:
249
+
250
+ 1. **Prepara o `opencode.json`** — grava o provider `opencode` **direto no OpenCode Zen**
251
+ (sem `baseURL` de proxy), junto do `model: opencode/big-pickle`, do MCP `nio`, dos MCPs
252
+ do perfil e de um bloco `permission` semeado (allowlist só-leitura → `allow`, resto →
253
+ `ask`). O **Headroom foi desativado** ([ADR 0010](docs/adr/0010-headroom-desativado.md)):
254
+ o client fala direto no LLM, sem compressão — **não precisa de Docker** pro `nio ai`.
255
+ (O `nio docker headroom` continua existindo, dormente, pra quem quiser subir manualmente.)
256
+ 2. **Sobe o `opencode serve` headless e abre a interface NIO** (Ink). O motor é o
257
+ `opencode/big-pickle`; a casca é nossa. Se a sessão tem IDE (VS Code / Cursor), o
258
+ `nio init` grava um `.vscode/tasks.json` (task `NIO`, `runOn: folderOpen`) e o
259
+ `nio ai` sobe num **terminal integrado da IDE** — uma superfície, não duas. Sem
260
+ IDE, roda no terminal atual. Sem TTY → recusa com mensagem; sem `opencode` no
261
+ PATH → cai na TUI do OpenCode.
262
+
263
+ Ver [`docs/arch/ARQUITETURA-CLIENTE-IA.md`](docs/arch/ARQUITETURA-CLIENTE-IA.md),
264
+ [`docs/arch/ARQUITETURA-TUI-UX-SPRINTS.md`](docs/arch/ARQUITETURA-TUI-UX-SPRINTS.md) e
265
+ [`docs/arch/ARQUITETURA-TUI-INTERACOES-MOTOR.md`](docs/arch/ARQUITETURA-TUI-INTERACOES-MOTOR.md).
266
+
267
+ ### Interface do `nio ai` (TUI)
268
+
269
+ Chat no terminal (Ink) sobre o `opencode/big-pickle`, **em uma superfície só** — no
270
+ estilo do Claude Code. O que o motor faz aparece **em linha**, conforme acontece:
271
+ o raciocínio (`✻`), cada ferramenta (`● nome(args)` + `⎿` a saída), o checklist
272
+ (`☑ ◐ ☐`), os arquivos tocados, o diff da rodada (`✎ N arquivo(s) +x −y`) e os
273
+ tokens/custo no rodapé de cada resposta. Sem sidebar, sem janela extra.
274
+
275
+ **Digitar & enviar**
276
+
277
+ | Tecla | Faz |
278
+ |---|---|
279
+ | `Enter` | envia o prompt |
280
+ | `\` + `Enter` · `Ctrl-J` | quebra linha — o prompt é multi-linha e cresce sozinho |
281
+ | `←` `→` `↑` `↓` | move o cursor dentro do texto |
282
+ | `Ctrl-A` / `Ctrl-E` | início / fim da linha |
283
+ | `Ctrl-W` / `Ctrl-U` / `Ctrl-K` | apaga a palavra anterior / até o início / até o fim |
284
+ | colar um bloco | entra literal (várias linhas **não** enviam sozinhas) |
285
+
286
+ **Modos** — o modo troca o comportamento do agente
287
+
288
+ | Tecla | Faz |
289
+ |---|---|
290
+ | `Tab` | alterna entre os agentes primários do `opencode.json` (`build` → `plan` → …) |
291
+ | `build` | o agente **executa** (edita, roda comando) |
292
+ | `plan` | o agente **só propõe** — não toca nada |
293
+
294
+ O modo atual fica no rodapé: `[build]`.
295
+
296
+ **Paleta de comandos**
297
+
298
+ | Tecla | Faz |
299
+ |---|---|
300
+ | `/` | abre a lista inline — comandos do `nio` + capacidades do operador |
301
+ | `↑` `↓` + `Enter` | roda o comando / manda a capacidade pro agente / abre o painel |
302
+ | `Esc` | fecha a lista — o texto que você já digitou **continua lá** |
303
+
304
+ **Quando o agente te interrompe**
305
+
306
+ - **Permissão** (rodar shell, editar arquivo, chamar MCP…) → modal:
307
+ `a`/`Enter` permite uma vez · `s` permite **sempre** (salva a regra no `opencode.json`) · `d`/`Esc` nega.
308
+ Pedidos em paralelo entram numa **fila** (`+N na fila`); um sub-agente travado é
309
+ reconciliado sozinho em ~4s — não trava mais em "processando".
310
+ - **Pergunta aberta** — o agente termina com "?" → o cue `↳ o nio perguntou` aparece acima do input.
311
+ - **Lista de opções** — o agente listou `1./2./3.` → menu `↑`/`↓`+`Enter` pra escolher; ou ignore e escreva livre.
312
+
313
+ **Acompanhar & controlar**
314
+
315
+ | Tecla | Faz |
316
+ |---|---|
317
+ | `Ctrl-R` | expande / colapsa o raciocínio (`✻`) — ver o agente "pensar" ao vivo |
318
+ | `Esc` | durante o processamento: **aborta o turno** |
319
+
320
+ `NIO_DEBUG=1 nio ai` grava cada evento cru do motor em `~/.nio/tui.log` (nunca no
321
+ terminal — corromperia o render).
322
+
323
+ > A interface NIO (Ink) está na **fatia 2a** ([ADR 0008](docs/adr/0008-interface-nio-ink.md)).
324
+ > A paridade completa com o OpenCode (diff viewer, file tree, seletor de modelo…) é a 2b.
325
+ > Multi-cliente (OpenCode | Codex) e o ladder de failover entre modelos seguem
326
+ > parkeados em
327
+ > [`docs/arch/ARQUITETURA-CLIENTES-MULTI-FUTURO.md`](docs/arch/ARQUITETURA-CLIENTES-MULTI-FUTURO.md)
328
+ > ([ADR 0004](docs/adr/0004-operador-ia-unico.md)).
329
+
330
+ ---
331
+
332
+ ## Comandos do CLI
333
+
334
+ Operações do CLI, **sem o binário na frente** (declarado no cabeçalho da tabela).
335
+ Gerada da fonte por `npm run gen:docs`. Ajuda de qualquer comando: `nio <cmd> --help`.
336
+
337
337
  <!-- COMMANDS:START -->
338
338
  <!-- gerado por `bun run gen:docs` — não edite à mão. binário `nio`, 60 comandos. -->
339
339
 
@@ -399,60 +399,60 @@ Gerada da fonte por `npm run gen:docs`. Ajuda de qualquer comando: `nio <cmd> --
399
399
  | `sync` | Instala/atualiza skills, commands e agents nos clientes configurados, a partir do bundle (idempotente); checa atualização do pacote |
400
400
  | `validate-plan` | Lê o plan.md da raiz e roda o Qwen (vLLM local) para julgar se o plano precisa de uma spec antes de implementar. |
401
401
  | `whoami` | Mostra o usuário autenticado |
402
- <!-- COMMANDS:END -->
403
-
404
- ### Diagnóstico da própria CLI
405
-
406
- ```bash
407
- nio debug # bateria de checagens: nio.json, login, Postgres, sessão ativa,
408
- # OpenCode no PATH, cache de skills — ✓ / ⚠ / ✗ com dica em cada
409
- nio docs # documentação completa no terminal
410
- nio docs --html # a mesma coisa como página (arte); --open abre no navegador
411
- ```
412
-
413
- ### Autocomplete (tab)
414
-
415
- O `nio init` **oferece** ativar; o `nio sync` **valida** e prompta se faltar. À mão:
416
-
417
- ```bash
418
- eval "$(nio completion zsh)" # ~/.zshrc
419
- eval "$(nio completion bash)" # ~/.bashrc
420
- nio completion fish | source # ~/.config/fish/config.fish
421
- ```
422
-
423
- ---
424
-
425
- ## Docker (`nio docker`)
426
-
427
- Camada de gerência de container — metade wrapper determinístico sobre `docker`,
428
- metade dirigida pelo operador de IA em linguagem natural (via o **Docker MCP
429
- Gateway**). Roda em qualquer Docker Engine (não exige Docker Desktop). Ver
430
- [`docs/arch/ARQUITETURA-DOCKER.md`](docs/arch/ARQUITETURA-DOCKER.md) ·
431
- [ADR 0005](docs/adr/0005-camada-docker.md).
432
-
433
- ```bash
434
- nio docker toolkit up # sobe o MCP Gateway (127.0.0.1:8811/mcp) + Portainer (9443)
435
- # e registra o gateway no opencode.json
436
- nio docker compose up -f app/docker-compose.yml # wrapper sobre `docker compose` do projeto
437
- nio docker create --image redis:7 --port 6379:6379
438
- nio docker debug <container> # coleta ps/logs/inspect → operador analisa e propõe o fix
439
- nio docker orquest "sobe api + worker + redis" # operador gera o compose e sobe (--dry-run mostra)
440
- nio docker cluster up "api + worker + redis + postgres" # Docker Swarm (stack `nio-cluster`)
441
- nio docker cluster status | scale api=3
442
- nio docker portainer # abre a UI
443
- ```
444
-
445
- `debug`/`orquest`/`cluster` exigem `nio login` + sessão ativa + `opencode` no
446
- PATH. O estado do cluster fica em `sessions.config` (Postgres), validado contra
447
- `docker stack services`.
448
-
449
- ---
450
-
451
- ## Tools MCP
452
-
453
- O servidor `nio-cli` expõe as tools de ambiente v2 (todas passam pelo
454
- `SessionManager` e exigem `nio login`):
455
-
402
+ <!-- COMMANDS:END -->
403
+
404
+ ### Diagnóstico da própria CLI
405
+
406
+ ```bash
407
+ nio debug # bateria de checagens: nio.json, login, Postgres, sessão ativa,
408
+ # OpenCode no PATH, cache de skills — ✓ / ⚠ / ✗ com dica em cada
409
+ nio docs # documentação completa no terminal
410
+ nio docs --html # a mesma coisa como página (arte); --open abre no navegador
411
+ ```
412
+
413
+ ### Autocomplete (tab)
414
+
415
+ O `nio init` **oferece** ativar; o `nio sync` **valida** e prompta se faltar. À mão:
416
+
417
+ ```bash
418
+ eval "$(nio completion zsh)" # ~/.zshrc
419
+ eval "$(nio completion bash)" # ~/.bashrc
420
+ nio completion fish | source # ~/.config/fish/config.fish
421
+ ```
422
+
423
+ ---
424
+
425
+ ## Docker (`nio docker`)
426
+
427
+ Camada de gerência de container — metade wrapper determinístico sobre `docker`,
428
+ metade dirigida pelo operador de IA em linguagem natural (via o **Docker MCP
429
+ Gateway**). Roda em qualquer Docker Engine (não exige Docker Desktop). Ver
430
+ [`docs/arch/ARQUITETURA-DOCKER.md`](docs/arch/ARQUITETURA-DOCKER.md) ·
431
+ [ADR 0005](docs/adr/0005-camada-docker.md).
432
+
433
+ ```bash
434
+ nio docker toolkit up # sobe o MCP Gateway (127.0.0.1:8811/mcp) + Portainer (9443)
435
+ # e registra o gateway no opencode.json
436
+ nio docker compose up -f app/docker-compose.yml # wrapper sobre `docker compose` do projeto
437
+ nio docker create --image redis:7 --port 6379:6379
438
+ nio docker debug <container> # coleta ps/logs/inspect → operador analisa e propõe o fix
439
+ nio docker orquest "sobe api + worker + redis" # operador gera o compose e sobe (--dry-run mostra)
440
+ nio docker cluster up "api + worker + redis + postgres" # Docker Swarm (stack `nio-cluster`)
441
+ nio docker cluster status | scale api=3
442
+ nio docker portainer # abre a UI
443
+ ```
444
+
445
+ `debug`/`orquest`/`cluster` exigem `nio login` + sessão ativa + `opencode` no
446
+ PATH. O estado do cluster fica em `sessions.config` (Postgres), validado contra
447
+ `docker stack services`.
448
+
449
+ ---
450
+
451
+ ## Tools MCP
452
+
453
+ O servidor `nio-cli` expõe as tools de ambiente v2 (todas passam pelo
454
+ `SessionManager` e exigem `nio login`):
455
+
456
456
  <!-- TOOLS:START -->
457
457
  <!-- gerado por `bun run gen:docs` — não edite à mão. 10 tools. -->
458
458
 
@@ -470,152 +470,152 @@ O servidor `nio-cli` expõe as tools de ambiente v2 (todas passam pelo
470
470
  | `session_create` | Cria uma sessão de ambiente pro usuário autenticado e materializa o perfil escolhido: garante os toolchains, resolve os MCPs e persiste o `config` em `sessions.config`. |
471
471
  | `session_list` | Lista as sessões de ambiente do usuário autenticado (mais recentes primeiro), com id, nome, perfil, status e o `config` materializado. |
472
472
  | `validate_plan` | Lê o `plan.md` da raiz do projeto e roda o Qwen (vLLM local, via API) para julgar se o plano é complexo o bastante para virar uma spec SDD antes de implementar. |
473
- <!-- TOOLS:END -->
474
-
475
- ### Recipes de ambiente (repo NIO-SKILLS)
476
-
477
- Além dos 6 perfis fixos, o repo `NIO-SKILLS-` pode carregar **recipes** em
478
- `recipes/<slug>.md` — presets nomeados (`profile` + linguagens + frameworks +
479
- MCPs + envVars/aliases) que **estendem** um perfil, editáveis sem release da CLI.
480
- O `nio init` oferece a recipe depois do perfil; `nio_session_create` aceita
481
- `{ recipe: "<slug>" }`. Merge determinístico (recipe vence em envVars/aliases;
482
- união em linguagens/frameworks/MCPs).
483
-
484
- ---
485
-
486
- ## Skills, commands e dependências
487
-
488
- Além das tools, o nio entrega **skills, commands e agents** pros clientes. O conteúdo
489
- vive num **repo aberto** — [`hugoreiis12-png/NIO-SKILLS-`](https://github.com/hugoreiis12-png/NIO-SKILLS-) —
490
- e **não** é um pacote npm. O CLI baixa o repo (zipball do GitHub, sem precisar de `git`)
491
- pra um cache local em **`~/.nio/skills`** e lê de lá. `nio sync` **atualiza o cache**
492
- (pull da branch) toda vez, então as skills evoluem sem republicar o CLI; e **auto-detecta**
493
- se o OpenCode tem o conector `nio` configurado, provisionando pra ele conforme a seleção
494
- de perfil/área do `nio.json`.
495
-
496
- Overrides por ambiente:
497
-
498
- | Variável | Efeito |
499
- | --------------------- | ------------------------------------------------------------------ |
500
- | `NIO_SKILLS_DIR` | Aponta pra um checkout local do repo (dev) — vence tudo |
501
- | `NIO_SKILLS_REPO` | Outro `owner/repo` (default `hugoreiis12-png/NIO-SKILLS-`) |
502
- | `NIO_SKILLS_REF` | Outra branch/tag (default `main`) |
503
-
504
- Cada cliente recebe no formato que entende:
505
-
506
- | Cliente | Onde | Formato |
507
- | --------------- | ----------------------------- | ----------------------------------------------------------------------- |
508
- | OpenCode | `~/.config/opencode/` | MCP `nio` registrado no `opencode.json`; skills/commands no layout cru do pacote (`skills/<id>/SKILL.md`) |
509
- | Cowork/Desktop | — | via **MCP prompts** + resources, servidos ao vivo |
510
-
511
- > **Como aparecem no Cowork/Claude Desktop.** Lá as skills chegam como **prompts MCP**,
512
- > que o app expõe como **slash-commands** no menu de conectores/"+" (ex.: digite `/` e
513
- > procure os itens do nio) — são **invocados manualmente**, não carregados sozinhos
514
- > como Agent Skills que o modelo detecta e usa por conta própria. Se não aparecerem:
515
- > feche o app de vez (Cmd+Q) e reabra, e confirme que o conector nio está conectado.
516
-
517
- ### Visibilidade por cliente
518
-
519
- Um doc pode ser restrito a clientes específicos via frontmatter:
520
-
521
- ```yaml
522
- clients: cowork, opencode # vazio/ausente = todos os clientes
523
- ```
524
-
525
- Valores: `cowork`, `opencode`. O MCP filtra por esse campo, então um skill
526
- marcado `cowork` só aparece como prompt no Cowork/Desktop, e um `opencode` só
527
- nos docs provisionados ao operador OpenCode.
528
-
529
- ### Dependências externas
530
-
531
- Commands/skills podem depender de libs externas, declaradas como arquivos em
532
- `dependencies/` no repo de skills (a presença do arquivo é a declaração). No fim do
533
- `init`/`sync`, a CLI lista cada uma e:
534
-
535
- - **instalador estruturado** (`npm:`, `skills:` = `npx skills add`, `git:`) → oferece
536
- rodar com `[y/N]` (comando montado a partir do campo validado, **sem shell**);
537
- - **`manual:`** (sem instalador automatizável — checagem/UI no cliente) → imprime os
538
- passos, com os comandos destacados.
539
-
540
- A string `install:` (se houver) é **só exibição** — nunca é executada. A CLI **detecta
541
- o que já está instalado** e mostra um selo `✓ instalada` (via `npm ls -g`, dir de
542
- destino, ou o `detect:` do frontmatter).
543
-
544
- ---
545
-
546
- ## Claude Desktop / Cowork
547
-
548
- O Cowork/Claude Desktop é um cliente de **chat** via MCP — as skills chegam como
549
- **prompts MCP** servidos ao vivo, e o conector vive no `claude_desktop_config.json`
550
- com caminhos absolutos (`node` + `dist/mcp-server.js`) e `NIO_CLIENT=cowork`. Ele
551
- **não** é mais um alvo do `nio init` (o checkbox só oferece OpenCode): o setup
552
- inicial do conector é manual. O `nio sync` **reafirma** esse config quando o conector
553
- já existe — com o app instalado e você logado (`nio login`), ele reescreve o entry
554
- com paths atuais (merge não-destrutivo + backup). Reinicie o Claude Desktop pra
555
- carregar prompts novos depois do sync.
556
-
557
- ---
558
-
559
- ## Atualizando
560
-
561
- ```bash
562
- npm i -g @nio-cli/cli@latest
563
- ```
564
-
565
- O `nio sync` **checa a versão publicada** no início e **oferece atualizar** ali mesmo
566
- (com sua confirmação). `nio sync --yes` aceita sem prompt. A CLI também avisa em
567
- background em qualquer comando (`update-notifier`).
568
-
569
- ---
570
-
571
- ## Troubleshooting
572
-
573
- | Sintoma | Causa provável / o que fazer |
574
- |---|---|
575
- | `nio: command not found` | `npm i -g @nio-cli/cli` e confira `npm bin -g` no PATH |
576
- | `Configuração necessária` / `NIO_DATABASE_URL não definida` | rode `nio config setup` (ou deixe o `nio init` abrir o wizard) |
577
- | `Não consegui falar com o nio-gateway` | o `nio-gateway` não está no ar — rode `nio-gateway &` |
578
- | `Não autenticado` | `nio register` (1ª vez) e depois `nio login` |
579
- | Erro de conexão com o banco | `ECONNREFUSED` = Postgres fora do ar / host errado; `password authentication failed` = credencial; erro de SSL = `NIO_DATABASE_SSL=true` |
580
- | `2FA não configurado no servidor` (503) | faltam as `WHATSAPP_*` no ambiente do `nio-gateway` |
581
- | `nio ai` diz `precisa de um terminal interativo` | você está num pipe/CI — rode num terminal de verdade |
582
- | `nio ai` travado em "processando" | `Esc` aborta o turno; o motor recupera permissão perdida sozinho em ~4s. Persistiu? `NIO_DEBUG=1 nio ai` e veja `~/.nio/tui.log` |
583
- | `nio ai` cai na TUI do OpenCode | falta o binário `opencode` no PATH — `npm i -g opencode-ai` |
584
- | Skills não aparecem no Cowork | chegam como **prompts MCP** (slash-commands), não skills autônomas. Cmd+Q e reabra; confirme o conector |
585
- | `Conteúdo de skills não encontrado` | cache `~/.nio/skills` vazio — rode `nio sync` com rede, ou `NIO_SKILLS_DIR` pra um checkout local |
586
-
587
- Sempre: `nio debug` mostra o estado de tudo com uma dica por item. E
588
- `NIO_DEBUG=1 nio <cmd>` liga log verboso (`[nio:debug]` em stderr): `.env`
589
- carregados, config resolvida, requests pro gateway, e stack trace completo nos erros.
590
-
591
- O logo Matrix anima (chuva caindo) toda vez que aparece em terminal interativo.
592
- `NIO_NO_ANIM=1` deixa ele sempre estático; fora de TTY (pipe/CI) já é estático.
593
-
594
- ---
595
-
596
- ## Convenções
597
-
598
- - **Idioma:** UI/CLI em pt-BR. Código (variáveis, funções, tipos) em inglês.
599
- - **Backups:** toda escrita em config existente gera `.bak.<timestamp>` ao lado.
600
- - **stdout reservado pro JSON-RPC** no MCP server — logs vão pra stderr.
601
- - **Regra do hexágono:** `core/ports.ts` / `core/repositories.ts` não importam
602
- driver de banco; os adapters (`adapters/*`) implementam os contratos.
603
- - **Migrations:** fonte da verdade em `db/schema.sql`; deltas incrementais em
604
- `db/migrations/NNNN_*.sql`, aplicados à mão (`psql -f`).
605
-
606
- ---
607
-
608
- ## Versão
609
-
610
- **0.5.0** — a interface do `nio ai` (TUI) fechada: editor multi-linha, fluxo em
611
- linha estilo Claude Code (raciocínio, ferramentas, checklist, diff, tokens),
612
- `Tab` troca de modo, paleta `/` executável, fila de permissões (com recuperação
613
- de pedido perdido de sub-agente), perguntas e menus de opção. Mais o fix da cauda
614
- de 30s no shutdown que tocava o Postgres.
615
-
616
- Base (0.2.0–0.4.0): auth (senha + 2º fator SMS OTP), backend de sessões no
617
- Postgres, wizard de ambiente, tools MCP, camada Docker, gateway com Kong e a
618
- auditoria de segurança (argon2id + pepper, HIBP k-anonymity, roles de menor
619
- privilégio). Nasceu de um cliente NOS/Supabase (v1), já removido.
620
-
621
- Histórico cronológico: [`docs/PROGRESSO.md`](docs/PROGRESSO.md).
473
+ <!-- TOOLS:END -->
474
+
475
+ ### Recipes de ambiente (repo NIO-SKILLS)
476
+
477
+ Além dos 6 perfis fixos, o repo `NIO-SKILLS-` pode carregar **recipes** em
478
+ `recipes/<slug>.md` — presets nomeados (`profile` + linguagens + frameworks +
479
+ MCPs + envVars/aliases) que **estendem** um perfil, editáveis sem release da CLI.
480
+ O `nio init` oferece a recipe depois do perfil; `nio_session_create` aceita
481
+ `{ recipe: "<slug>" }`. Merge determinístico (recipe vence em envVars/aliases;
482
+ união em linguagens/frameworks/MCPs).
483
+
484
+ ---
485
+
486
+ ## Skills, commands e dependências
487
+
488
+ Além das tools, o nio entrega **skills, commands e agents** pros clientes. O conteúdo
489
+ vive num **repo aberto** — [`hugoreiis12-png/NIO-SKILLS-`](https://github.com/hugoreiis12-png/NIO-SKILLS-) —
490
+ e **não** é um pacote npm. O CLI baixa o repo (zipball do GitHub, sem precisar de `git`)
491
+ pra um cache local em **`~/.nio/skills`** e lê de lá. `nio sync` **atualiza o cache**
492
+ (pull da branch) toda vez, então as skills evoluem sem republicar o CLI; e **auto-detecta**
493
+ se o OpenCode tem o conector `nio` configurado, provisionando pra ele conforme a seleção
494
+ de perfil/área do `nio.json`.
495
+
496
+ Overrides por ambiente:
497
+
498
+ | Variável | Efeito |
499
+ | --------------------- | ------------------------------------------------------------------ |
500
+ | `NIO_SKILLS_DIR` | Aponta pra um checkout local do repo (dev) — vence tudo |
501
+ | `NIO_SKILLS_REPO` | Outro `owner/repo` (default `hugoreiis12-png/NIO-SKILLS-`) |
502
+ | `NIO_SKILLS_REF` | Outra branch/tag (default `main`) |
503
+
504
+ Cada cliente recebe no formato que entende:
505
+
506
+ | Cliente | Onde | Formato |
507
+ | --------------- | ----------------------------- | ----------------------------------------------------------------------- |
508
+ | OpenCode | `~/.config/opencode/` | MCP `nio` registrado no `opencode.json`; skills/commands no layout cru do pacote (`skills/<id>/SKILL.md`) |
509
+ | Cowork/Desktop | — | via **MCP prompts** + resources, servidos ao vivo |
510
+
511
+ > **Como aparecem no Cowork/Claude Desktop.** Lá as skills chegam como **prompts MCP**,
512
+ > que o app expõe como **slash-commands** no menu de conectores/"+" (ex.: digite `/` e
513
+ > procure os itens do nio) — são **invocados manualmente**, não carregados sozinhos
514
+ > como Agent Skills que o modelo detecta e usa por conta própria. Se não aparecerem:
515
+ > feche o app de vez (Cmd+Q) e reabra, e confirme que o conector nio está conectado.
516
+
517
+ ### Visibilidade por cliente
518
+
519
+ Um doc pode ser restrito a clientes específicos via frontmatter:
520
+
521
+ ```yaml
522
+ clients: cowork, opencode # vazio/ausente = todos os clientes
523
+ ```
524
+
525
+ Valores: `cowork`, `opencode`. O MCP filtra por esse campo, então um skill
526
+ marcado `cowork` só aparece como prompt no Cowork/Desktop, e um `opencode` só
527
+ nos docs provisionados ao operador OpenCode.
528
+
529
+ ### Dependências externas
530
+
531
+ Commands/skills podem depender de libs externas, declaradas como arquivos em
532
+ `dependencies/` no repo de skills (a presença do arquivo é a declaração). No fim do
533
+ `init`/`sync`, a CLI lista cada uma e:
534
+
535
+ - **instalador estruturado** (`npm:`, `skills:` = `npx skills add`, `git:`) → oferece
536
+ rodar com `[y/N]` (comando montado a partir do campo validado, **sem shell**);
537
+ - **`manual:`** (sem instalador automatizável — checagem/UI no cliente) → imprime os
538
+ passos, com os comandos destacados.
539
+
540
+ A string `install:` (se houver) é **só exibição** — nunca é executada. A CLI **detecta
541
+ o que já está instalado** e mostra um selo `✓ instalada` (via `npm ls -g`, dir de
542
+ destino, ou o `detect:` do frontmatter).
543
+
544
+ ---
545
+
546
+ ## Claude Desktop / Cowork
547
+
548
+ O Cowork/Claude Desktop é um cliente de **chat** via MCP — as skills chegam como
549
+ **prompts MCP** servidos ao vivo, e o conector vive no `claude_desktop_config.json`
550
+ com caminhos absolutos (`node` + `dist/mcp-server.js`) e `NIO_CLIENT=cowork`. Ele
551
+ **não** é mais um alvo do `nio init` (o checkbox só oferece OpenCode): o setup
552
+ inicial do conector é manual. O `nio sync` **reafirma** esse config quando o conector
553
+ já existe — com o app instalado e você logado (`nio login`), ele reescreve o entry
554
+ com paths atuais (merge não-destrutivo + backup). Reinicie o Claude Desktop pra
555
+ carregar prompts novos depois do sync.
556
+
557
+ ---
558
+
559
+ ## Atualizando
560
+
561
+ ```bash
562
+ npm i -g @nio-cli/cli@latest
563
+ ```
564
+
565
+ O `nio sync` **checa a versão publicada** no início e **oferece atualizar** ali mesmo
566
+ (com sua confirmação). `nio sync --yes` aceita sem prompt. A CLI também avisa em
567
+ background em qualquer comando (`update-notifier`).
568
+
569
+ ---
570
+
571
+ ## Troubleshooting
572
+
573
+ | Sintoma | Causa provável / o que fazer |
574
+ |---|---|
575
+ | `nio: command not found` | `npm i -g @nio-cli/cli` e confira `npm bin -g` no PATH |
576
+ | `Configuração necessária` / `NIO_DATABASE_URL não definida` | rode `nio config setup` (ou deixe o `nio init` abrir o wizard) |
577
+ | `Não consegui falar com o nio-gateway` | o `nio-gateway` não está no ar — rode `nio-gateway &` |
578
+ | `Não autenticado` | `nio register` (1ª vez) e depois `nio login` |
579
+ | Erro de conexão com o banco | `ECONNREFUSED` = Postgres fora do ar / host errado; `password authentication failed` = credencial; erro de SSL = `NIO_DATABASE_SSL=true` |
580
+ | `2FA não configurado no servidor` (503) | faltam as `WHATSAPP_*` no ambiente do `nio-gateway` |
581
+ | `nio ai` diz `precisa de um terminal interativo` | você está num pipe/CI — rode num terminal de verdade |
582
+ | `nio ai` travado em "processando" | `Esc` aborta o turno; o motor recupera permissão perdida sozinho em ~4s. Persistiu? `NIO_DEBUG=1 nio ai` e veja `~/.nio/tui.log` |
583
+ | `nio ai` cai na TUI do OpenCode | falta o binário `opencode` no PATH — `npm i -g opencode-ai` |
584
+ | Skills não aparecem no Cowork | chegam como **prompts MCP** (slash-commands), não skills autônomas. Cmd+Q e reabra; confirme o conector |
585
+ | `Conteúdo de skills não encontrado` | cache `~/.nio/skills` vazio — rode `nio sync` com rede, ou `NIO_SKILLS_DIR` pra um checkout local |
586
+
587
+ Sempre: `nio debug` mostra o estado de tudo com uma dica por item. E
588
+ `NIO_DEBUG=1 nio <cmd>` liga log verboso (`[nio:debug]` em stderr): `.env`
589
+ carregados, config resolvida, requests pro gateway, e stack trace completo nos erros.
590
+
591
+ O logo Matrix anima (chuva caindo) toda vez que aparece em terminal interativo.
592
+ `NIO_NO_ANIM=1` deixa ele sempre estático; fora de TTY (pipe/CI) já é estático.
593
+
594
+ ---
595
+
596
+ ## Convenções
597
+
598
+ - **Idioma:** UI/CLI em pt-BR. Código (variáveis, funções, tipos) em inglês.
599
+ - **Backups:** toda escrita em config existente gera `.bak.<timestamp>` ao lado.
600
+ - **stdout reservado pro JSON-RPC** no MCP server — logs vão pra stderr.
601
+ - **Regra do hexágono:** `core/ports.ts` / `core/repositories.ts` não importam
602
+ driver de banco; os adapters (`adapters/*`) implementam os contratos.
603
+ - **Migrations:** fonte da verdade em `db/schema.sql`; deltas incrementais em
604
+ `db/migrations/NNNN_*.sql`, aplicados à mão (`psql -f`).
605
+
606
+ ---
607
+
608
+ ## Versão
609
+
610
+ **0.5.0** — a interface do `nio ai` (TUI) fechada: editor multi-linha, fluxo em
611
+ linha estilo Claude Code (raciocínio, ferramentas, checklist, diff, tokens),
612
+ `Tab` troca de modo, paleta `/` executável, fila de permissões (com recuperação
613
+ de pedido perdido de sub-agente), perguntas e menus de opção. Mais o fix da cauda
614
+ de 30s no shutdown que tocava o Postgres.
615
+
616
+ Base (0.2.0–0.4.0): auth (senha + 2º fator SMS OTP), backend de sessões no
617
+ Postgres, wizard de ambiente, tools MCP, camada Docker, gateway com Kong e a
618
+ auditoria de segurança (argon2id + pepper, HIBP k-anonymity, roles de menor
619
+ privilégio). Nasceu de um cliente NOS/Supabase (v1), já removido.
620
+
621
+ Histórico cronológico: [`docs/PROGRESSO.md`](docs/PROGRESSO.md).