A VSCode extension that runs tasks defined in .vscode/tasks.json with
interactive parameter prompts — serial port pickers, file dialogs, and
validated text input — tailored for firmware development workflows.
Features
- Activity bar view that lists tasks defined in the workspace (
.vscode/tasks.json) - Run / terminate / restart tasks directly from the tree
- Favorite frequently used tasks
- Interactive input commands usable from the standard
inputsarray oftasks.json:- Auto-detected serial port picker (
pickSerialPort) - Validated text prompt (
promptInput) - File / folder pickers (
pickFile,pickFolder) - Dynamic list picker (
pickFromList)
- Auto-detected serial port picker (
- Pre-configure inputs without running: a gear icon ⚙️ next to tasks with
${input:...}variables opens the input UI without launching the task; the selected values are stored and reused on the next ▶ run (no re-prompt). Current values appear as a description next to the task name (e.g.flash port=/dev/cu.usbserial · cfg=debug). - Remembers the last value entered per task and prefills it on the next run
Input commands
Use these commands as "type": "command" inputs in your tasks.json.
| Command | Purpose | Args |
|---|---|---|
firmware-task.pickSerialPort |
Auto-detects and lets the user pick a serial port. Falls back to manual entry if none detected. | placeholder, filter (regex) |
firmware-task.promptInput |
Free-form text prompt. | prompt, placeholder, value, password, validateRegex, validateMessage |
firmware-task.pickFile |
File picker (showOpenDialog). |
title, openLabel, filters, defaultUri, canSelectMany, relative |
firmware-task.pickFolder |
Folder picker. | title, openLabel, defaultUri, relative |
firmware-task.pickFromList |
QuickPick over a custom list. | items (string[] or {label,value,description}[]), placeholder |
Example tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "Serial Monitor",
"type": "shell",
"command": "pyserial-miniterm ${input:port} ${input:baud}"
},
{
"label": "Flash Firmware",
"type": "shell",
"command": "openocd -f interface/stlink.cfg -c 'program ${input:bin} verify reset exit'"
}
],
"inputs": [
{ "id": "port", "type": "command", "command": "firmware-task.pickSerialPort" },
{
"id": "baud",
"type": "command",
"command": "firmware-task.promptInput",
"args": { "prompt": "Baud rate", "value": "115200", "validateRegex": "^\\d+$" }
},
{
"id": "bin",
"type": "command",
"command": "firmware-task.pickFile",
"args": { "filters": { "Firmware": ["bin", "hex", "elf"] } }
}
]
}
Variables (${input:port}, etc.) are substituted by Firmware Task Manager when
you launch the task from its tree view. Standard VSCode promptString and
pickString input types are also supported.
Run in an existing terminal
VSCode tasks always spawn a fresh task terminal, which does not inherit the
environment of a terminal you already set up (e.g. an ESP-IDF terminal where
export.sh / export.ps1 was sourced). To reuse such a terminal, add
"runInActiveTerminal": true to the task. When set, running the task types
the command into a terminal instead of launching a new task terminal:
{
"label": "build",
"type": "shell",
"command": "idf.py build",
"runInActiveTerminal": true, // type into a terminal instead of a new task terminal
"terminalName": "ESP-IDF" // optional: always target this named terminal (created if missing)
}
Terminal selection priority:
terminalNamegiven → the terminal with that exact name (created if none exists). Use this to pin sends to one terminal when several are open.- Otherwise → the active terminal.
- If no terminal is open → a new one is created with the default profile (so a configured terminal profile, e.g. one that sources the IDF environment, still applies).
The command is sent with a trailing newline, so it executes immediately.
Notes / limitations:
runInActiveTerminalandterminalNameare custom keys, so VSCode's editor may flag them with a "not allowed" warning. This is cosmetic — the extension reads them directly fromtasks.jsonand they work regardless.- Commands sent this way are not tracked as VSCode task executions: the tree's
running indicator, Terminate, Restart, and the running-count badge do not
apply to them.
${input:...}substitution is still applied.
Build shortcut (Ctrl/Cmd+Shift+B)
VSCode's Run Build Task shortcut runs the default build task through its
native task system, which bypasses this extension — so runInActiveTerminal
would be ignored. To fix that, mark your build task as the default build task and
add runInActiveTerminal:
{
"label": "idf-build",
"type": "shell",
"command": "idf.py build",
"runInActiveTerminal": true,
"group": { "kind": "build", "isDefault": true }
}
When a workspace contains a default build task (group.kind = "build",
isDefault = true) with runInActiveTerminal: true, the extension reroutes
the build shortcut to itself so the command is sent to your terminal:
- macOS:
Cmd+Shift+B· Windows / Linux:Ctrl+Shift+B(matches the native bindings). - The override is scoped by the
firmwareTask.hasBuildInTerminalcontext key — it only takes effect in workspaces that actually have such a task. Other projects keep the normal VSCode build behavior. ${input:...}is resolved exactly like a tree-view run. (Remembered input values are cached per task; values entered via the tree are not shared with the shortcut path, so the first shortcut run of an input-bearing task may prompt once.)
Configuration
| Setting | Default | Description |
|---|---|---|
firmwareTask.showOnlyWorkspaceTasks |
true |
Show only tasks defined in .vscode/tasks.json. Set to false to also show auto-detected tasks (CMake, npm, tsc, etc.). |
firmwareTask.rememberInputs |
true |
Remember last entered input values per task and prefill on subsequent runs. |
firmwareTask.serialPortFilter |
"" |
Regex applied to detected serial port device names. |
firmwareTask.exclude |
null |
Regex pattern for excluding tasks by name. |
firmwareTask.collapseLargeTaskTree |
true |
Collapse top-level groups when there are more than three groups and more than 30 tasks. |
firmwareTask.taskSortOrder |
"label" |
Sort order: "label", "group", or "provider". |
firmwareTask.favorites |
[] |
Saved favorite task ids (workspace settings). |
Installation (local VSIX)
pnpm install
pnpm run vsix
# → dist-vsix/firmware-task-manager-1.0.0.vsix
Install it in VSCode via Extensions: Install from VSIX... in the command palette, or from the CLI:
code --install-extension dist-vsix/firmware-task-manager-1.0.0.vsix
Development
pnpm install
pnpm run watch # rolldown + tsc in watch mode
# Press F5 in VSCode to launch the Extension Development Host
Credits
This extension is based on cnshenj/vscode-task-manager, with modifications focused on firmware development workflows (serial port picking, file dialogs, per-task remembered inputs, copy-command-line action, etc.).
License
MIT