laurent22/joplin · warning · Error
Shortcuts are not available in CLI mode.
Error message
Shortcuts are not available in CLI mode.
What it means
Thrown by `help shortcuts` (or `help keymap`) when the GUI is a dummy. The CLI runs in two modes: interactive GUI (`app-gui.ts`, real keymap) and one-shot CLI (`dummyGui()`, `isDummy() === true`). Keymaps only exist in the interactive GUI; the one-shot CLI has no keymap, so printing one is impossible. The message above the throw still helpfully points to the online docs URL.
Source
Thrown at packages/app-cli/app/command-help.ts:44
output.sort((a, b) => (a.name() < b.name() ? -1 : +1));
return output;
}
public override async action(args: { command?: string }) {
const stdoutWidth = app().commandStdoutMaxWidth();
if (args.command === 'shortcuts' || args.command === 'keymap') {
this.stdout(_('For information on how to customise the shortcuts please visit %s', 'https://joplinapp.org/help/apps/terminal#shortcuts'));
this.stdout('');
if (
app()
.gui()
.isDummy()
) {
throw new Error(_('Shortcuts are not available in CLI mode.'));
}
const keymap = app()
.gui()
.keymap();
const rows = [];
for (let i = 0; i < keymap.length; i++) {
const item = keymap[i];
const keys = item.keys.map((k: string) => (k === ' ' ? '(SPACE)' : k));
rows.push([keys.join(', '), item.command]);
}
cliUtils.printArray(this.stdout.bind(this), rows);
} else if (args.command === 'all') {
const commands = this.allCommands();
const output = commands.map(c => renderCommandHelp(c));View on GitHub (pinned to 2654b33620)
Solutions
- Visit the URL printed just before the throw: https://joplinapp.org/help/apps/terminal#shortcuts
- Launch the interactive terminal GUI (run `joplin` with no command args) and press the relevant keys, then run `:help shortcuts` inside it
- If you need keymap data programmatically, read `<profileDir>/keymap.json` directly (falling back to defaults from app.ts:loadKeymaps)
Example fix
// before (one-shot CLI) joplin help shortcuts // throws: Shortcuts are not available in CLI mode. // after # option A: read the docs URL the command prints # option B: read the keymap file directly cat ~/.config/joplin-dev-desktop/keymap.json # option C: launch interactive mode (no command arg) and run :help shortcuts
Defensive patterns
Strategy: validation
Validate before calling
import app from './app';
function assertInteractiveGuiForShortcuts(): void {
if (!app().hasGui() || app().gui().isDummy()) {
throw new Error('Shortcuts/keymap require the interactive terminal GUI. See https://joplinapp.org/help/apps/terminal#shortcuts');
}
}
// or read the keymap file directly instead of going through `help keymap`:
// `${Setting.value('profileDir')}/keymap.json` Type guard
const hasRealKeymap = (): boolean => app().hasGui() && !app().gui().isDummy() && typeof app().gui().keymap === 'function';
Prevention
- Don't script `help keymap`/`help shortcuts` in non-interactive CI
- Read `<profileDir>/keymap.json` for programmatic access
- Link users to the online docs URL rather than the CLI subcommand
When it happens
Trigger: Running `joplin help shortcuts` or `joplin help keymap` as a one-shot CLI invocation (argv passed to the binary). The check `app().gui().isDummy()` is true in this path (app.ts:413 sets `this.gui_ = this.dummyGui()`).
Common situations: CI/scripted calls to `joplin help keymap` expecting structured output; users exploring the CLI from a non-interactive shell.
Related errors
- More than one item match "%s". Please narrow down your query
- Cannot find "%s".
- No notebook selected.
- No notebook has been specified.
- The command "%s" is only available in GUI mode
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/87a27c38f1acad15.
Report an issue: GitHub.