# CLI

A CLI do Fayz scaffolda projetos, valida manifestos e limites de arquitetura, assiste a migração de config-em-código para manifesto, e provisiona o banco Supabase de um app a partir dos pacotes instalados. Você a chama sem instalar nada, via `npx`:

```bash
npx @fayz-ai/cli <comando>
```

## Comandos

| Comando | O que faz |
| --- | --- |
| `fayz create storefront <nome>` | Scaffolda um storefront (loja voltada ao cliente). |
| `fayz create admin <nome>` | Scaffolda um app admin multi-tenant. |
| `fayz create member <nome>` | Scaffolda um portal de membros/alunos. |
| `fayz create plugin <nome>` | Scaffolda um plugin app-local (incubator). |
| `fayz doctor [dir]` | Valida manifesto + limites de arquitetura. |
| `fayz extract [dir]` | Migração assistida de config-em-código → manifesto. |
| `fayz db apply [dir]` | Provisiona o Supabase a partir dos pacotes instalados. |
| `fayz db pool status` | Mostra o ledger de migração de cada *industry pool* (Runner v2). *(≥ 0.3.0)* |
| `fayz db pool apply <name> --app <dir>` | Aplica o plano de um app a **um** pool, sempre ledger-gated. *(≥ 0.3.0)* |
| `fayz db pool move-tenant --from <p> --to <p> --tenant <uuid> [--yes]` | Move um tenant entre pools (dry-run sem `--yes`). *(≥ 0.3.0)* |
| `fayz db fan-out --app <dir>` | Aplica o plano de um app em todos os pools: canary primeiro, depois o resto. *(≥ 0.3.0)* |
| `fayz login [--token \| --status]` | Salva o token da plataforma Fayz para o `deploy`. *(≥ 0.3.0, em rollout)* |
| `fayz logout` | Remove a credencial salva. *(≥ 0.3.0, em rollout)* |
| `fayz deploy [dir] [--dry-run \| --yes]` | Publica o app na plataforma Fayz. *(≥ 0.3.0, em rollout)* |
| `fayz --help` | Mostra a ajuda. |
| `fayz --version` | Mostra a versão. |

{% callout type="info" %}
Os comandos `db pool`, `db fan-out`, `login`, `logout` e `deploy` **requerem CLI ≥ 0.3.0** — não existem na 0.2.0 publicada. `login`/`logout`/`deploy` ainda estão **em rollout** para a rede de desenvolvedores convidados.
{% /callout %}

O `create` recebe o **kind** e um **nome em kebab-case** (`^[a-z0-9][a-z0-9-]*$`) — sem flags. Ele gera um projeto Vite com `app.manifest.json`, `src/plugins.generated.ts`, `src/registry.tsx`, `AGENTS.md` e o `.env.example`. Veja o [tutorial 01](/pt-BR/docs/tutorial/01-criar-o-app).

## `fayz create plugin`

Cria um plugin app-local em `src/plugins/<nome>/`, seguindo o mesmo contrato dos plugins oficiais (index/data/schema/README). Detalhes em [Incubator](/pt-BR/docs/plugins-proprios/incubator).

## `fayz doctor`

Valida o app do diretório atual: estrutura do manifesto, plugins referenciados, cobertura de locale e os limites de arquitetura (imports de provedor + superfície suportada). Problemas **estruturais** do manifesto saem com erro (exit 1); problemas de **boundary** são avisos (soft enforcement). Um app sem `app.manifest.json` mas com `package.json` é tratado como código-primeiro — roda só os boundaries e passa. Veja [Testar e debugar](/pt-BR/docs/testar-e-debugar).

## `fayz db apply`

Monta a ordem de migração — o **core** primeiro, depois os módulos versionados de cada plugin, depois os incubator — a partir dos pacotes instalados e a aplica no seu projeto Supabase via Management API. O CLI atual rotula os passos como `spine → drizzle → seed → plugins → incubator` (os três primeiros são o core; o rótulo migra na wave de *industry pools*).

### Flags

| Flag | Efeito |
| --- | --- |
| `--dry-run` | Imprime só o plano ordenado; **nenhuma** chamada de rede. |
| `--yes`, `-y` | Pula a confirmação (obrigatório em shells não interativos). |
| `--spine-only` | Aplica só o core do `@fayz-ai/db` (a flag mantém o rótulo `spine` na wave atual). |
| `--plugins-only` | Aplica só as migrations de plugins + incubator. |
| `--only-plugins a,b` | Restringe o passo de plugins aos ids nomeados. |

### Env (obrigatório num apply real; nunca no `--dry-run`)

| Variável | Descrição |
| --- | --- |
| `SUPABASE_PROJECT_REF` | Ref do projeto (alias: `SUPABASE_REF`). Dashboard → Project Settings → General. |
| `SUPABASE_PAT` | Personal access token (alias: `SUPABASE_ACCESS_TOKEN`). Dashboard → Account → Access Tokens. |

O comando lê primeiro do ambiente do processo, depois de `<app>/.env.local`, depois de `<app>/.env` — e os arquivos nunca sobrescrevem o ambiente. Sem essas variáveis, um apply real para com um erro claro; o `--dry-run` não precisa delas.

