Skip to main content

shade-cli

O comando shade: cria, ensaia, testa, empacota e envia robôs da ShadeOne escritos com o shade-sdk. O ciclo local roda sem conta; auth, deploy, releases e runs falam com a plataforma pela chave de API, e shade mcp expõe o ciclo a um agente (Claude Code). 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.

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 (o mesmo pacote que a plataforma monta de uma gravação) e manifesto.json em .shade/build/; recusa o plugin de [plugins] que a imagem não tem, ou cujos hosts e credenciais o projeto não declara, e o estado de sessão do robô (a sessao_salva, ou um storage_state do Playwright) que o .gitignore não ignora
shade doctor [pasta] Python, uv, Chromium do Playwright, Docker, o plugin do Claude Code e o shade-sdk do projeto
shade docs [tópico] [--pasta P] a referência da versão do shade-sdk do projeto
shade claude-code instalar instala (ou atualiza) o plugin do Claude Code desta versão da CLI: as skills /shade-* e o shade mcp
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 Alvos já conferidos pelo diagnóstico do SDK; Enter no terminal encerra (--headless varre a página sem janela)

Com a chave de API

Comando Faz
shade auth login [--url URL] lê a chave sem eco (ou de uma linha do stdin, sem terminal), confere com a plataforma e guarda URL, chave e workspace no keyring do sistema
shade auth status de onde vem a conta, o workspace e os escopos da chave, conferidos agora
shade auth logout apaga a conta do keyring
shade deploy [pasta] [--criar] [--nao-esperar] [--prazo S] confere /sdk/compat, monta o artefato em memória, envia e acompanha recebida → conferida → em ensaio → aguardando aprovação; o robo.id novo pede --criar sem terminal
shade releases list [pasta] [--robo ID] [--limite N] as versões do robô
shade releases show <id> [--esperar] [--prazo S] uma versão; com --esperar, acompanha como o deploy
shade releases ensaiar <id> [--esperar] [--prazo S] repete o ensaio que caiu por infraestrutura ou esperava credencial

SHADE_API_KEY e SHADE_URL vencem o keyring (o caminho do CI). A chave nunca é argumento, nunca vai para arquivo e sai redigida de todo texto. http:// só para localhost.

O deploy é idempotente: o mesmo código dá o mesmo sha256, e o servidor devolve a release que já existe. Se a CLI cair no meio, repetir shade deploy (ou shade releases show <id> --esperar) retoma a mesma versão. O prazo da espera (10 min) sai 6 com esse comando.

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.

Servidor MCP (shade mcp)

shade mcp [--pasta P] sobe um servidor MCP local, por stdio, sem porta, para o Claude Code (ou outro cliente MCP) escrever, testar e enviar o robô com ferramentas observáveis. Vem num extra:

uv tool install 'shade-cli[mcp]'
shade claude-code instalar        # no Claude Code: o plugin registra o shade mcp
# em outro cliente MCP, ou sem o plugin, na pasta do projeto:
claude mcp add shade -- shade mcp

Use um dos dois: o plugin e o claude mcp add sobem o mesmo servidor duas vezes. Quem já tinha o claude mcp add e instala o plugin tira o antigo com claude mcp remove shade.

O projeto é o shade.toml mais próximo do diretório em que o cliente sobe o servidor (ou --pasta), fixo na sessão. A chave vem do keyring (shade auth login) ou de SHADE_API_KEY e SHADE_URL. As ferramentas listadas são as que a chave e o projeto permitem: sem projeto, só as da plataforma; sem chave, só as locais; chave só de leitura, nada que envie.

Risco Ferramentas Precisa
local, sem rede ler_manifesto, montar_artefato, rodar_lint o projeto
leitura da plataforma listar_robos, ver_release, listar_runs, ver_run, listar_itens, ver_falha, buscar_eventos, ler_gravacao processes:read ou runs:read
navegação local snapshot_da_pagina (árvore de acessibilidade e Alvos candidatos), conferir_seletor (em que elemento um Alvo cai) o projeto
executa código local rodar_testes (shade test), rodar_ensaio (shade run em ensaio, headless) o projeto
envia sem pessoa enviar_release (shade deploy, até aguardando_aprovacao) o projeto e releases:write

Recursos: shade://sdk/referencia, shade://projeto/manifesto, shade://projeto/ultimo-ensaio, shade://protocolo/runtime e shade://ferramentas/schema; cada um tem o equivalente em ferramenta ou em shade docs.

O que o servidor garante, e o que não garante:

  • Nenhuma ferramenta roda o robô em modo real, aprova nem ativa uma versão. O ensaio para antes de cada efetivar(); o --real fica no terminal, com você.
  • A resposta é o documento do --json, com comando = o nome da ferramenta, redigida pelo mesmo serializador: cada valor do .env, das credenciais declaradas, da chave e de variável com nome de segredo sai como [redigido], também URL-encoded e em base64. Nenhuma ferramenta lê .env, keyring, cookie ou o conteúdo de um trace; a captura da falha sai como caminho, tamanho e sha256.
  • O texto que veio do cliente (o log do run, a página, a gravação) chega só em dados.cliente ({"dados_do_cliente": true, "origem", "truncado", "conteudo"}), sem caractere de controle e com teto de 16 KiB e 200 linhas. É rótulo e teto, não barreira contra injeção: o modelo lê os mesmos tokens. Ids, estados e contagens ficam no topo, conferidos pela forma. Na gravação, todo valor digitado sai como [digitado].
  • Caminhos são relativos ao projeto e presos a ele (.., absoluto, symlink para fora e laço caem); .env*, .git/, *.pem e .shade/credenciais são recusados. Leitura até 256 KiB por arquivo, listagens até 500 entradas.
  • O navegador é sempre um Chromium headless num contexto novo (nunca o seu perfil, sem service worker, sem download, sem o storage de outra chamada), com a rede só em [hosts] permitidos, em HTTP e WebSocket, salto a salto nos redirecionamentos. IP privado, loopback, link-local, localhost e *.local só passam listados por inteiro. O que a página pediu fora da lista volta em bloqueados. Risco que fica: o DNS rebinding de um nome da lista.

