La línea de comandos

stxt valida, formatea y describe documentos STXT desde un terminal, un script o un trabajo de integración continua.

Usa la biblioteca TypeScript @stxt-lang/core y no lleva parser propio: los errores y sus códigos son los mismos que en la extensión de VS Code, el playground y las bibliotecas. El uso sobre un proyecto completo, con su directorio .stxt/, está en El entorno de trabajo.

Instalación

Se publica en npm como @stxt-lang/cli y necesita Node 20 o superior:

npm install -g @stxt-lang/cli
stxt --version

stxt 1.0.4 (@stxt-lang/core 1.0.3, spec 2026-09-07)

--version muestra la versión del comando, la de la biblioteca y la fecha de STXT-SPEC que esta implementa. Sin instalación, con npx:

npx @stxt-lang/cli validate --recursive docs/

Dentro de la línea 1.x del paquete son estables los comandos, sus opciones, los códigos de salida y --format json. La salida en texto puede cambiar.

Sinopsis

stxt [--version | --help]
stxt validate <file|dir|->... [--recursive] [--format text|json] [--warn-schema | --no-schema]
              [--verbose] [--max-nesting N] [--max-line-length N] [--max-input-size N]
stxt format   <file|dir|->... [--recursive] [--tabs | --spaces] [--write | --check] [--clean]
              [--verbose] [--max-nesting N] [--max-line-length N] [--max-input-size N]
stxt describe <file|-> [--max-nesting N] [--max-line-length N] [--max-input-size N]
stxt schemas  [path]
stxt install  <file> [--local | --user | --system | --root <dir>] [--force] [--ignore-non-definitions]
Comando Qué hace
stxt validate Parsea y valida documentos contra las gramáticas que resuelve; sin salida si todo pasa
stxt format Reescribe documentos en forma canónica, conservando comentarios
stxt describe Emite el árbol lógico de un documento como JSON (STXT-TREE-SPEC)
stxt schemas Muestra la cadena de resolución y qué gramática aplica a cada namespace
stxt install Valida una gramática y la instala en un nivel de la cadena de resolución

Convenciones comunes a todos los comandos:

  • Las opciones son largas, con doble guion. Cuatro tienen alias corto: -v (--version), -h (--help), -r (--recursive) y -w (--write).
  • --version y --help valen en cualquier posición y tienen precedencia. No hay ayuda por comando: stxt validate --help imprime la general.
  • Una opción o un comando desconocidos son errores de uso: código 2, sin realizar ninguna acción.
  • Los resultados van por la salida estándar, incluido el informe de validate. Los errores de uso y de lectura, los de sintaxis de format y describe, y el progreso de --verbose, van por la salida de error.
  • - designa la entrada estándar en validate, format y describe, una sola vez por llamada, y el documento se reporta como <stdin>. Sin argumentos, ningún comando lee la entrada estándar: es un error de uso.
  • Ningún comando reescribe ficheros sin una opción explícita: format solo escribe con --write, e install solo sobrescribe con --force.

Códigos de salida

Código Significado
0 Éxito: los documentos validan, no hay nada que reformatear, la definición se ha instalado
1 Fallo de los documentos: errores de sintaxis o de gramática, ficheros que --check cambiaría, un fichero ilegible, una definición que no se puede instalar, una cadena de resolución con errores en schemas
2 Uso incorrecto: comando u opción desconocidos, falta un argumento, opciones incompatibles, un directorio sin --recursive

stxt validate

Parsea cada documento, resuelve su cadena de gramáticas (ver Resolución de gramáticas y STXT_PATH) y lo valida contra la gramática de cada namespace que use. Si todo pasa, no escribe nada y termina con 0.

