laurent22/joplin · error · Error
Reading commands from standard input is only available in…
Error message
Reading commands from standard input is only available in CLI mode.
What it means
The 'batch' command reads a command script from a file or, when the path is '-', from standard input. Because the interactive terminal GUI also reads from stdin, reading commands from stdin conflicts with the GUI; if app().hasGui() is true the command throws 'Reading commands from standard input is only available in CLI mode.'. The message is i18n-translated.
Solutions
- Write the commands to a file and run 'batch <file>' instead of stdin.
- Run in pure CLI mode (no terminal GUI) when piping via stdin.
- Use the data API or a single 'exec' call instead of batch stdin in GUI mode.
Example fix
# before # echo 'ls' | joplin batch - # inside terminal GUI -> throws # after # printf 'ls\n' > /tmp/cmds.txt && joplin batch /tmp/cmds.txt
Defensive patterns
Strategy: validation
Validate before calling
if (filePath === '-' && app().hasGui()) {
throw new Error('Stdin batch input requires CLI mode; write to a file instead.');
} Prevention
- Prefer a script file over stdin for batch in any environment that may have a GUI.
- Detect hasGui() before piping commands via stdin.
- Use the data API for programmatic multi-command runs in GUI mode.
When it happens
Trigger: Running 'batch -' (or piping commands into stdin) while inside the interactive terminal GUI, where stdin is already owned by the GUI input loop.
Common situations: Piping a command list ('echo ... | joplin batch -') in a mode where the terminal GUI is active; running batch from a keybinding inside the GUI.
Related errors
- The command " " is only available in GUI mode
- Cannot change encrypted item
- Cannot find " ".
- Cannot find " ".
- Cannot find " ".
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/b46fdcea483b5801.
Report an issue: GitHub.
Appendix: source
Thrown at packages/app-cli/app/command-batch.ts:45
public description() {
return _('Runs the commands contained in the text file. There should be one command per line.');
}
private streamCommands_ = async function*(filePath: string) {
const processLines = function*(lines: string) {
const commandLines = splitCommandBatch(lines);
for (const command of commandLines) {
if (!command.trim()) continue;
yield splitCommandString(command.trim());
}
};
if (filePath === '-') { // stdin
// Iterating over standard input conflicts with the CLI app's GUI.
if (app().hasGui()) {
throw new Error(_('Reading commands from standard input is only available in CLI mode.'));
}
for await (const lines of iterateStdin('command> ')) {
yield* processLines(lines);
}
} else {
const data = await readFile(filePath, 'utf-8');
yield* processLines(data);
}
};
public async action(options: Options) {
let lastError;
for await (const command of this.streamCommands_(options['file-path'])) {
try {
await app().refreshCurrentFolder();
await app().execCommand(command);
} catch (error) {View on GitHub (pinned to 2654b33620)