STXT - Semantic Text
Built for humans. Reliable for machines.

Frequently asked questions

Short answers to the questions that come up when starting with STXT. Each answer links to the section of the reference that settles it; where they disagree, the reference wins.

The language

Why not YAML, JSON or TOML?

Because they solve a different problem. JSON and TOML are designed for data; YAML tries to cover data and text and pays for it with a huge grammar and well-known surprises (NO turning into false, variable indentation widths, anchors, tags that instantiate objects). STXT is designed for documents: things a person writes and reads, with structure and paragraphs of free text mixed together.

What sets it apart:

When what you have is data for another machine to read, JSON remains a good choice; and in fact every STXT document has a canonical JSON representation (see How do I convert it to JSON?).

Is it a data format or a document format?

Both, because the line between them is artificial: an email has fields and a body, a contract has clauses and metadata, a configuration has values and long comments. STXT is a tree of named nodes; each node carries either a value and children, or a block of text. That describes a data record as well as a twenty-page document. The use cases walk through that range.

Which file extension and media type do I use?

Extension .stxt; media type text/stxt, with text/plain as a compatible alternative. UTF-8 without BOM, LF line endings (CRLF is accepted). See STXT-SPEC §3 and §13.

Writing documents

Tabs or spaces?

Both work, and they mean the same: one tab is one level, four spaces are one level. What does not work is mixing them in the indentation of a single line (error MIXED_INDENTATION), or using another width (two spaces are not half a level: they are an error). Different lines of a document may use different styles, but for style's sake pick one; stxt format --tabs or --spaces unify it.

The fixed width is deliberate: the level of a line is computed from that line alone, and the hierarchy looks the same in every editor. Anyone who prefers a more compact indentation uses tabs and adjusts the tab width of their editor. See STXT-SPEC §8.1.

Do case, accents and spaces matter in names?

Names are compared by their canonical name: lower case, and every run of spaces, hyphens and underscores reduced to a single hyphen. Accents and non-Latin letters are kept. So:

Namespaces are stricter: ASCII [a-z0-9] and dots only, at least a.b, and they are lower-cased. See STXT-SPEC §4.3 and §7.

How do I write a value with a colon or a hash inside?

Just write it. In an inline node the value is everything after the first :, so Time: 10:30 has the value 10:30, and # only opens a comment when it is the first character of the line. Inside a >> block there is nothing to think about: it is literal text.

Meeting: 10:30 in room 2 # this is part of the value
Notes >>
	# this is text too, not a comment
	Key: value >> not a node either

Can a document have several root nodes?

Yes. A file may contain several level-0 nodes, each with its own tree, and the tools return them in order. That is what allows streaming parsing of large files: each root is emitted complete as soon as the next one begins. Namespaces are not inherited sideways between roots: each declares its own. See STXT-SPEC §8.5.

What about comments?

A line whose first non-blank character is # is a comment, and it does not count for indentation: neither a comment nor a blank line can cause a level error. Inside a >> block, a # line indented deeper than the node is text of the block; one indented less or equal is a comment and does not close the block. See STXT-SPEC §9.

What happens to comments when formatting?

They are kept. stxt format (and Format Document in the VS Code extension) rewrites only the lines that open a node; comments, blank lines and the content of blocks stay as they are, except for trailing whitespace. Losing comments requires an explicit flag, --clean, which re-serializes the tree and drops everything the tree does not describe. No tool in the ecosystem rewrites a file unless you ask for it (--write).

Schemas and templates

Are schemas mandatory?

No. A document without a namespace is parsed, full stop. If it has a namespace and its resolution chain has no definition at all, the tools only parse: nothing is wrong, it simply cannot be validated. Validation kicks in when definitions are nearby (a .stxt/ directory), and then it does count: a document with a namespace for which there is no definition is flagged with SCHEMA_NOT_FOUND, because it is almost always a misspelled namespace. In the CLI, --warn-schema turns that into a warning and --no-schema disables validation altogether.

Schema or template?

Two syntaxes for the same model, and every template is equivalent to a schema. The template (@stxt.template) is written like the document it describes, with the cardinality and the type in parentheses, and it is the recommended form for writing by hand:

Template (@stxt.template): com.example.docs
	Structure >>
		Email (com.example.docs):
			From: EMAIL
			To: (+) EMAIL
			Subject: (?)
			Body: (1) TEXT

The schema (@stxt.schema) is the explicit form, with Node, Children, Child, Min/Max and Type; it is what gets generated and what gets processed. When in doubt, template. See STXT-TEMPLATE-SPEC and STXT-SCHEMA-SPEC.

Where do I put schemas and templates?

In a directory called .stxt/ in the project: every .stxt file inside it is loaded, recursively, regardless of file names or subdirectories. The resolution chain of a document is every .stxt/ of its ancestor directories, then ~/.stxt, and finally /etc/stxt (on Windows, %USERPROFILE%\.stxt and %ProgramData%\stxt). The closest level wins, namespace by namespace. The STXT_PATH variable replaces the whole chain with a list of directories, handy in CI.

stxt install file.stxt puts a definition in place and stxt schemas shows what applies in a directory and where it comes from. The full walkthrough, with an example, is in The working environment; the norm, in STXT-DISCOVERY-SPEC.

What if I write Titel instead of Title?

The validator complains (CHILD_NOT_DECLARED). The content model is closed: a node only admits the children its definition declares, and if it declares none, it admits none. That is the point of validating: fail loudly instead of accepting silently. See STXT-SCHEMA-SPEC §6.

Is the order of children validated?

No. What is validated is how many times each child appears, not in which position: two documents with the same children in a different order validate the same. The order is preserved in the tree, so an application that gives it meaning gets it from the tree, not from the validator. There are no regular expressions, default values or conditional rules between fields either: they are declared non-goals. See STXT-SCHEMA-SPEC §11.

How do I evolve a schema without breaking documents?

Because the model is closed, adding a node breaks the validation of documents that use the old definition. The recommended practice is to version the namespace (com.example.docs.v1com.example.docs.v2): each version has its definition and each document declares the one it uses.

Tools

How do I validate in CI?

With the command line, without installing anything permanently:

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

The exit code is 1 if any document fails and 2 if the call itself is wrong, so the job fails on its own. --format json gives machine-readable output. And if the CI environment must not depend on whatever is in ~/.stxt or /etc/stxt, STXT_PATH=./.stxt pins the resolution chain. Details on the Tools page.

How do I convert it to JSON?

Every valid document has a canonical tree in JSON, defined in STXT-TREE-SPEC: an array of roots with name, canonicalName, namespace, and value plus children (inline) or lines (block). stxt describe file.stxt prints it, and the three libraries expose it from their API. It includes no positions and no comments: it is the logical content, the same in every implementation.

Which languages have a parser?

TypeScript/JavaScript (@stxt-lang/core), Java (dev.stxt:stxt-core) and Python (stxt), with the same scope, the same version and the same conformance corpus. The VS Code extension, the CLI and the playground run on the first one. Everything is on the Tools page; and to try it without installing anything, play.stxt.dev.