bt, the command line
A headless command line that translates text, one file or a folder of files through the same engine the window uses. It needs neither the window nor the agent endpoint, and it starts its own gateway.
What bt is
An executable named bt, built on .NET 10, described in the product's own documentation as the headless command line for scripts. It is headless in the strict sense: it does not need the application window running, and it does not need the agent endpoint enabled.
It is produced by the publish step and carried inside the shipped application, and the build fails if that copy is missing beside the published application: cli\bt.exe
Invocation
bt <command> [options]
As a first argument, help and the version each have their own switches. Inside a command, the help switches print that command's own help. Note that the bare word help is accepted but is not one of the four commands.
bt --help bt -h bt -? bt help
bt --version bt -v
bt translate --help
Run with no arguments at all, it prints the root help and exits successfully.
The four commands
There are exactly four. An unknown command is refused with a message naming all four.
| Command | What it does |
|---|---|
| translate | Translate text, one file, or a folder of files. |
| languages | List the languages the selected model can translate. |
| models | List installed models, or select one. |
| mcp | Serve the agent tools over standard input and output. |
Options
Six options take a value: --from --to --file --batch --out --select
Four are switches: --json --quiet (-q) --overwrite --memory
A valued option accepts either spelling, so a space or an equals sign parse to the same thing. A target language is required for a translation, and the source language defaults to English. An option given without a usable value is refused by name, and so is an option that does not exist.
One option is refused deliberately rather than being absent. Both spellings are rejected before any value is read, with the reason that index scope is chosen in the application and this command line cannot narrow it: --context-dir
Translating text
Text is passed as a plain argument, or piped in on standard input when no text argument is given. Standard input is read only when it is redirected, so a run with neither fails and says so rather than waiting for something that will never arrive.
Text, a file and a folder are mutually exclusive, each with its own message. The languages command takes no file, no folder and no free arguments.
Files and folders
Use the file option for one file and the batch option for a folder. The output option chooses the destination, which is an output file for a single file and an output folder for a batch.
The default output is written beside the input with the target language in the name. So readme.md translated to Czech becomes readme.cs.md, while a PDF or a DOCX comes back as text instead, for example terms.pdf.cs.txt
A batch covers the files directly inside the named folder, ordered by full path, case insensitively. It does not descend into subfolders. A folder holding nothing translatable is an error rather than a silent success.
An existing output file is never silently replaced. Overwriting is opt in: --overwrite
Memory scope differs by path. The memory switch is an opt in for text. A file or a folder always translates with memory on, because a file is always translated against the project it belongs to.
Output discipline
Standard output carries the result or the JSON envelope. Everything else goes to standard error. Nothing ever prompts. The console encoding is UTF-8 without a byte order mark.
In human readable mode, languages print code, name and availability in fixed columns; models print a marker for selected and installed, then the name and the file; a batch prints one line per file with its outcome; and a single file run prints only the output path.
The JSON envelope
With the JSON switch, exactly one envelope is written to standard output and nothing else. Progress notes are suppressed. There are five shapes:
text { ok, from, to, model, result, note }
files { ok, results[] { file, status, out, error } }
languages { ok, languages[] { code, name, endonym, availability } }
models { ok, models[] { name, file, path, installed, selected } }
failure { ok: false, error { code, message } }
The switch is detected anywhere in the argument list before the command is resolved, which is what lets an unknown command still answer with a failure envelope rather than plain text.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success. |
| 2 | Usage or argument error. |
| 3 | Input file missing or unreadable. |
| 4 | Model runtime unreachable. |
| 5 | Translation failed or incomplete. |
The same block is interpolated into all five help screens. A fault with no arm of its own, such as an unsupported format or an output file that already exists, reports a usage error.
Worked examples
bt translate "Save the document" --from en --to cs
bt translate --file README.md --to cs
bt translate --batch .\docs --to de --out .\docs\de
bt languages
bt models
bt models --select EuroLLM
bt mcp
Selecting a model
A model is chosen by name, by file name or by full path, case insensitively. The choice is stored and holds from then on: bt models --select <name>
An unknown name is answered with the list of installed models. With nothing installed at all, the message points at the application's Downloads screen instead.
Serving the agent tools
The mcp command speaks the protocol on standard output, so the JSON switch is refused with a message of its own. No port is opened and nothing listens.
The first line on standard error is a banner naming the version, the build time and the path of the executable that answered, which is what lets a client reporting a closed connection be diagnosed as a stale binary. The agent tool surface