```bash
# planeje sem tocar no banco
npx @fayz-ai/cli db apply --dry-run

# aplique (pede confirmação; use --yes em CI)
npx @fayz-ai/cli db apply
```

O fluxo completo de conexão está em [Supabase](/pt-BR/docs/dados/supabase).

## `fayz extract`

Assiste a migração de um app código-primeiro (config em `src/App.tsx` / `defineSaas`) para o `app.manifest.json`. Rode-o na raiz de um app existente; ele lê o código de config e propõe o manifesto equivalente.

## `fayz db pool` e `fayz db fan-out` (industry pools — Runner v2) {% badge status="beta" %}

{% callout type="info" %}
Requer **CLI ≥ 0.3.0** — estes comandos não existem na 0.2.0 publicada.
{% /callout %}

Enquanto o `db apply` provisiona **um** projeto Supabase, o Runner v2 opera sobre uma frota de *industry pools* — os projetos Supabase compartilhados por vertical. Ele lê o registro de pools de `cli/pools.config.json` (use `--pools-file` para apontar outro arquivo) e pega o token de `SUPABASE_PAT` / `SUPABASE_ACCESS_TOKEN` (a ref de cada pool vem do arquivo de pools, não do ambiente).

| Comando | O que faz |
| --- | --- |
| `fayz db pool status` | Imprime o ledger de migração de cada pool: o que já foi aplicado e o que está pendente. |
| `fayz db pool apply <name> --app <dir>` | Aplica o plano do app (derivado dos pacotes instalados em `<dir>`) a **um** pool nomeado. |
| `fayz db pool move-tenant --from <p> --to <p> --tenant <uuid> [--yes]` | Move um tenant de um pool para outro. |
| `fayz db fan-out --app <dir>` | Aplica o plano do app **em todos os pools**: o canary primeiro, depois o resto. |

### Applies são sempre ledger-gated

Toda aplicação passa pelo ledger de cada pool. Um arquivo já aplicado, sem mudança, é **pulado**. Um arquivo já aplicado cujo **checksum mudou** é um **HARD STOP** — o runner para em vez de reaplicar. A regra é absoluta: **nunca edite uma migração já aplicada; escreva a próxima**. Isso garante que o histórico de cada pool seja reprodutível e auditável.

### Fan-out: canary primeiro

O `db fan-out` não aplica em tudo de uma vez. Ele aplica primeiro no pool marcado como canary (`--canary <pool>` para forçar outro), e só depois nos demais — para um erro aparecer num pool antes de tocar a frota inteira. Pools em estado `PROVISIONING` são pulados no fan-out a menos que nomeados explicitamente; um pool marcado `dataCritical` exige `--allow-critical` (junto de `--yes`).

### `move-tenant` é seguro por construção

O `move-tenant` é **dry-run por padrão** — sem `--yes` ele só mostra o plano. Com `--yes`, ele: faz backup em JSON **antes** de qualquer escrita, insere os registros no destino (parents-first), **verifica as contagens** (se divergirem, é HARD STOP e a origem fica intacta) e só então apaga na origem (children-first). O pool de destino não pode estar em `PROVISIONING`.

## `fayz login` / `fayz logout` / `fayz deploy` {% badge status="experimental" %}

{% callout type="info" %}
Requer **CLI ≥ 0.3.0** e está **em rollout** para a rede de desenvolvedores convidados. Se o `deploy` retornar erro de autorização, seu token ainda não tem acesso de CLI liberado — o [host estático](/pt-BR/docs/deploy/estatico) coloca o mesmo app no ar enquanto isso.
{% /callout %}

Esse trio publica um app direto na plataforma Fayz, sem CI próprio.

- **`fayz login [--token <fayz_...> | --status]`** — salva o token de acesso da plataforma (prefixo `fayz_`) em `~/.fayz/credentials.json` (modo `0600`, só o dono lê). Sem `--token`, ele lê da env `FAYZ_TOKEN` ou pede interativamente (num shell não interativo sem token, falha rápido com instruções). `--status` mostra a credencial mascarada, sem rede. Não há validação de rede no login — o token é validado no primeiro deploy.
- **`fayz logout`** — apaga a credencial salva.
- **`fayz deploy [dir] [--dry-run | --yes]`** — coleta os arquivos de **fonte** do app, cria/vincula um projeto na plataforma e dispara o build server-side com host estático. O vínculo do projeto fica em `<app>/.fayz/project.json` (adicione `.fayz/` ao seu `.gitignore`). O app publicado fica em `https://<app>.live.fayz.ai`. `--dry-run` não faz **nenhuma** chamada de rede; um deploy real pede confirmação a menos que `--yes`.

**Resolução de token e URL:** o token vem de `FAYZ_TOKEN` (env, prioridade) → `~/.fayz/credentials.json`. A URL da API vem de `FAYZ_API_URL` (default `https://beta.fayz.ai/api`). O passo a passo com screenshots está em [Deploy na Fayz](/pt-BR/docs/deploy/fayz).

---

Próximo: os campos que o `doctor` valida em [Manifesto do plugin — referência](/pt-BR/docs/referencia/plugin-manifest).