Opción Efecto
--recursive, -r Desciende en los directorios y valida todos sus *.stxt, ordenados por nombre; los .stxt/ se saltan
--format text Un hallazgo por línea, más un resumen (por defecto)
--format json Los mismos hallazgos como array JSON
--warn-schema Los errores de gramática se reportan como avisos y no hacen fallar; los de sintaxis, sí
--no-schema Solo sintaxis: no resuelve ni aplica ninguna gramática
--verbose Escribe Validating <fichero> por la salida de error antes de cada documento
--max-nesting N, --max-line-length N, --max-input-size N Los límites del parser (STXT-SPEC §11.2): niveles de anidamiento, longitud de línea y tamaño total de la entrada; por defecto 100, 10000 y 10000000; -1 desactiva el límite

Un directorio exige --recursive; sin él es un error de uso (2). Ficheros, directorios y - se pueden mezclar en la misma llamada.

Un límite excedido se reporta como un error de parseo más y corta el parseo de ese documento. validate parsea en streaming: la memoria que usa es del orden del mayor nodo raíz y no del documento. Un documento mayor que el tamaño por defecto se valida con --max-input-size -1.

En modo texto, los hallazgos de cada documento se escriben al terminar ese documento, y el recuento, al final. El array de --format json se escribe entero al final. --verbose muestra el progreso sin tocar la salida estándar:

stxt validate --recursive --verbose docs/

Validating /home/ana/libros/docs/book.stxt

Con -, la cadena de gramáticas es la del directorio actual, la que muestra stxt schemas sin argumento:

git show HEAD:docs/book.stxt | stxt validate -

Los hallazgos

Con el proyecto de El entorno de trabajo (la plantilla com.acme.book en .stxt/), un docs/book.stxt con una fecha no válida y sin el ISBN obligatorio:

stxt validate docs/book.stxt

/home/ana/libros/docs/book.stxt:6: [INVALID_VALUE] Published: Invalid date (1 de octubre de 2025) (error)
/home/ana/libros/docs/book.stxt:1: [TOO_FEW_CHILDREN] 0 nodes of 'com.acme.book:isbn' and min is 1 (error)
2 error(s), 0 warning(s)

Cada línea es fichero:línea: [CÓDIGO] mensaje (severidad), con la ruta absoluta, y al final va el recuento. Los códigos son estables y los mismos en todas las herramientas. Los más habituales:

Código Ámbito
INDENTATION_MIXED, INDENTATION_LEVEL_NOT_VALID, INVALID_LINE Sintaxis (STXT-SPEC)
INVALID_VALUE, TOO_FEW_CHILDREN, CHILD_NOT_DECLARED, NODE_NOT_DEFINED_IN_SCHEMA Gramática (STXT-SCHEMA-SPEC)
SCHEMA_NOT_FOUND El documento usa un namespace que la cadena no define
DISCOVERY_DUPLICATE_NAMESPACE, DISCOVERY_NOT_A_DEFINITION La propia cadena de resolución (STXT-DISCOVERY-SPEC)
FILE_NOT_READABLE El fichero no existe o no se puede leer

Un error de cardinalidad se señala en la línea del padre (Book, línea 1). Los errores de la cadena de resolución (una gramática no válida en .stxt/, dos definiciones del mismo namespace en el mismo nivel) se reportan en la línea 0 del fichero causante y hacen fallar la validación:

stxt validate docs/book.stxt

/home/ana/libros/.stxt/otro/copia.stxt:0: [DISCOVERY_DUPLICATE_NAMESPACE] Duplicate definition for namespace 'com.acme.book' at level /home/ana/libros/.stxt: already defined in /home/ana/libros/.stxt/@stxt.template/com.acme.book.stxt (error)
1 error(s), 0 warning(s)

Sin gramática, o con la gramática en aviso

  • Un documento sin namespace no se valida y pasa (STXT-SCHEMA-SPEC §5).
  • Uno con namespace que la cadena no define produce SCHEMA_NOT_FOUND, también con la cadena vacía.
  • Una definición (@stxt.schema o @stxt.template) se comprueba siempre contra su meta-esquema.

