Guide
Automate Build and Test Workflows with VS Code Tasks
Set up VS Code tasks.json to compile TypeScript, run tests, and surface errors in the Problems view — all behind Ctrl+Shift+B. Includes cross-platform shell setup, problemMatcher wiring, and dependsOn chaining.
Published by Tasadduq Burney
19 Sept 2026, 18:38 UTC
3 min57.7K views0

Desired Outcome
Configure a project-specific .vscode/tasks.json that compiles TypeScript, runs tests, and surfaces compiler errors directly in the Problems view — all invokable via Ctrl+Shift+B or the Command Palette.
Prerequisites
- VS Code 1.80 or later (task API stable since 1.14).
- A Node.js project with
typescriptand a test runner (e.g.,vitestorjest) installed as dev dependencies. - Terminal access to verify that
npx tsc --versionandnpx vitest --versionexecute without PATH errors.
Create the Tasks Configuration
Open the Command Palette (Ctrl+Shift+P), run Tasks: Configure Task, and select Create tasks.json file from template → Others. Replace the generated file with the following configuration tailored for a TypeScript + Vitest project:
{
"version": "2.0.0",
"tasks": [
{
"label": "tsc: compile",
"type": "shell",
"command": "npx",
"args": ["tsc", "--noEmit", "--pretty", "false"],
"group": "build",
"problemMatcher": ["$tsc"]
},
{
"label": "vitest: run",
"type": "shell",
"command": "npx",
"args": ["vitest", "run", "--reporter=verbose"],
"group": "test",
"problemMatcher": []
},
{
"label": "build",
"group": {
"kind": "build",
"isDefault": true
},
"dependsOn": ["tsc: compile", "vitest: run"],
"problemMatcher": []
}
]
}
Key Properties Explained
| Property | Purpose |
|---|---|
type": "shell" | Runs the command through the integrated terminal (cross-platform). Avoid hardcoding bash or powershell.exe. |
command": "npx" | Uses the local project binaries, avoiding global PATH surprises. |
problemMatcher": ["$tsc"] | Built-in matcher that parses TypeScript compiler output into the Problems panel. |
group": { "kind": "build", "isDefault": true } | Binds the composite build task to Ctrl+Shift+B. |
dependsOn | Runs tsc: compile then vitest: run sequentially; failure in the first aborts the chain. |
Run and Verify
- Press Ctrl+Shift+B. The Integrated Terminal should open, showing
npx tsc --noEmit ...followed by the Vitest run. - Introduce a deliberate type error in a
.tsfile (e.g.,const x: number = "oops"). Re-run the build task. - Open the Problems panel (Ctrl+Shift+M). The TypeScript error should appear with file, line, and message — click to jump to the source.
- Run the test task alone: Command Palette → Tasks: Run Task →
vitest: run. Confirm test output appears in the terminal without polluting the Problems view (no matcher attached).
Cross-Platform Considerations
- Because
type": "shell"delegates to the user's default shell (bash/zsh on Linux/macOS, PowerShell on Windows), the sametasks.jsonworks across OSes. - If you must invoke a platform-specific executable, use
"windows": { "command": "..." }, "linux": { "command": "..." }, "osx": { "command": "..." }blocks inside the task definition. - Avoid absolute paths to shells (e.g.,
/bin/bash) — they break on Windows and non-standard Unix layouts.
Common Failure Modes and Recovery
| Symptom | Likely Cause | Fix |
|---|---|---|
Terminal shows command not found: npx | Node.js not in system PATH or not installed. | Install Node.js, restart VS Code, verify which npx (or where npx on Windows) in a fresh terminal. |
| Problems panel stays empty despite compile errors | problemMatcher missing or mismatched (e.g., using $tsc for non-TypeScript output). | Check the task's problemMatcher value; for custom tools, define a pattern with regex capturing file, line, column, severity, and message. |
dependsOn task runs but second task starts before first finishes | First task is a background/watch process (does not exit). | Use "dependsOrder": "sequence" (default) and ensure the first task terminates. For watch tasks, run them separately via a compound launch configuration instead. |
| Task hangs with no output | Command prompts for input (e.g., interactive CLI) but stdin is not connected. | Add "args": ["--ci", "--no-interactive"] or equivalent flags to force non-interactive mode. |
Limitations
- Tasks run in the workspace root by default; set
"options": { "cwd": "${workspaceFolder}/packages/app" }for monorepo subprojects. - No built-in parallel execution —
dependsOnis strictly sequential. For parallelism, use a shell script or a Node-based orchestrator as the command. - Environment variables defined in
tasks.json("env") do not persist beyond the task; they are not injected into subsequent terminal sessions.
Quick Validation Checklist
Ctrl+Shift+Btriggers the default build task without prompting.- TypeScript errors appear in Problems panel with correct file/line links.
- Test output is visible in the terminal and exits with non-zero code on failure.
- Running
Tasks: Run Tasklists all three labels (tsc: compile,vitest: run,build).
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.