{"record":{"id":"87a27c38f1acad15","repo":"laurent22/joplin","slug":"shortcuts-are-not-available-in-cli-mode","errorCode":null,"errorMessage":"Shortcuts are not available in CLI mode.","messagePattern":"Shortcuts are not available in CLI mode\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/app-cli/app/command-help.ts","lineNumber":44,"sourceCode":"\n\t\toutput.sort((a, b) => (a.name() < b.name() ? -1 : +1));\n\n\t\treturn output;\n\t}\n\n\tpublic override async action(args: { command?: string }) {\n\t\tconst stdoutWidth = app().commandStdoutMaxWidth();\n\n\t\tif (args.command === 'shortcuts' || args.command === 'keymap') {\n\t\t\tthis.stdout(_('For information on how to customise the shortcuts please visit %s', 'https://joplinapp.org/help/apps/terminal#shortcuts'));\n\t\t\tthis.stdout('');\n\n\t\t\tif (\n\t\t\t\tapp()\n\t\t\t\t\t.gui()\n\t\t\t\t\t.isDummy()\n\t\t\t) {\n\t\t\t\tthrow new Error(_('Shortcuts are not available in CLI mode.'));\n\t\t\t}\n\n\t\t\tconst keymap = app()\n\t\t\t\t.gui()\n\t\t\t\t.keymap();\n\n\t\t\tconst rows = [];\n\n\t\t\tfor (let i = 0; i < keymap.length; i++) {\n\t\t\t\tconst item = keymap[i];\n\t\t\t\tconst keys = item.keys.map((k: string) => (k === ' ' ? '(SPACE)' : k));\n\t\t\t\trows.push([keys.join(', '), item.command]);\n\t\t\t}\n\n\t\t\tcliUtils.printArray(this.stdout.bind(this), rows);\n\t\t} else if (args.command === 'all') {\n\t\t\tconst commands = this.allCommands();\n\t\t\tconst output = commands.map(c => renderCommandHelp(c));","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-cli/app/command-help.ts#L26-L62","documentation":"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.","triggerScenarios":"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()`).","commonSituations":"CI/scripted calls to `joplin help keymap` expecting structured output; users exploring the CLI from a non-interactive shell.","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)"],"exampleFix":"// before (one-shot CLI)\njoplin help shortcuts   // throws: Shortcuts are not available in CLI mode.\n\n// after\n# option A: read the docs URL the command prints\n# option B: read the keymap file directly\ncat ~/.config/joplin-dev-desktop/keymap.json\n# option C: launch interactive mode (no command arg) and run :help shortcuts","handlingStrategy":"validation","validationCode":"import app from './app';\n\nfunction assertInteractiveGuiForShortcuts(): void {\n  if (!app().hasGui() || app().gui().isDummy()) {\n    throw new Error('Shortcuts/keymap require the interactive terminal GUI. See https://joplinapp.org/help/apps/terminal#shortcuts');\n  }\n}\n\n// or read the keymap file directly instead of going through `help keymap`:\n// `${Setting.value('profileDir')}/keymap.json`","typeGuard":"const hasRealKeymap = (): boolean =>\n  app().hasGui() && !app().gui().isDummy() && typeof app().gui().keymap === 'function';","tryCatchPattern":null,"preventionTips":["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"],"tags":["cli","gui","keymap","mode","interactive-only"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}