--warn-schema rebaja los errores de gramática a avisos, para introducir una gramática en un proyecto con documentos anteriores a ella:

stxt validate --warn-schema docs/book.stxt

/home/ana/libros/docs/book.stxt:6: [INVALID_VALUE] Published: Invalid date (1 de octubre de 2025) (warning)
/home/ana/libros/docs/book.stxt:1: [TOO_FEW_CHILDREN] 0 nodes of 'com.acme.book:isbn' and min is 1 (warning)
0 error(s), 2 warning(s)

Termina con 0. Con --no-schema solo se comprueba la sintaxis: el mismo documento pasa sin salida.

Salida JSON

Con --format json la salida es un array con un objeto por hallazgo (file, line, code, message, severity), o [] si todo pasa, sin resumen. El código de salida es el mismo que en modo texto.

stxt validate --format json docs/book.stxt

[{"file":"/home/ana/libros/docs/book.stxt","line":6,"code":"INVALID_VALUE","message":"Published: Invalid date (1 de octubre de 2025)","severity":"error"},{"file":"/home/ana/libros/docs/book.stxt","line":1,"code":"TOO_FEW_CHILDREN","message":"0 nodes of 'com.acme.book:isbn' and min is 1","severity":"error"}]
# Cuántos hallazgos de cada código hay en todo el proyecto
stxt validate --format json --recursive docs/ | jq -r '.[].code' | sort | uniq -c

stxt format

Reescribe documentos línea a línea, según el reformateado de STXT-TREE-SPEC §12:

  • Normaliza la indentación a tabuladores (o a cuatro espacios con --spaces), deja un solo espacio tras los dos puntos y quita los espacios de final de línea.
  • Conserva los comentarios, las líneas en blanco, el final de línea original (CRLF incluido) y la ausencia de salto final.
  • El contenido de los bloques >> solo se reindenta. Las líneas en blanco finales de un bloque no son contenido y quedan sin indentar.
  • De la indentación de un comentario convierte solo las unidades enteras (tabuladores o grupos de cuatro espacios).
  • Escribe el namespace únicamente donde el fuente lo escribió.

Tres modos, mutuamente excluyentes:

Modo Qué hace Sale con 1 si...
(por defecto) Imprime el resultado por la salida estándar; no escribe en disco Algún documento no parsea
--check Lista los ficheros que cambiarían (<fichero>: would be reformatted); no escribe nada Alguno cambiaría, o no parsea
--write, -w Reescribe cada fichero in situ, solo si cambia, y lo indica (Formatted <fichero>) Algún documento no parsea

Otras opciones:

Opción Efecto
--tabs / --spaces Indentar con tabuladores (por defecto) o con cuatro espacios
--recursive, -r Igual que en validate: desciende, ordena por nombre, salta los .stxt/
--clean Reserializa el árbol lógico (STXT-TREE-SPEC §11): se pierden comentarios y líneas en blanco
--verbose Escribe Formatting <fichero> (Checking <fichero> con --check) por la salida de error antes de cada documento
--max-nesting N, --max-line-length N, --max-input-size N Los límites del parser, como en validate

--check equivale a gofmt -l o prettier --check. Un documento con errores de sintaxis se reporta y no se reformatea. format no aplica gramáticas. Combinar --write con --check, o --tabs con --spaces, es un error de uso (2).

Un documento escrito con espacios, con un comentario, una línea en blanco y espacios de más:

# Ficha del libro
Book (com.acme.book):
    Title:   Arquitectura de software moderna

    Authors:
        Author: María Pérez
    ISBN: 978-84-123456-7-8
stxt format docs/book.stxt

# Ficha del libro
Book (com.acme.book):
	Title: Arquitectura de software moderna

	Authors:
		Author: María Pérez
	ISBN: 978-84-123456-7-8

Los otros dos modos sobre el mismo fichero:

stxt format --check docs/book.stxt
/home/ana/libros/docs/book.stxt: would be reformatted
# código de salida 1

