How to Create Dependent, Background, and Compound Tasks in VS Code

Create VS Code compound tasks with dependsOn, choose parallel or sequential execution, and configure background tasks so dependent workflows can detect readiness.

7 min read

VS Code compound tasks use dependsOn to run other tasks under one label. Dependencies start in parallel by default, dependsOrder: "sequence" makes them run in listed order, and isBackground: true marks a process that keeps running.

Use these patterns for existing build, lint, test, watch, or server tasks. Each dependency label must match a task shown by Tasks: Run Task.

The current behavior is documented in the official VS Code Tasks guide. Make sure the individual tasks work by themselves before composing them.

Run tasks in sequence with dependsOn

The dependsOn property tells VS Code to run other tasks before the current one. By default, tasks in the dependsOn array run in parallel. Add dependsOrder to run them in sequence.

Here is a compound task that type-checks, then runs the linter:

jsonjson
{
  "label": "Verify code",
  "dependsOrder": "sequence",
  "dependsOn": ["Type check", "Lint"]
}

The Verify code task has no command of its own. When you run it, VS Code starts Type check, waits for that task to finish, and then starts Lint.

Define Type check and Lint elsewhere in the same tasks.json, or use their exact auto-detected labels. Run Tasks: Run Task > Verify code and watch the task terminals to confirm the order.

If the order does not matter, omit dependsOrder instead of forcing a sequence.

Run tasks in parallel

Remove dependsOrder (or do not add it) to run tasks in parallel. This is useful when two steps are independent:

jsonjson
{
  "label": "Lint and test",
  "dependsOn": ["ESLint check", "Run unit tests"]
}

VS Code starts both tasks at the same time. The compound task stays active until both dependencies finish. Check each task terminal for its exit status and output.

For tasks that share a terminal group, use the presentation.group property to show them in split panes instead of separate tabs.

Create a background task

A background task keeps running after it starts. Use this for watchers, dev servers, and any long-running process.

Mark a task as background with isBackground: true. This TypeScript example uses the built-in $tsc-watch matcher, which also reports errors and tracks watch cycles:

jsonjson
{
  "label": "TypeScript watch",
  "type": "shell",
  "command": "tsc --watch",
  "isBackground": true,
  "problemMatcher": "$tsc-watch"
}

After you run the task, the terminal remains active and reports that TypeScript is watching for file changes. Run Tasks: Terminate Task and choose TypeScript watch when you want to stop it.

A background matcher is not required merely to keep a process running. It is required when VS Code must track active and inactive states, such as a background task used in a sequential dependsOn chain or as a debugger preLaunchTask.

For a custom watcher or server, copy its real start and ready lines into beginsPattern and endsPattern. The ready pattern must match output the process actually prints.

Build a compound task with a background server

You can group a watcher and a server under one label. Assume TypeScript watch and Start app are already working background tasks:

jsonjson
{
  "label": "Development",
  "dependsOn": ["TypeScript watch", "Start app"]
}

Run Tasks: Run Task > Development. VS Code starts both dependencies in parallel, and the compound task remains active while they run. Confirm that both task terminals reach their normal watch or ready state, then use Tasks: Terminate Task to stop the workflow.

If Start app must wait for TypeScript watch to become ready, add dependsOrder: "sequence" and ensure the watch task has a background matcher whose endsPattern matches its ready line.

Use a background task as a pre-launch task

Background tasks can run before a debug session starts. In the relevant configuration inside .vscode/launch.json, set preLaunchTask to the exact task label:

jsonjson
{
  "preLaunchTask": "TypeScript watch"
}

The debugger waits for the background matcher's ready state before launching. If the matcher never reaches that state, stop the task and compare endsPattern with the exact terminal output instead of adding an unrelated debugger setting.

For more on debugging, see the beginner's guide to Run and Debug.

Hide intermediate tasks

When a compound task runs several dependencies, its task terminals can become distracting. Use presentation to keep an intermediate terminal hidden while still revealing matched problems:

jsonjson
{
  "label": "Type check",
  "type": "shell",
  "command": "npm run typecheck",
  "presentation": {
    "reveal": "never",
    "revealProblems": "onProblem",
    "panel": "shared"
  }
}

This example assumes package.json defines a typecheck script and the task has a suitable problem matcher elsewhere in its definition.

Set reveal to never to keep the terminal in the background. revealProblems: "onProblem" brings the Problems panel forward only when a problem matcher reports an issue. panel: "shared" lets tasks reuse the same task terminal.

For the final task in the chain (the one the user cares about), keep reveal as always so the output is visible.

Troubleshooting

A sequential dependsOn chain hangs

A background task in the chain may not have an endsPattern that matches its output. VS Code waits for the pattern to appear before running the next task. Check the task's terminal output and make sure the pattern matches a line that actually appears.

Parallel tasks overwrite each other's output

By default, parallel tasks use separate terminals. If you set presentation.panel to shared for both, their output mixes. Use dedicated or new for tasks that should not share a terminal.

A pre-launch task never becomes ready

Inspect the task terminal and copy the exact ready line produced by the current tool. Update the background matcher's endsPattern, rerun the task by itself, and confirm the matcher reaches its ready state before starting the debugger again.

Once you can chain and orchestrate tasks, learn how to use task variables to make your automation portable across machines and environments.

Rune AI

Rune AI

Key Insights

  • Use dependsOn to create a compound task from existing task labels.
  • Dependencies run in parallel by default; add dependsOrder: sequence when order matters.
  • Mark a long-running watcher or server with isBackground: true.
  • A sequential dependency or preLaunchTask needs a background-aware problem matcher to detect readiness.
  • Run Tasks: Terminate Task to stop a background workflow cleanly.
RunePowered by Rune AI

Frequently Asked Questions

Can I use dependsOn with auto-detected tasks?

Yes. Reference the exact label shown by Tasks: Run Task. Auto-detected labels are qualified by their task provider, such as npm: build or tsc: build - tsconfig.json, so copy the displayed label instead of guessing it.

How do I stop a background task that is running?

Run Tasks: Terminate Task from the Command Palette and select the task. You can also focus its terminal and send the shell's interrupt shortcut, usually Ctrl+C.

Can a compound task depend on another compound task?

Yes. A label in dependsOn can identify another compound task. Keep the dependency graph small and avoid circular references so the execution order remains clear.

How do I choose sequential or parallel dependencies?

Dependencies run in parallel when dependsOrder is omitted. Set dependsOrder to sequence when each listed task must finish, or report a background ready state, before the next dependency starts.

Conclusion

A VS Code compound task groups dependencies under one label. Dependencies run in parallel by default, while dependsOrder: sequence enforces their listed order. Mark long-running processes with isBackground and add a background-aware problem matcher whenever another task or debugger must know when that process is ready.