Plugin do Claude Code

O plugin vem na wheel, na mesma versão das ferramentas que as skills encadeiam (o que cada skill faz está no README do plugin):

uv tool install 'shade-cli[mcp]'
shade claude-code instalar

O comando copia o plugin para ~/.shade/claude-code/, um marketplace local do Claude Code, e roda claude plugin marketplace add ~/.shade/claude-code, claude plugin install shade@shadeone e claude plugin update shade@shadeone (escopo user: vale em qualquer pasta). Pede o claude no PATH. Para atualizar, uv tool upgrade shade-cli e o mesmo comando; o shade doctor avisa quando o plugin ficou atrás da CLI. Para tirar: claude plugin uninstall shade@shadeone.

CI

A mesma sequência em qualquer CI: instalar a CLI numa versão exata, shade test, shade deploy. A chave vem de SHADE_API_KEY, num segredo do CI e no env do job, nunca em argumento nem em arquivo. Sem terminal a CLI nunca pergunta (--criar diz que o robô novo é de propósito), e o --json põe o resultado no stdout. A release fica aguardando a aprovação de uma pessoa: o CI não ativa nada. A saída 6 (prazo da espera) não é falha: a release segue no servidor e o erro.recuperacao do JSON traz shade releases show <id> --esperar.

GitHub. A Action shade-deploy (.github/actions/shade-deploy/) roda essa sequência e devolve os outputs release_id, project_sha256 e estado, lidos do JSON. O shade init já gera o workflow com ela (job publicar, na branch padrão):

- uses: SamuelPerroni/shade-one/.github/actions/shade-deploy@cli-v0.1.6
  env:
    SHADE_API_KEY: ${{ secrets.SHADE_API_KEY }}
  with:
    versao-da-cli: "0.1.6"            # exata; sem latest
    # pasta: robos/cadastro            # onde está o shade.toml (padrão: a raiz)
    # url-da-plataforma: https://...   # sem ela, vale o SHADE_URL ou o padrão da CLI

O repositório do ShadeOne é privado: para outro repositório usar a Action, libere o acesso em Settings > Actions > General > Access do repositório do ShadeOne.

GitLab.

publicar:
  image: ghcr.io/astral-sh/uv:python3.14-bookworm
  script:
    - uv tool install shade-cli==0.1.6
    - export PATH="$(uv tool dir --bin):$PATH"
    - uv sync --locked
    - shade test --json
    - shade deploy --json --criar | tee deploy.json
    - python3 -c "import json; print(json.load(open('deploy.json'))['dados']['estado'])"
  variables:
    SHADE_API_KEY: $SHADE_API_KEY      # variável mascarada do projeto
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

Azure Pipelines.

- script: |
    pip install uv
    uv tool install shade-cli==0.1.6
    export PATH="$(uv tool dir --bin):$PATH"
    uv sync --locked
    shade test --json
    shade deploy --json --criar
  displayName: Publicar o robô
  env:
    SHADE_API_KEY: $(SHADE_API_KEY)    # variável secreta: mapeie-a em env, o Azure não a expõe sozinho

Nos dois, o código de saída é o do shade: 1 gate reprovado, 3 chave, 6 prazo (retome com o comando do JSON), 7 rede. Trate o 6 como aviso se quiser o comportamento da Action.

--json e códigos de saída

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

{"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 (inclusive o deploy que acha a release existente, e a release que espera uma pessoa: aprovar ou preencher o cofre)
1 gate, lint ou teste reprovou; release reprovada na conferência ou no ensaio (e o defeito da própria CLI, com erro.codigo = "erro_interno")
2 uso inválido ou shade.toml inválido; robô novo sem --criar
3 chave ausente, recusada ou sem o escopo (401/403)
4 conflito de estado (409): ensaiar uma release reprovada, a release arquivada
5 incompatibilidade de versão: o shade-sdk do projeto não é o da imagem, ou o /sdk/compat não casa
6 o prazo da espera acabou; a release segue no servidor (erro.recuperacao traz a retomada)
7 rede ou servidor indisponível (5xx, 429)
130 interrompido (Ctrl-C, SIGTERM ou SIGHUP: o robô em andamento morre junto)

Lint de contrato

Regra Efeito O quê
L3 reprova import de pacote fora do lock da imagem e dos plugins da imagem que o projeto declara em [plugins]
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: quem isola o robô é o executor da plataforma.

Desenvolvimento

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.

Metadata

Release files for shade-cli 0.1.15

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distribution (wheel)

Table of built distributions (wheels) for shade-cli 0.1.15
File Interpreter ABI Platform
shade_cli-0.1.15-py3-none-any.whl Python 3 none any Details

Release files / shade_cli-0.1.15-py3-none-any.whl

Download URL shade_cli-0.1.15-py3-none-any.whl
Size 174.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9a7da39882230221e0e577ede1d4176a246b28756db49c03af80e8ab4a687cda
BLAKE2b-256 checksum
How to use checksums
6b780d7917797142c636529434639984d45a737d9aea7efcfbafe52113464d1f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Security for shade-cli 0.1.15

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page