stxt format --write docs/book.stxt
Formatted /home/ana/libros/docs/book.stxt

stxt format --check docs/book.stxt
# ya no escribe nada: código de salida 0

Con -, format es un filtro: lee de la entrada estándar y escribe en la salida estándar. --check - responde <stdin>: would be reformatted y 1 si cambiaría. --write - es un error de uso:

stxt format --spaces - < docs/book.stxt

stxt format --write -
stxt format: --write cannot be used with - (the standard input); the result is printed to stdout

stxt describe

Escribe por la salida estándar el árbol lógico de un documento en el JSON canónico de STXT-TREE-SPEC: un array de nodos raíz, cada uno con name, canonicalName, el namespace efectivo y la forma ("inline" con value y children, o "block" con lines). No incluye posiciones ni comentarios.

No resuelve gramáticas ni valida. Si el documento tiene errores de sintaxis no emite un árbol parcial: los informa por la salida de error y termina con 1. Acepta - y los mismos límites del parser que validate.

Book (com.acme.book):
	Title: Arquitectura de software moderna
	Chapter: Introducción
		Content >>
			Conceptos básicos y objetivos del libro.
stxt describe docs/book.stxt

[
  {
    "name": "Book",
    "canonicalName": "book",
    "namespace": "com.acme.book",
    "form": "inline",
    "value": "",
    "children": [
      {
        "name": "Title",
        "canonicalName": "title",
        "namespace": "com.acme.book",
        "form": "inline",
        "value": "Arquitectura de software moderna",
        "children": []
      },
      {
        "name": "Chapter",
        "canonicalName": "chapter",
        "namespace": "com.acme.book",
        "form": "inline",
        "value": "Introducción",
        "children": [
          {
            "name": "Content",
            "canonicalName": "content",
            "namespace": "com.acme.book",
            "form": "block",
            "lines": [
              "Conceptos básicos y objetivos del libro."
            ]
          }
        ]
      }
    ]
  }
]
# El título del libro, con jq
stxt describe docs/book.stxt | jq -r '.[0].children[] | select(.canonicalName == "title") | .value'

stxt schemas

Muestra la cadena de resolución de un documento o de un directorio (por defecto, el actual) y, para cada namespace, la definición activa y su fichero. Es el primer diagnóstico ante un SCHEMA_NOT_FOUND.

stxt schemas docs

Resolution chain for /home/ana/libros/docs:
    /home/ana/libros/.stxt

Namespaces:
    com.acme.book <- /home/ana/libros/.stxt/@stxt.template/com.acme.book.stxt

La cadena lista los niveles en orden de precedencia. Si el proyecto está dentro de otro con su propio .stxt/, aparecen los dos, y para cada namespace gana el más cercano. Sin ningún nivel:

stxt schemas

Resolution chain for /home/ana/notas:
    (empty: no .stxt directory found)

No namespaces resolved.

Los errores de la cadena van por la salida de error, en un bloque Errors: al final. Con dos definiciones del mismo namespace en el mismo nivel, el namespace se queda sin definición activa, y validate falla con el mismo error:

stxt schemas docs

Resolution chain for /home/ana/libros/docs:
    /home/ana/libros/.stxt

No namespaces resolved.

Errors:
    DISCOVERY_DUPLICATE_NAMESPACE /home/ana/libros/.stxt/otro/copia.stxt: Duplicate definition for namespace 'com.acme.book' at level /home/ana/libros/.stxt: already defined in /home/ana/libros/.stxt/@stxt.template/com.acme.book.stxt

Termina con 1 si la cadena tiene errores o la ruta no existe, y con 0 en cualquier otro caso, también con la cadena vacía.

stxt install

Instala las definiciones de un fichero en un nivel de la cadena de resolución. Antes de escribir comprueba que el fichero tenga extensión .stxt, que parsee y que cada nodo raíz sea una definición que valide contra su meta-esquema; si algo falla, no escribe nada. Cada definición se escribe por separado, en forma canónica, como <nivel>/@stxt.schema/<namespace>.stxt o <nivel>/@stxt.template/<namespace>.stxt.

