2026-08-19 18:44:00 +02:00
# Command line
2026-09-17 21:23:29 +02:00
The reference below is taken from the program itself. `interpres-decode` is
2026-09-19 11:38:19 +02:00
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.
2026-09-22 21:15:07 +02:00
The same reference ships as the manual page `man/interpres-decode.1` .
2026-09-19 11:38:19 +02:00
Install it with Go itself, no release assets involved:
2026-09-17 21:23:29 +02:00
```sh
2026-09-19 00:14:39 +02:00
go install sourcedock.dev/petrbalvin/interpres/v2/cmd/interpres-decode@latest
2026-09-17 21:23:29 +02:00
```
2026-08-19 18:44:00 +02:00
## Synopsis
```sh
2026-09-17 21:23:29 +02:00
interpres-decode [ flags]
2026-09-22 21:15:07 +02:00
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
2026-08-19 18:44:00 +02:00
```
2026-09-22 21:15:07 +02:00
Without `--validate` , `--encode` , `--json` , `--struct` or `--schema` 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
2026-09-22 00:55:02 +02:00
`bin/interpres-decode` , or run it straight from the module directory with
`just run` .
2026-09-19 11:38:19 +02:00
2026-09-22 21:15:07 +02:00
With `--encode` the direction is reversed: the program reads a tagged-JSON
2026-09-19 11:38:19 +02:00
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
2026-09-22 00:55:02 +02:00
arguments either, and the mode flags cannot be combined.
2026-09-17 21:23:29 +02:00
2026-09-22 21:15:07 +02:00
With `--validate` the program parses each named file instead, or stdin when no
2026-09-17 21:23:29 +02:00
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
2026-09-22 00:55:02 +02:00
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.
2026-09-22 21:15:07 +02:00
With `--json` the decoding half prints plain indented JSON instead of the
2026-09-22 00:55:02 +02:00
tagged form, the shape for people and diffs: the values keep their types as
2026-09-22 21:15:07 +02:00
JSON sees them, and the date-time wrappers print in their TOML form. The flag
shapes the decoding output only, so it is rejected together with the mode
flags.
2026-09-22 00:55:02 +02:00
2026-09-22 21:15:07 +02:00
With `--struct` the program reads a TOML document from stdin and prints a Go
2026-09-22 00:55:02 +02:00
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.
2026-09-22 21:15:07 +02:00
With `--schema` the program reads a Go source file and writes a TOML template
2026-09-22 00:55:02 +02:00
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
2026-09-22 21:15:07 +02:00
where one is set. It is the inverse of `--struct` , for config-driven
2026-09-22 00:55:02 +02:00
applications that generate their example configuration from the type.
2026-09-22 21:15:07 +02:00
`--version` prints the binary's version and exits. The release pipeline builds
2026-09-22 00:55:02 +02:00
at the tag, so a released binary prints its own tag; a build from a working
tree prints `(devel)` .
2026-09-17 21:23:29 +02:00
## Flags
| Flag | Effect |
|---|---|
2026-09-22 21:15:07 +02:00
| `--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 |
| `--help` | print the usage |
2026-08-19 18:44:00 +02:00
## Exit codes
| Code | Meaning |
|---|---|
2026-09-22 00:55:02 +02:00
| `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 |
2026-09-22 21:15:07 +02:00
| `1` | adapter: parse error; validate: at least one document is invalid; struct: the document on stdin failed to parse |
| `2` | a usage error, a read or write failure, malformed tagged JSON, or a value with no TOML representation |
2026-08-19 18:44:00 +02:00
## Wire format
Tables become JSON objects, arrays become JSON arrays, and every scalar is
wrapped in an object with a `type` and a `value` :
```json
{
"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` |
2026-09-22 21:15:07 +02:00
The `--encode` mode reads exactly this form back. Two properties of it are
2026-09-19 11:38:19 +02:00
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.
2026-08-19 18:44:00 +02:00
## Examples
Echo a small document through the adapter:
```sh
echo 'title = "hello"
[server]
host = "127.0.0.1"
port = 9090
' | ./bin/interpres-decode
```
2026-09-19 11:38:19 +02:00
The output is the equivalent value tree as one JSON object. Turn a description
2026-09-22 21:15:07 +02:00
back into TOML with `--encode` :
2026-09-19 11:38:19 +02:00
```sh
2026-09-22 21:15:07 +02:00
echo '{"title": {"type": "string", "value": "hello"}}' | ./bin/interpres-decode --encode
2026-09-19 11:38:19 +02:00
```
```toml
title = "hello"
```
Validate the TOML files of another repository in CI:
2026-09-17 21:23:29 +02:00
```sh
2026-09-22 21:15:07 +02:00
interpres-decode --validate config.toml deploy/example.toml
2026-09-17 21:23:29 +02:00
```
An invalid document reports the file and the library's line number:
```sh
2026-09-22 21:15:07 +02:00
$ interpres-decode --validate bad.toml
interpres-decode: bad.toml: interpres: line 1: expected a value
2026-09-17 21:23:29 +02:00
$ echo $?
1
```
2026-09-22 00:55:02 +02:00
Sweep a whole directory tree of configuration, with the summary the walk
closes on:
```sh
2026-09-22 21:15:07 +02:00
$ interpres-decode --validate configs/
interpres-decode: configs/old.toml: interpres: line 3: duplicate key "port"
2026-09-22 00:55:02 +02:00
checked 14 documents, 1 invalid
$ echo $?
1
```
2026-09-22 21:15:07 +02:00
See the document a `--struct` template would decode:
2026-09-22 00:55:02 +02:00
```sh
echo 'host = "db"
port = 5432
2026-09-22 21:15:07 +02:00
' | ./bin/interpres-decode --struct
2026-09-22 00:55:02 +02:00
```
```go
2026-09-22 21:15:07 +02:00
// Generated by interpres-decode --struct; decode with
// sourcedock.dev/petrbalvin/interpres/v2.
2026-09-22 00:55:02 +02:00
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"` :
```sh
2026-09-22 21:15:07 +02:00
./bin/interpres-decode --schema Config config.go
2026-09-22 00:55:02 +02:00
```
```toml
# The host to dial
host = "example.org"
```
Print the binary's version:
```sh
2026-09-22 21:15:07 +02:00
$ ./bin/interpres-decode --version
2026-09-22 00:55:02 +02:00
interpres-decode v2.0.0
```
2026-09-17 21:23:29 +02:00
Run the official compliance suite against the adapter:
2026-08-19 18:44:00 +02:00
```sh
just toml-test
```
That recipe needs the `toml-test` binary on `PATH` , installed with
2026-09-19 11:38:19 +02:00
`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
2026-08-19 18:44:00 +02:00
reference for the library itself is [API.md ](API.md ).