Tasks
In today's software development world lots of tools exists to automate tasks like building, packaging, testing or deploying software systems. Examples are Make, Ant, Gulp, Jake, Rake or MSBuild to name only a few.
Although these tools are mostly run from the command line and automate jobs outside the inner software development loop (edit, compile, test and debug), having quick access to their tasks or targets from within the developer tool is a must. In addition, capturing problems (e.g. errors, warnings and infos) about the code and presenting them inside the tool improves developer productivity. That's why we made Visual Studio Code (aka VSCode) integrate with existing task runners and build tools.
Hello World
This section describes how VSCode's task integration facilities can be used to compile a simple TypeScript HelloWorld program. Open VSCode on an empty folder and create a HelloWorld.ts file with the following content:
class Startup {
public static main(): number {
console.log('Hello World');
return 0;
}
}
Now type ⇧⌘P (Windows, Linux Ctrl+Shift+P) and then Configure Task and press Enter. This will create a ./.settings/tasks.json file in your top level folder containing
sample task configurations. Let's have a look at the first uncommented configuration.
{
"version": "0.1.0",
// The command is tsc.
"command": "tsc",
// Show the output window only if unrecognized errors occur.
"showOutput": "silent",
// Under windows use tsc.exe. This ensures we don't need a shell.
"windows": {
"command": "tsc.exe"
},
// args is the HelloWorld program to compile.
"args": ["HelloWorld.ts"],
// Use the standard tsc problem matcher to find compile problems
// in the output.
"problemMatcher": "$tsc"
}
This configuration instructs VSCode to use tsc (the TypeScript compiler) as the command to be executed. We basically interpret tsc as an external task runner exposing exactly one task: compiling of TypeScript files into JavaScript files. When executed, VSCode runs tsc HelloWorld.ts and under Windows tsc.exe HelloWorld.ts. If you don't have the Typescript compiler installed you can get it from here.
To execute the task you can either:
- press ⇧⌘P (Windows, Linux Ctrl+Shift+P), type
Run Tasks, select it and press Enter. This will list all available tasks. Select tsc and press Enter to execute it. - press ⌘O (Windows, Linux Ctrl+E), type
taskand a whitespace. This will also list all available tasks. - press ⇧⌘B (Windows, Linux Ctrl+Shift+B). If a tasks.json file only defines one top level task, the task can be triggered using ⇧⌘B (Windows, Linux Ctrl+Shift+B).