Esa disposición es una convención de la CLI: STXT-DISCOVERY-SPEC §3 no da significado a los nombres de fichero ni a los subdirectorios de un nivel, y una gramática colocada a mano puede estar en cualquier ruta.

Nivel Opción Dónde escribe
Proyecto --local ./.stxt (el directorio actual; por defecto)
Usuario --user ~/.stxt (%USERPROFILE%\.stxt en Windows)
Sistema --system /etc/stxt (%ProgramData%\stxt en Windows)
Cualquiera --root <dir> El directorio que se indique, exista o no
Opción Efecto
--force Sobrescribe una definición ya instalada para ese namespace (coincidencia de ruta o de namespace)
--ignore-non-definitions Instala las definiciones del fichero y salta los demás nodos raíz, en vez de fallar
stxt install book-template.stxt

Installed com.acme.book (@stxt.template) to /home/ana/libros/.stxt/@stxt.template/com.acme.book.stxt

Los casos que hacen fallar la instalación (código 1):

stxt install book-template.stxt
stxt install: /home/ana/libros/.stxt/@stxt.template/com.acme.book.stxt already exists (use --force to overwrite)

stxt install docs/book.stxt
stxt install: docs/book.stxt:1: root node 'Book' belongs to 'com.acme.book', not to @stxt.schema or @stxt.template (use --ignore-non-definitions to install only the definitions)

stxt install broken.stxt
stxt install: broken.stxt: invalid @stxt.template definition: Type not valid: NOTATYPE

stxt install notes.txt
stxt install: not an STXT document (.stxt expected): notes.txt

Resolución de gramáticas y STXT_PATH

validate, schemas e install usan la cadena de STXT-DISCOVERY-SPEC §4, la misma que la extensión de VS Code y las bibliotecas:

  • Los niveles son todos los directorios .stxt/ desde la carpeta del documento hacia arriba, después ~/.stxt y por último /etc/stxt.
  • Dentro de un nivel se cargan todos los ficheros .stxt, recursivamente, y cada uno debe ser una definición.
  • La precedencia es por namespace: prevalece el nivel más cercano que lo defina, y los demás niveles aportan los namespaces que aquel no define.
  • Dos definiciones del mismo namespace en el mismo nivel son un error, y ese namespace se queda sin definición.

La variable de entorno STXT_PATH sustituye la cadena entera por una lista de directorios separados por : (; en Windows), en orden de precedencia. Las entradas no tienen por qué llamarse .stxt, y una que no exista no aporta nada. En CI evita depender del ~/.stxt o del /etc/stxt de la máquina:

STXT_PATH=./.stxt stxt validate --recursive docs/

Una STXT_PATH definida pero vacía deja la cadena vacía: validate falla con SCHEMA_NOT_FOUND en todo documento con namespace, salvo con --no-schema o --warn-schema, y schemas muestra (empty: STXT_PATH provides no directories).

Tareas frecuentes

Integración continua: los documentos validan y están formateados.

npx @stxt-lang/cli validate --recursive docs/
npx @stxt-lang/cli format --check --recursive docs/

Formatear un proyecto entero por primera vez, pasándolo a espacios. Los .stxt/ se saltan; las gramáticas se formatean en una llamada aparte.

stxt format --write --spaces --recursive .

Un documento que no está en disco, con -:

curl -s https://example.com/api/book.stxt | stxt validate -
curl -s https://example.com/api/book.stxt | stxt describe - | jq '.[0].name'

Límites

  • No convierte a otros formatos: las únicas salidas estructuradas son el JSON de describe y el de validate --format json.
  • No lleva parser. Los errores de parseo o de validación se reportan en stxt-js; los de opciones, mensajes o comportamiento del comando, en stxt-cli.