Metadata-Version: 2.5
Name: shade-cli
Version: 0.1.2
Summary: O comando `shade`: cria, ensaia, testa e empacota robôs da ShadeOne escritos com o shade-sdk.
Author: ShadeOne
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: pathspec>=1.1
Description-Content-Type: text/markdown

# shade-cli

O comando `shade`: cria, ensaia, testa e empacota robôs da ShadeOne escritos com o
`shade-sdk`. Roda na máquina do dev, sem conta; nunca importa o runtime no
próprio processo: o projeto roda em subprocesso, no venv dele (`uv run` na pasta), com o
`shade-sdk` que ele fixa. Spec: `docs/specs/sdk-python-cli-e-mcp.md` (§6 e §8); ADR 019 (D3,
D4, D11 e D15).

```bash
uv tool install shade-cli
shade init cadastro-erp          # starter de produção (--minimo para o enxuto)
cd cadastro-erp
uv run playwright install chromium
shade test                       # lint de contrato + pytest do projeto
shade run                        # ensaio: para antes de cada efetivar()
shade build                      # artefato determinístico em .shade/build/
```

## Comandos

| Comando | Faz |
|---|---|
| `shade init <pasta> [--minimo] [--modelo lista\|tarefa] [--editor vscode] [--id ID] [--nome NOME] [--sem-sync]` | o starter (produção por padrão) e o `uv sync`; nunca pergunta |
| `shade run [pasta] [--real [--sim]] [--entrada ARQ] [--item CHAVE] [--debug] [--trace] [--como-plataforma] [--headless]` | ensaio por padrão; `--real` pede TTY ou `--sim` |
| `shade test [pasta]` | lint (L1 a L8) e o pytest do projeto |
| `shade build [pasta]` | `projeto.tar.gz` (formato da HU-22.1) e `manifesto.json` em `.shade/build/` |
| `shade doctor [pasta]` | Python, uv, Chromium do Playwright, Docker e o `shade-sdk` do projeto |
| `shade docs [tópico] [--pasta P]` | a referência da versão do `shade-sdk` do projeto |
| `shade inspecionar <url> [--pagina Nome] [--pasta P]` | abre a página no Chromium (contexto efêmero, rede só em `[hosts] permitidos`), grava o que você clica e preenche, e propõe `Pagina` com `Alvo`s já conferidos pelo diagnóstico do SDK; Enter no terminal encerra (`--headless` varre a página sem janela) |

Tudo o que a CLI escreve num projeto fica em `.shade/` (que se ignora sozinho no git): o
`git status` do projeto continua limpo depois de qualquer comando, menos o `init`.

## `--json` e códigos de saída

Com `--json`, um documento no stdout; progresso e logs no stderr, redigidos:

```json
{"versao": 1, "comando": "build", "ok": false, "dados": {},
 "erro": {"codigo": "lint_reprovado", "mensagem": "L3 robo.py:1 import fora do lock: yaml",
          "recuperacao": "corrija o que o lint aponta (shade test mostra a lista inteira)"}}
```

| Código | Significado |
|---|---|
| 0 | ok |
| 1 | gate, lint ou teste reprovou (e o defeito da própria CLI, com `erro.codigo = "erro_interno"`) |
| 2 | uso inválido ou `shade.toml` inválido |
| 5 | incompatibilidade de versão (o `shade-sdk` do projeto não é o da imagem) |
| 130 | interrompido (Ctrl-C, SIGTERM ou SIGHUP: o robô em andamento morre junto) |

Os códigos 3, 4, 6 e 7 são dos comandos com conta (`deploy`, `releases`, `runs`).

## Lint de contrato

| Regra | Efeito | O quê |
|---|---|---|
| L3 | reprova | import de pacote fora do lock da imagem e dos plugins aprovados |
| L7 | reprova (avisa no `run`) | credencial lida sem declaração, ou o valor dela chegando a `goto`, ao HTTP do Playwright, a `shade_sdk.http` ou a arquivo |
| L8 | reprova | entrada ausente ou inválida (`main.py`, `[robo] classe`, arquivo que não compila) |
| L1 | avisa | `subprocess`, `os.system`, `os.exec*`, `os.fork`, `ctypes`, `multiprocessing` |
| L2 | avisa | `socket`, `http.client`, `urllib.request`, `requests`, `httpx`, `aiohttp` |
| L4 | avisa | `eval`, `exec`, `compile`, import dinâmico |
| L5 | avisa | caminho literal fora do workdir |
| L6 | avisa | clique ou envio em alvo com cara de submissão fora de `efetivar()` |

O lint não é controle de segurança (ADR 019, D3): a fronteira é o isolamento do executor.

## Desenvolvimento

```bash
cd cli && uv sync
uv run pytest -q -m "not starter"   # rápido
uv run pytest -q -m starter         # os starters de verdade: uv sync, Chromium, ~45 s
```

`src/shade_cli/imagem.py` é a cópia do `requirements.lock` da imagem do run:
`backend/tests/test_hu294_artefato_da_cli.py` a confere, e confere que o artefato do
`shade build` passa no `ler()` do backend.
