Files
interpres/docs/CLI.md
T
petrbalvin 3e741e7790
Test / test (push) Successful in 1m35s
feat(cmd): add version, plain json, struct inference and schema modes
Assisted-by: GLM 5.3 Flash
2026-09-22 00:55:02 +02:00

6.9 KiB

Command line

The reference below is taken from the program itself. interpres-decode is the toml-test harness adapter in both directions, decoding TOML into tagged JSON and encoding tagged JSON back into TOML, and it also validates documents. Install it with Go itself, no release assets involved:

go install sourcedock.dev/petrbalvin/interpres/v2/cmd/interpres-decode@latest

Synopsis

interpres-decode [flags]
interpres-decode -encode
interpres-decode -validate [file ...]
interpres-decode -validate [directory ...]
interpres-decode -json
interpres-decode -struct
interpres-decode -schema TYPE file.go
interpres-decode -version

Without -validate, -encode, -json or -struct the program is the decoding half of the toml-test adapter: it takes no arguments, reads one TOML document from stdin, and writes the toml-test tagged-JSON form to stdout. Build it locally with just build, which compiles it into bin/interpres-decode, or run it straight from the module directory with just run.

With -encode the direction is reversed: the program reads a tagged-JSON description from stdin and writes the TOML document it describes to stdout, which is the shape toml-test expects of an encoder command. It takes no arguments either, and the mode flags cannot be combined.

With -validate the program parses each named file instead, or stdin when no file is named, and prints one line per invalid document to stderr. It is quiet on valid documents, which is the shape a CI step wants. The - name means stdin. A named directory is walked for .toml files, every one of them validated, and the walk closes with a summary on stderr naming how many documents were checked and how many were invalid.

With -json the decoding half prints plain indented JSON instead of the tagged form, the shape for people and diffs: the values keep their types as JSON sees them, and the date-time wrappers print in their TOML form.

With -struct the program reads a TOML document from stdin and prints a Go struct definition shaped like it: one field per key in written order, nested tables as nested struct types, and an array of tables as a slice. The printed type compiles and decodes the document it came from.

With -schema the program reads a Go source file and writes a TOML template for the named struct type: one key per exported field, the comment= tag option printed as a comment above it, and the default= option as the value where one is set. It is the inverse of -struct, for config-driven applications that generate their example configuration from the type.

-version prints the binary's version and exits. The release pipeline builds at the tag, so a released binary prints its own tag; a build from a working tree prints (devel).

Flags

Flag Effect
-validate validate the documents instead of emitting tagged JSON; directories are walked for .toml files
-encode read tagged JSON from stdin and write TOML instead
-json with the default mode, print plain indented JSON instead of tagged JSON
-struct infer a Go struct definition from the document on stdin and print it
-schema TYPE write a TOML template for the struct type TYPE from the Go source file named as the first argument
-version print the version and exit
-h print the usage

Exit codes

Code Meaning
0 adapter: the document parsed and the tagged JSON was written; encode: the TOML was written; validate: every document parsed; schema, struct, version: the output was written
1 adapter: parse error; validate: at least one document is invalid
2 a usage error, a read failure, malformed tagged JSON, or a value with no TOML representation

Wire format

Tables become JSON objects, arrays become JSON arrays, and every scalar is wrapped in an object with a type and a value:

{
  "title": {"type": "string", "value": "hello"},
  "port": {"type": "integer", "value": "9090"},
  "enabled": {"type": "bool", "value": "true"},
  "ratio": {"type": "float", "value": "3.14"}
}
TOML value Tag Rendering
string string the string verbatim
integer integer decimal
float float decimal, or inf, -inf, nan
boolean bool true or false
offset date-time datetime RFC 3339 with nanoseconds
local date-time datetime-local 1979-05-27T07:32:00
local date date-local 1979-05-27
local time time-local 07:32:00.999999

The -encode mode reads exactly this form back. Two properties of it are worth knowing. A float whose value has no fraction and no exponent is written as a bare integer string, {"type": "float", "value": "1"}, so there the tag decides the type and not the literal. And the form cannot tell an array of tables from a value array of inline tables, so the adapter writes the header form, [[a]], for an array whose every element is a JSON object; a mixed array keeps the value form.

Examples

Echo a small document through the adapter:

echo 'title = "hello"
[server]
host = "127.0.0.1"
port = 9090
' | ./bin/interpres-decode

The output is the equivalent value tree as one JSON object. Turn a description back into TOML with -encode:

echo '{"title": {"type": "string", "value": "hello"}}' | ./bin/interpres-decode -encode
title = "hello"

Validate the TOML files of another repository in CI:

interpres-decode -validate config.toml deploy/example.toml

An invalid document reports the file and the library's line number:

$ interpres-decode -validate bad.toml
bad.toml: interpres: line 1: expected a value
$ echo $?
1

Sweep a whole directory tree of configuration, with the summary the walk closes on:

$ interpres-decode -validate configs/
configs/old.toml: interpres: line 3: duplicate key "port"
checked 14 documents, 1 invalid
$ echo $?
1

See the document a -struct template would decode:

echo 'host = "db"
port = 5432
' | ./bin/interpres-decode -struct
type inferred struct {
	Host string `toml:"host"`
	Port int64  `toml:"port"`
}

Write the template back from the type, comments and defaults included, where the Go source declares fields tagged toml:"host,comment=The host to dial,default=example.org":

./bin/interpres-decode -schema Config config.go
# The host to dial
host = "example.org"

Print the binary's version:

$ ./bin/interpres-decode -version
interpres-decode v2.0.0

Run the official compliance suite against the adapter:

just toml-test

That recipe needs the toml-test binary on PATH, installed with go install github.com/toml-lang/toml-test/v2/cmd/toml-test@v2.2.0. It runs the suite in both directions: the decoder against the valid and invalid corpora, and the encoder against the tagged JSON of the valid one. The full reference for the library itself is API.md.