Select the task and press Enter. This will execute the Typescript compiler. Since the program doesn't contain any compile problems a corresponding HelloWorld.js file is created and should be available in the Explorer view.
There are two additional properties in the tasks.json file we haven't talk about yet: showOutput and problemMatcher. Let's start with the problemMatcher property. If the source code to be compiled has problems, the output view (which can be opened using ⇧⌘U (Windows, Linux Ctrl+Shift+U) will show something like this
HelloWorld.ts(3,17): error TS2339: Property 'logg' does not exist on type 'Console'.
If a task specifies a problemMatcher property then VSCode will scan the output and if the problem matcher matches a line it will generate a VSCode problem for it. Those problems show up in the left corner of the status line. In addition all problems can be navigated to using the short cut ⇧⌘M (Windows, Linux Ctrl+Shift+M).

Capturing the compile problems in a single file project might not be very useful since the VSCode's internal language service already does so for open files. However, in larger projects where many inter-file dependencies exist, compiling the whole project and having all problems available inside VSCode at the developer's finger tips is very helpful.
VSCode ships with a number of out-of-the-box problem matchers:
- $tsc: captures problems produced by the Typscript compiler in the output. The problem matcher assumes that file names in the output are relative to the opened folder.
- $jshint: captures problems produced by the tool JSHint. The matcher assumes that file names are reported as an absolute path.
- $mscompile: captures problems produced by Microsoft compilers like csc. The matcher assumes that file names are reported as an absolute path.
- $lessCompile: captures problems produced by the less compiler. This matcher also assumes that file names are reported as absolute path.
The property showOutput controls whether VSCode should always bring the output view to the front if the user requests the execution of a task. Valid values are:
- never: the output window will not come to front. The user must explicitly bring it to front using the View menu or the short cut ⇧⌘U (Windows, Linux Ctrl+Shift+U).
- silent: the output view only comes to front if no problem matchers are configured for the task. This is the default.
- always: the output view is always brought to front.
As with all configuration files, IntelliSense is available for the tasks.json file.
Autodetection
VSCode has support to autodetect Gulp and Jake files and make their tasks available inside VSCode without configuration. The gulpfile below defines two tasks, build and debug. The first compiles C# code using mono's compiler. The second starts the MyApp under the mono debugger.
var program = "MyApp";
var port = 55555;
gulp.task('default', ['debug']);
gulp.task('build', function() {
return gulp
.src('./**/*.cs')
.pipe(msc(['-fullpaths', '-debug', '-target:exe', '-out:' + program]));
});
gulp.task('debug', ['build'], function(done) {
return mono.debug({ port: port, program: program}, done);
});
Pressing ⇧⌘P (Windows, Linux Ctrl+Shift+P) and then typing Run Tasks followed by Enter will list all available tasks in the user interface
without configuring them in tasks.json. Selecting one and pressing Enter will execute the task.

The same autodetection is available for Jake. Please note that both Gulp and Jake are autodetected only if the corresponding files are present in the root of the opened folder.
If you want to benefit from having compile problems inside VSCode or to trigger a build using ⇧⌘B (Windows, Linux Ctrl+Shift+B), you still need
to tell VSCode about it by configuring the tasks in tasks.json. VSCode helps you generate such a file for Gulp and Jake. To do so,
press ⇧⌘P (Windows, Linux Ctrl+Shift+P), type Configure Tasks and press Enter. This will generate the following tasks.json file:
{
"version": "0.1.0",
"command": "gulp",
"isShellCommand": true,
"args": [
"--no-color"
],
"tasks": [
{
"taskName": "build",
"args": [],
"isBuildCommand": true,
"problemMatcher": [
"$lessCompile",
"$tsc",
"$jshint"
]
}
]
}
In contrast to the tasks.json file in the HelloWorld section, this file has a explicit tasks property. Since the underlying task system is Gulp and a gulpfile usually defines more than one task to execute, VSCode allows to augment each task separately. The tasks property is defined as an array of object literals where each literal has the following properties:
- taskName: this is the task's name of the underlying task runner.
- args: an array of additional arguments to be passed to the task runner. Elements must be of type string.
- isBuildCommand: if this property is set to true ⇧⌘B (Windows, Linux Ctrl+Shift+B) will trigger this task.
- problemMachter: the problem matchers used for this task to detect problems in the output. Observe that here the property is an array of predefined problem matchers. In general the property can either be a single strings or an array of strings. Since Gulp is mainly used in Web development, we add problem matchers for typical Web tooling. In our case we are compiling C# using the mono compiler. Since msc adheres to the Microsoft compiler pattern we can reuse the predefined $msCompile problem matcher.
In addition, there is a new property isShellCommand in the global section. The property tells VSCode to execute the gulp command in a shell instead of directly executing it.
Observe that VSCode didn't generate a task for the debug task defined in the gulpfile. The reason is that there is usually not much to capture
for a task that starts a debugger. However you are still able to execute the debug task from within VSCode using ⌘O (Windows, Linux Ctrl+E),
Run Tasks.
If you want to add configuration for a task, simply add a corresponding entry into the tasks.json. Imagine you want to always show the output view when the debug task is executed. To achieve this do:
{
...
"tasks": [
...
{
"taskName": "debug",
"showOutput": "always"
}
]
}
Defining a Problem Matcher
As said VSCode ships with a set of predefined problem matchers. However there are lots of compilers and linting tools out there, all of which produce their own style of errors and warnings. Assume we have a helloWorld.c program in which the developer mistyped printf as prinft. Compiling it with gcc will produce the following warning:
helloWorld.c:5:3: warning: implicit declaration of function ‘prinft’
We want to produce a problem matcher that can capture the message in the output and show a corresponding problem in VSCode. Problem matchers heavily rely on regular expressions. The section below assumes you are familiar with regular expressions. A matcher that captures the above warning looks like:
{
// The problem is owned by the cpp language service.
"owner": "cpp",
// The file name for a reported problems is relative to the opened folder.
"fileLocation": ["relative", "${workspaceRoot}"],
// The actual pattern to match problems in the output.
"pattern": {
// The regular expression. Example to match: helloWorld.c:5:3: warning: implicit declaration of function ‘prinft’ [-Wimplicit-function-declaration]
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
// The first match group matches the file name which is relative.
"file": 1,
// The second match group matches the line on which the problem occurred.
"line": 2,
// The third match group matches the column at which the problem occurred.
"column": 3,
// The forth match group matches the problem's severity. Can be ignore. Then all problems are captured as errors.
"severity": 4,
// The fifth match group matches the message.
"message": 5
}
}
The final tasks.json file to run gcc and capturing errors and warning looks like this (comments removed):
{
"version": "0.1.0",
"command": "gcc",
"args": ["-Wall", "helloWorld.c", "-o", "helloWorld"],
"problemMatcher": {
"owner": "cpp",
"fileLocation": ["relative", "${workspaceRoot}"],
"pattern": {
"regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
"file": 1,
"line": 2,
"column": 3,
"severity": 4,
"message": 5
}
}
}
Running it inside VSCode and pressing ⇧⌘M (Windows, Linux Ctrl+Shift+M) to get the list of problems displays like this:

There are a couple more properties that can be used inside a pattern. These are:
- location: if the problem location is line or line,column or startLine,startColumn,endLine,endColumn then are generic location match group can be used.
- endLine: the match group index for the problem's end line. Can be omitted if no end line value is provided by the compiler.
- endColumn: the match group index for the problem's end column. Can be omitted if no end column value is provided by the compiler.
- code: the match group index for the problem's code. Can be omitted if no code value is provided by the compiler.
A functional pattern must at least provide a match group for file, message and line or location.
Variables in tasks.json
VScode supports variable substitution inside strings in the task.json file. The following predefined variables exist:
- ${workspaceRoot}: the path of the folder opened in VSCode.
- ${file}: the current opened file
- ${fileBasename}: the current opened file's basename
- ${fileDirname}: the current opened file's dirname
- ${fileExtname}: the current opened file's extension
- ${cwd}: the task runner's current working directory on startup.
Below is an example of a configuration that passes the current opened file to the TypeScript compiler.
{
...
"command": "tsc",
"args": ["${file}"],
...
}
Common Questions
Q: Some task runners require node for execution. Does VSCode require executing a task runner under a special node version?
A: We recommend that you use node version 0.12.x. This is due to the fact that node 0.10.x doesn't flush stdio on exit (see this issue for details).
Q: Does VSCode support matching multi-line compiler errors and warnings?
A: No, but it is a high priority on our backlog.
Next Steps
OK, well, that was tasks - let's keep going...
- Editing Evolved - Lint, IntelliSense, Lightbulbs, Peek and Goto Definition and more
- Language Support - Our Good, Better, Best language grid to see what you can expect
- Debugging - This is where VSCode really shines
- Customization - Themes, settings and keyboard bindings