Command line
bafi -i INPUT -t TEMPLATE [-o OUTPUT]
COMMAND | bafi -f FORMAT -t TEMPLATE
bafi -h prints the same overview with all flags.
Flags
| Flag | Meaning |
|---|---|
-i file |
Input file. Without -i, bafi reads standard input (a pipe or < file). -i '?list.yaml' reads several files. |
-t template |
Template file, or an inline template starting with ?: -t '?{{toJSON .}}'. |
-o file |
Output file. Without -o, the result goes to standard output. |
-f format |
Input format: json, bson, yaml, csv, xml, mt940. Default: from the -i file extension. Required for standard input. |
-d delimiter |
CSV delimiter: one character (-d ';') or a hex byte (-d 0x09 for TAB). Default ,. For MT940, the separator between messages. |
-strict |
Fail on a key that is missing from the input instead of printing <no value>. |
-v |
Print the version. |
-h |
Print help. |
-gq question |
Ask OpenAI about the input instead of using a template. See Ask OpenAI. |
-gk key |
OpenAI API key. Default: the OPENAI_API_KEY environment variable (preferred). |
-gm model |
OpenAI model: gpt35 (default), gpt4, gpt4o, gpt4o-mini, gpt5, gpt5mini, gpt5nano. |
Flags must come before any other argument.
Input
bafi -i testdata.xml -t '?{{index .TOP_LEVEL "-description"}}'
employeeData
The format is taken from the extension: .json, .bson, .yaml/.yml, .csv, .xml (also .cdf,
.cdf3), .sta (MT940). -f overrides it. Standard input has no name, so -f is required:
curl -fs https://example.com/api/users | bafi -f json -t users.tmpl
Redirecting a file works the same way:
{"users": [{"name": "Alice"}, {"name": "Bob"}]}
bafi -f json -t '?{{len .users}} users' < users.json
2 users
A single - after the flags, the usual "read standard input" marker, is accepted and changes nothing.
A UTF-8 byte order mark at the start of the input is ignored.
Several input files
-i '?list.yaml' reads every file named in a YAML list and makes each available under its label (quote it: zsh, the macOS
default shell, treats an unquoted ? as a wildcard):
- file: rates.xml
label: RATES # {{ .RATES }}
- file: orders.json
label: ORDERS
format: json # optional; the extension decides when omitted
-f is ignored in this mode; -d applies to every CSV file. Full example:
Merge several files into one output.
Templates on the command line
An inline template starts with ?. Quote it so the shell passes it as one argument:
| Shell | Example |
|---|---|
| bash, zsh | bafi -i data.json -t '?{{toXML .}}' |
| PowerShell | .\bafi.exe -i data.json -t "?{{toXML .}}" |
| cmd.exe | bafi.exe -i data.json -t "?{{toXML .}}" |
Inside single quotes, template strings use double quotes: -t '?{{index . "my-key"}}'. A template
file avoids quoting issues altogether: -t report.tmpl. The template guide explains the
syntax.
Output
The result goes to standard output unless -o names a file. bafi renders the whole result first: when
a template fails, standard output stays empty and an existing -o file is left as it was, so a pipe
never receives half a document and a scheduled job keeps its last good report.
Append to a file with the shell:
bafi -i testdata.xml -t template.tmpl >> output.txt
Errors, warnings and exit codes
Errors and warnings go to standard error, never into the output. An error names the file and line, shows the problem and suggests a fix; see Troubleshooting.
| Exit code | Meaning |
|---|---|
0 |
Success (warnings may have been printed). |
1 |
The input, the template, the output file or the OpenAI request failed. |
2 |
The command line is wrong: missing template or input, unknown flag or format. |
Warnings do not change the output or the exit code:
- the output contains
<no value>because the template used a key the input does not have; - a CSV header ended up as a single column, which usually means the wrong
-d.
Strict mode
-strict turns a missing key into an error with the key name and the template line, instead of
printing <no value>:
bafi -i testdata.xml -strict -t '?{{.TOP_LEVEL.DATA_LINES}}'
bafi: template error in the inline template (line 1, column 3)
1 | {{.TOP_LEVEL.DATA_LINES}}
| ^
map has no entry for key "DATA_LINES" (at <.TOP_LEVEL.DATA_LINES>)
hint: the input has no key "DATA_LINES" here (-strict is on); check spelling and case - XML attributes start with "-" (index . "-id"); for keys that may be absent use {{with index . "DATA_LINES"}}...{{end}}
docs: https://mmalcek.github.io/bafi/troubleshooting/#missing-keys-and-no-value
Use it while writing a template, and in automation where a missing field must not go unnoticed.
For keys that may legitimately be absent, use index: {{with index . "nickname"}}{{.}}{{end}}.