@nio-cli/cli 0.11.0 → 0.11.2
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.
- package/.env.example +118 -118
- package/Dockerfile.gateway +20 -20
- package/README.md +539 -539
- package/dist/adapters/pg/auth-event-repository.js +4 -4
- package/dist/adapters/pg/auth-session-repository.js +2 -2
- package/dist/adapters/pg/dependency-event-repository.js +4 -4
- package/dist/adapters/pg/login-challenge-repository.js +2 -2
- package/dist/adapters/pg/login-ip-repository.js +3 -3
- package/dist/adapters/pg/session-repository.js +3 -3
- package/dist/app/ai-client.js +4 -1
- package/dist/app/ai-client.js.map +1 -1
- package/dist/cli/commands/completion.js +28 -28
- package/dist/cli/commands/docs/html.js +78 -78
- package/dist/cli/copy/auth.json +13 -13
- package/dist/cli/copy/flows.json +5 -5
- package/dist/cli/copy/init.json +15 -15
- package/dist/cli/copy/sync.json +3 -3
- package/dist/cli.js +0 -0
- package/dist/gateway/index.js +0 -0
- package/dist/lib/clients/client-configs.js +13 -5
- package/dist/lib/clients/client-configs.js.map +1 -1
- package/dist/lib/clients/nio-oc-config.js +14 -2
- package/dist/lib/clients/nio-oc-config.js.map +1 -1
- package/dist/lib/exec/map-reduce.js +56 -0
- package/dist/lib/exec/map-reduce.js.map +1 -0
- package/dist/lib/provision/provision.js.map +1 -1
- package/dist/lib/shutdown.js +5 -1
- package/dist/lib/shutdown.js.map +1 -1
- package/dist/mcp-server-lang.js +0 -0
- package/dist/mcp-server.js +0 -0
- package/dist/tui/app.js +29 -9
- package/dist/tui/app.js.map +1 -1
- package/dist/tui/attachments.js +117 -0
- package/dist/tui/attachments.js.map +1 -0
- package/dist/tui/components.js +21 -5
- package/dist/tui/components.js.map +1 -1
- package/dist/tui/debug.js +1 -1
- package/dist/tui/debug.js.map +1 -1
- package/dist/tui/opencode.js +7 -7
- package/dist/tui/opencode.js.map +1 -1
- package/dist/tui/palette.js +3 -3
- package/dist/tui/palette.js.map +1 -1
- package/dist/tui/state.js +56 -3
- package/dist/tui/state.js.map +1 -1
- package/docker/docker-compose.yml +114 -114
- package/docker/kong.yml +59 -59
- package/package.json +99 -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).
|