C4 — CLI esencial (run / check / fmt / lint / dev)¶
Pre-requisitos: C3 — Hola mundo + LSP
terminado. Ya tenés mi-saludos/ abierto en VSCode.
Objetivo: dominar los comandos CLI del día-a-día con
todos sus flags, exit codes y edge cases. Al final del cap
no tenés que volver a fitz <cmd> --help para nada.
Por qué importa: el LSP de C3 te cubre mientras escribís. Pero antes de commitear, abrir un PR, o correr en CI, lo canónico es pasar por la terminal. Cada comando de este cap es una pieza del workflow estándar.
El CLI completo de Fitz¶
Usage: fitz <COMMAND>
Commands:
run Ejecutar un .fitz (interpretado)
build Compilar a binario nativo ← C6
check Type-check sin ejecutar
openapi Emitir schema OpenAPI 3.1 ← M4
py-types Generar `type` Fitz desde modelos SQLAlchemy
py-stubs Generar `type` Fitz desde stubs .pyi
new Crear proyecto nuevo ← C2
init Inicializar proyecto en cwd ← C2
add Agregar dependencia ← M3
remove Quitar dependencia ← M3
update Actualizar git deps ← M3
fmt Formatear código
test Correr `@test` fns ← M2
dev Hot reload
repl REPL interactivo ← C5
lint Linter
db Migraciones del ORM ← M6
help Print this message or help of subcommand
Options:
-h, --help Print help
-V, --version Print version
Para help de un subcomando específico:
Para versión:
El comando
fitz help(sin guion) es equivalente afitz --help. Convención clap (la lib de parsing). Ambas funcionan.
Tabla maestra de comandos cubiertos en este cap¶
| Comando | Para qué | Manifest mode | Exit code 0 | Exit code 1 |
|---|---|---|---|---|
fitz run |
Ejecutar (interpretado) | ✓ sin args | Programa OK | Error de tipo (strict) o panic |
fitz check |
Type-check sin ejecutar | ✓ sin args | Sin errores | Hay errores de tipo |
fitz fmt |
Formatear | ✓ sin args | Aplicado/ya OK | (n/a) |
fitz fmt --check |
Verificar formato | ✓ sin args | Está bien | Hay archivos sin formatear |
fitz lint |
Detectar patrones | ✓ sin args | Sin findings (o sin --deny) |
--deny <lint> matcheó |
fitz dev |
Hot reload | ✓ sin args | (n/a — corre hasta Ctrl+C) | (n/a) |
fitz run es destructivo (ejecuta tu código). Los otros son
read-only: leen tus archivos y reportan.
Paso 1 — fitz run¶
Sintaxis completa¶
| Posición | Qué es |
|---|---|
FILE |
Archivo .fitz a ejecutar. Si se omite, busca fitz.toml en cwd o ancestros (Cargo-style) y ejecuta su [bin].main. |
ARGS... |
Args adicionales que se pasan al programa Fitz cuando tiene @command (M2.C6+). El -- los separa de los args de fitz. |
Flag: --no-typecheck¶
Saltea el chequeo estático. Sin esta flag, fitz run aborta
si hay errores de tipo (modo strict por default desde Fase
5.4). Con --no-typecheck corre igual.
Cuándo usarlo: - Prototipando algo y querés ver el output runtime aunque haya errores de tipo. - Migrando código viejo que todavía no anda en strict.
No lo uses en CI — el sentido del checker estático es que los errores son tu primera línea de defensa.
Modos de ejecución¶
Manifest mode (sin args)¶
Desde la raíz de un proyecto creado con fitz new:
Sube por ancestros buscando fitz.toml. Funciona desde
cualquier subcarpeta del proyecto:
Single-file mode¶
No requiere fitz.toml. Útil para archivos sueltos o
experimentos.
Con args al programa (-- <args>...)¶
Cuando tu programa tiene fns con @command (CLI builder de
Fase 13, M2.C6 lo cubre en detalle), pasás args al programa
después de --:
El -- separa: lo que va antes son args de fitz, lo que va
después son los args de tu programa.
@command("greet")
fn greet(name: Str, loud: Bool = false) {
if (loud) {
print("HOLA, {name}".upper())
} else {
print("hola, {name}")
}
}
fitz run src/main.fitz -- greet Ada
# hola, Ada
fitz run src/main.fitz -- greet Ada --loud
# HOLA, ADA
fitz run src/main.fitz -- --help
# (muestra el --help auto-generado del programa)
Exit codes de fitz run¶
| Exit code | Causa |
|---|---|
| 0 | Programa terminó OK |
| 1 | Error de tipo (modo strict, sin --no-typecheck) |
| 1 | Error de parseo o lex |
| 1 | Panic en runtime (división por cero, index fuera de rango, etc.) |
| 1 | Programa con @command retornó algo distinto de Int |
| Code custom | Programa con @command retornó un Int (es el exit code) |
Paso 2 — fitz check¶
Sintaxis¶
Como fitz run pero sin ejecutar el programa. Solo verifica
tipos y sintaxis.
Exit 0.
Output con errores¶
Editá src/main.fitz con un error a propósito:
✗ /ruta/a/mi-saludos/src/main.fitz — 2 error(es) de tipo:
Error en línea 1:1 — `edad` declarado como `Int` recibió un valor `Str`
Error en línea 2:1 — `altura` declarado como `Float` recibió un valor `Str`
Exit 1.
Diagnostics agregados:
fitz checkreporta todos los errores en un pase (gracias al error recovery del parser de Fase 9.0/F15), no se para en el primero. CI puede reportar la lista completa sin volver a correr.
Modos¶
| Modo | Comando |
|---|---|
| Single-file | fitz check archivo.fitz |
Manifest (chequea [bin].main) |
fitz check (desde la raíz) |
Para chequear todos los archivos del proyecto (no solo el
[bin].main), por ahora hay que correr fitz check archivo por
archivo o confiar en fitz lint (que sí pasa por todos).
Mejora pendiente del lenguaje.
Exit codes¶
| Exit code | Causa |
|---|---|
| 0 | Sin errores |
| 1 | Hay errores de tipo, parseo o lex |
Paso 3 — fitz fmt¶
Sintaxis¶
| Posición / flag | Qué hace |
|---|---|
FILES... |
Archivos a formatear. Si se omiten, formatea todos los .fitz del proyecto (requiere fitz.toml). |
--check |
Modo CI: no escribe, exit 1 si hay diffs. |
Estilo canónico¶
Cero config. Reglas fijas:
- 4 espacios de indent (no tabs).
- Comillas dobles (
"x", no'x'). - Trailing comma solo en multi-línea.
- Blank line entre fns y types top-level.
- Comments y blank lines del usuario preservados (no se reorganizan).
Demo bit-a-bit¶
Editá src/main.fitz con estilo "feo":
Antes de aplicar — modo CI (--check):
✗ /ruta/.../src/main.fitz no está en formato canónico
uso `fitz fmt` (sin `--check`) para aplicar el formato.
Exit 1.
Aplicar:
Resultado:
Cambios aplicados:
- Espacios alrededor de =, :, ->, *.
- fn double(n: Int) -> Int => n * 2 se expandió a bloque con
return explícito (preferido para fns multi-línea claras).
- Blank line entre la fn y el print del scope superior.
Modo "archivos explícitos"¶
fitz fmt src/main.fitz src/users.fitz # solo esos dos
fitz fmt src/main.fitz --check # check sobre uno solo
Útil en pre-commit hooks que solo formatean los archivos staged.
Exit codes¶
| Exit code | Causa |
|---|---|
| 0 | Sin --check: aplicado o ya OK. Con --check: todos en formato. |
| 1 | Con --check: hay archivos sin formatear. |
| 1 | Error de lectura/parseo de algún archivo. |
📚 Detalle de las convenciones: docs/fmt-style.md.
Paso 4 — fitz lint¶
Sintaxis¶
| Posición / flag | Qué hace |
|---|---|
FILES... |
Archivos a lintear. Si se omiten, lintea todos los .fitz del proyecto. |
--deny <lint> |
Trata ese lint como error (exit 1). Repetible. |
Los 4 lints implementados¶
1. unused_variable¶
Variable declarada que nunca se usa.
warning: variable `edad_olvidada` declarada pero no usada [unused_variable]
--> /ruta/.../src/main.fitz:2:1
= nota: si es intencional, prefijá con `_` (ej. `_edad_olvidada`) o suprimí con `// @allow(unused_variable)` en la línea anterior.
Para silenciar: prefijá con _ (convención que el lint
ignora) o anotá // @allow(unused_variable) en la línea
anterior.
2. unused_import¶
Import sin usos.
3. useless_match¶
match con un solo arm catch-all — equivale a el body directo.
warning: `match` con un solo arm catch-all es equivalente al body directo [useless_match]
--> /ruta/.../src/main.fitz:2:9
= nota: reemplazá `match x { _ => "default" }` por `"default"` directo.
4. string_concat¶
Concatenación de strings literales con + — preferí
interpolación.
warning: concatenación de strings — usá interpolación [string_concat]
--> /ruta/.../src/main.fitz:1:7
= nota: reemplazá `"a" + "b"` con `"ab"` (o usá interpolación `"{a}{b}"` si los lados son variables).
Nota: este lint solo dispara cuando ambos lados son string literales.
nombre + "!"(dondenombrees una var) NO dispara.
Suprimir un lint puntual¶
// @allow(<nombre-del-lint>) en la línea inmediatamente
anterior:
Útil cuando estás scaffoldeando algo o el "warning" es intencional (ej. variable que se rellena en una iteración futura).
--deny para CI¶
Default: los lints son warnings (exit 0). Para que CI falle, marcalos como errores:
Si encuentra alguno de esos, exit 1. Los otros siguen como warnings (no fallan el build).
Para que cualquier finding falle:
Output sin findings¶
Exit codes¶
| Exit code | Causa |
|---|---|
| 0 | Sin findings, o findings que no matchean --deny. |
| 1 | Findings que matchean algún --deny. |
| 1 | Error de lectura/parseo de algún archivo. |
📚 Catálogo y filosofía del linter: cap 27 — fitz lint
de la guía.
Paso 5 — fitz dev (hot reload)¶
Sintaxis¶
| Flag | Qué hace |
|---|---|
--file <FILE> |
Single-file mode. Sin él, manifest mode (lee fitz.toml). |
Cómo funciona¶
fitz dev levanta tu programa y lo re-arranca cada vez que
un .fitz o el fitz.toml cambia. Análogo a nodemon, cargo
watch, o vite dev.
🟢 fitz dev — corriendo src/main.fitz
esperando cambios... (Ctrl+C para salir)
[run 1]
Saludos desde Patagonia
Editás src/main.fitz, guardás → el child process se mata, el
output se limpia y arranca de nuevo:
Estrategia¶
- Kill + respawn del proceso entero. No hay incremental rebuild (deuda del lenguaje).
- Debounce 100ms — colapsa saves múltiples del editor en un solo restart.
- Ctrl+C mata el child antes de salir limpio (sin zombies).
Exclusiones automáticas¶
fitz dev ignora cambios en:
| Path / pattern | Por qué |
|---|---|
target/ |
Genera el codegen, no es source. |
.git/ |
Cambia constantemente con tu working tree. |
node_modules/, __pycache__/ |
Cache de otros tooling. |
.fitz/, dist/, build/ |
Output dirs. |
Archivos ocultos (.*) |
No-source típico. |
Solo dispara restart con .fitz o fitz.toml adentro del
proyecto.
Cuándo usarlo¶
- Desarrollando un servidor HTTP (M4) y querés ver cambios sin Ctrl+C + run manual.
- Iterando sobre un script que toma 1-2s en arrancar.
- Demos en vivo donde querés que cambios se reflejen al instante.
Cuándo NO usarlo: - Migrations destructivas o side effects irreversibles (cada restart corre todo desde cero). - Programs que necesitan retener state entre cambios (no hay hot-swap real).
📚 Detalle: cap 25 — fitz dev
de la guía.
Paso 6 — fitz test (preview, deep en M2.C6)¶
Adelanto para no dejarlo afuera del CLI esencial:
fitz test # todos los @test del proyecto
fitz test <FILTER> # solo los que matchean substring
fitz test --file <FILE> # single-file mode
Detalle completo + assertions + workflow en
M2.C6 (Funciones + fitz test) — cuando aprendamos a
definir fns con @test.
Paso 7 — Workflow estándar pre-commit¶
Antes de hacer git commit:
fitz fmt # 1. normalizar formato
fitz lint # 2. detectar patrones malos
fitz check # 3. verificar tipos
fitz test # 4. correr tests (si los hay)
fitz run # 5. confirmar que el happy path anda
Los 5 corren en <3s cada uno en proyectos chicos.
Pre-commit hook de git¶
Para que esto pase automático antes de cada commit, agregá
.git/hooks/pre-commit con:
#!/usr/bin/env bash
set -e
fitz fmt --check
fitz lint --deny unused_variable --deny string_concat
fitz check
fitz test
Ahora git commit aborta si alguno falla.
Workflow CI¶
Lo que típicamente va en .github/workflows/ci.yml o
equivalente:
- run: fitz fmt --check
- run: fitz lint --deny unused_variable --deny unused_import --deny string_concat
- run: fitz check
- run: fitz test
Tip de IDE: VSCode con la extensión Fitz te muestra los diagnostics del checker en vivo (C3). Eso cubre el
fitz checkinteractivo.fmtylintson los que conviene correr en CI o atarlos al pre-commit hook.
Paso 8 — Aplicar todo a mi-saludos¶
Editá src/main.fitz con código que va a disparar varios
issues:
let nombre = "Patagonia"
let edad_olvidada = 42
print("hola " + nombre)
let resultado = match nombre {
_ => "siempre default"
}
print(resultado)
Corré la suite completa:
warning: variable `edad_olvidada` declarada pero no usada [unused_variable]
--> /ruta/.../src/main.fitz:2:1
= nota: si es intencional, prefijá con `_` (ej. `_edad_olvidada`) o suprimí con `// @allow(unused_variable)` en la línea anterior.
warning: `match` con un solo arm catch-all es equivalente al body directo [useless_match]
--> /ruta/.../src/main.fitz:4:17
= nota: reemplazá `match x { _ => "default" }` por `"default"` directo.
2 findings en 1 archivo(s)
Arreglá los warnings:
let nombre = "Patagonia"
let _edad = 42 // prefijo _ silencia unused_variable
print("hola {nombre}") // interpolación en vez de "+"
let resultado = "siempre default" // sin match inútil
print(resultado)
Validación¶
-
fitz --helplista los comandos;fitz --versionimprimefitz 0.11.1(o más reciente). -
fitz rundesde la raíz del proyecto ejecuta[bin].mainsin pasar el archivo explícitamente. -
fitz checkexit 0 con código válido, exit 1 con un error de tipo a propósito; reporta todos los errores en un pase. -
fitz fmt --checkexit 1 cuando hay archivos sin formatear;fitz fmt(sin--check) los normaliza. -
fitz lint --deny unused_variableexit 1 si tu proyecto tiene una var no usada; sin--deny, exit 0 con warning. -
fitz devarranca el child, lo restartea al modificar un.fitz, y Ctrl+C lo termina limpio.
Troubleshooting¶
fitz run sin args me dice "no se encontró fitz.toml"
- Estás fuera de un proyecto. Opciones:
cda una carpeta confitz.toml.- O pasá el archivo explícito:
fitz run hola.fitz. - O creá un proyecto:
fitz new mi-proyecto.
fitz check me reporta un solo error y hay más
- Error de parseo serio puede limitar el recovery. Arreglá ese y el segundo pase va a mostrar más. Si no, es bug y vale issue.
fitz fmt me cambió cosas que no quería
- El estilo canónico es fijo (cero config). No hay opciones.
Si te molesta un cambio puntual, suprimilo manteniendo el
archivo fuera de
fitz fmt(no recomendado — preferí adaptarte al estilo).
fitz lint me lista warnings que no entiendo
- Cada warning trae nota con cómo arreglar. La nota es la primera línea de troubleshooting. Si querés más detalle, guide cap 27.
fitz dev no detecta mis cambios
- En Windows con WSL puede haber latency. Asegurate de editar el
archivo desde el sistema que corre
fitz dev(no cross-system WSL ↔ Windows). - Verificá que el path del archivo esté adentro del proyecto
(
fitz devignora cambios fuera del cwd / manifest dir).
fitz run -- arg1 arg2 me da error si no tengo @command
- Los args extras tras
--solo se usan cuando tu programa tiene@command. Sin@command, Fitz simplemente los ignora (no aborta) — pero verificá el output del programa si esperabas que los leyera.
Exit code distinto del esperado
- Tabla en la sección de cada comando arriba. Cualquier
fitz *con error severo (lex, parse, IO) sale con 1.
Lo que viene en C5¶
Vimos el CLI desde la perspectiva de "ejecutar mi código".
En el próximo cap arrancamos con el REPL — un shell
interactivo donde ingresás expresiones y statements línea
por línea. Perfecto para experimentar con la sintaxis, probar
fns sin crear archivos, y inspeccionar tipos en vivo con
:type.