83

I have seen that it is possible to define a task in the VSCode. But I am not sure how to define multiple tasks in the tasks.json file.

Gama11
  • 31,714
  • 9
  • 78
  • 100
Franz Gsell
  • 1,425
  • 2
  • 13
  • 22
  • First-class support was [added in VS Code 1.9 (Jan 2017)](https://code.visualstudio.com/updates/v1_9#_commands-per-task) eliminating the need for the workarounds seen in the top answers here. See [this answer (mine)](http://stackoverflow.com/a/43566702/1072626). – vossad01 Apr 23 '17 at 02:18
  • An answer can be found here: https://stackoverflow.com/questions/43657839/how-to-chain-tasks-in-visual-studio-code-using-only-tasks-json/50241977#50241977 – pasx May 08 '18 at 20:44

13 Answers13

36

Just in case it helps someone... . If you don't have/want gulp/grunt/etc... or an extra shell script to proxy out your task commands , "npm run" is there already .

this is for webpack and mocha as in "Build and Test" , Shift+Ctrl+B, Shift+Ctrl+T

.vscode/tasks.json:

{
  "name": "npmTask",
  //...
  "suppressTaskName": true,
  "command": "npm",
  "isShellCommand": true,
  "args": [
    "run"
  ],
  "tasks": [
    {
      //Build Task
      "taskName": "webpack",
      //Run On Shift+Ctrl+B
      "isBuildCommand": true,
      //Don't run when Shift+Ctrl+T
      "isTestCommand": false,
      // Show the output window if error any
      "showOutput": "silent",
      //Npm Task Name
      "args": [
        "webpack"
      ],
      // use 2 regex:
      // 1st the file, then the problem       
      "problemMatcher": {
        "owner": "webpack",
        "severity": "error",
        "fileLocation": "relative",
        "pattern": [
          {
            "regexp": "ERROR in (.*)",
            "file": 1
          },
          {
            "regexp": "\\((\\d+),(\\d+)\\):(.*)",
            "line": 1,
            "column": 2,
            "message": 3
          }
        ]
      }
    },
    {
      //Test Task   
      "taskName": "mocha",
      // Don't run on Shift+Ctrl+B
      "isBuildCommand": false,
      // Run on Shift+Ctrl+T
      "isTestCommand": true,
      "showOutput": "always",
      "args": [
        "mocha"
      ]
    }
  ]
}

package.json:

{
  ...
  "scripts": {
    "webpack": "webpack",
    "mocha": "/usr/bin/mocha"
  },
  ...
}
L Y E S - C H I O U K H
  • 4,765
  • 8
  • 40
  • 57
Dan
  • 2,818
  • 23
  • 21
  • Nice solution! So you define your actual commands in the npm scripts tag, and then you call the npm script from tasks.json. I would have really liked to just define the tasks straight inside tasks.json. This seems a bit redundant? – Kokodoko Apr 13 '16 at 09:18
13

What helped me understand this better is the sequence of arguments passed to the command. It may be obvious to some but it is not clear in the documentation.

Omitting some fields to only focus on the command being sent:

{ "command": "myCommand"
  "args": ["myCommandArguments"],
  "tasks" : [ 
    { "taskName": "myTask",
      "args": ["myTaskArguments"],
      "suppressTaskName": false,
    }
  ]
}

The above definition will result in the following command:

myCommand myCommandArguments myTaskArguments myTask

The task name myTask is always last. Since version 0.4 it can be omitted with "suppressTaskName": true.

Chris Redford
  • 16,982
  • 21
  • 89
  • 109
Hurelu
  • 1,458
  • 1
  • 14
  • 23
  • Wow, I couldn't believe this answer but tried it and it was true and worked. I wanted a task in VSCode for "gulp --no-color vet --verbose" but in order to get it to work I had the use the argument as the task and the task as the argument like " gulp --no-color --verbose vet" in the tasks.json where vet is my task and --verbose is an argument. Of course this cause problems with tasks whose args are the same so the task is named after it's args and listed as such in VSCode task run options. – GJSmith3rd Jul 21 '15 at 15:33
  • But what if I want different tasks with different commands? For example, one task should run node-sass and the other should run tsc? – Kokodoko Apr 13 '16 at 09:10
13

Try this

{
    "version": "0.1.0",
    "command": "cmd",
    "isShellCommand": true,
    "args": ["/C"],
    "tasks": [
        {
            "taskName": "install",
            "args": ["npm install"]
        },
        {
            "taskName": "build",
            "args": ["gulp build"],
            "isBuildCommand": true,
            "problemMatcher": "$gulp-tsc"
        }
    ]
}
AlexStack
  • 16,766
  • 21
  • 72
  • 104
  • more info please? What's the error? I'm using this as of VS Code 0.8.0 and it's working fine. – AlexStack Oct 11 '15 at 14:44
  • on toogle output I've see standart cmd.exe onrun output. Like this: Microsoft Windows [Version 10.0.10240] (c) Корпорация Майкрософт (Microsoft Corporation), 2015 г. Все права защищены. //MS copyrights on russian C:\Users\roman> – neftedollar Oct 13 '15 at 12:53
  • @neftedollar This only works on Windows. If you are looking for something that will work on a Mac, change "command": "cmd" to "command":"sh" and change "args":["/c"] to "args":["-c"]. – ra9r Sep 01 '16 at 01:45
  • @raiglstorfer thanks, it wasn't working on my windows PC. – neftedollar Sep 01 '16 at 13:40
10

I use the following tasks.json file to run multiple TypeScript build scenarios. I put a tsconfig.json file in each folder, so that allows me to tune each folder's output individually. Just make sure you suppress the task name, because it tries to put it in the command string.

{
    "version": "0.1.0",
    "command": "tsc",
    "showOutput": "always",
    "isShellCommand": true,
    "args": [],
    "windows": {
        "command": "tsc",
        "showOutput": "always",
        "isShellCommand": true
    },
    "tasks": [
        {
            "taskName": "Build the examples",
            "suppressTaskName": true,
            "isBuildCommand": false,            
            "args": ["-p", "./source/examples", "--outDir", "./script/examples"],
            "problemMatcher": "$tsc"
        },
        {
            "taskName": "Build the solution",            
            "suppressTaskName": true,
            "isBuildCommand": false,        
            "args": ["-p", "./source/solution", "--outDir", "./script/solution"],
            "problemMatcher": "$tsc"
        }   
    ]
}

This is what the folder structure looks like, where /script is the output root and /source is the input root. Both folders reference type declarations in the /typingd folder and /typings folder. TypeScript is somewhat limited to using relative paths in external references, so it helps simplify things if these folder structures are similar.

TypeScript Multi-Build Folder Structure

Oh yea, it makes it easier to launch them selectively if you mark them as non build and override the build key to select a specific task from a list, like so..

// Place your key bindings in this file to overwrite the defaults
[
    { "key": "ctrl+shift+b", "command": "workbench.action.tasks.runTask" }
]

Update: You can always just go entirely rogue, if you want. There may be better ways to handle the args, but this works for me under OSX at the moment.

{
  "version": "0.1.0",
  "isShellCommand": true,
  "linux": { "command": "sh", "args": ["-c"] },
  "osx": { "command": "sh", "args": ["-c"] },
  "windows": { "command": "powershell", "args": ["-Command"] },
  "tasks": [
    {
      "taskName": "build-models",
      "args": ["gulp build-models"],
      "suppressTaskName": true,
      "isBuildCommand": false,
      "isTestCommand": false
    },
    {
      "taskName": "run tests",
      "args": ["mocha ${workspaceRoot}/test"],
      "suppressTaskName": true,
      "isBuildCommand": false,
      "isTestCommand": false
    }
  ]
}
djabraham
  • 766
  • 11
  • 20
  • 2
    This is a very clear example! This is probably how MS intended the tasks.json to be used (it's a shame they don't explain this themselves). The only problem is: what if I have DIFFERENT command line tasks? (I need a tsc task and a node-sass task) – Kokodoko Apr 13 '16 at 09:33
  • 3
    See Update, for a means of running multiple independent commands. – djabraham Apr 14 '16 at 16:05
  • I agree that a single "build command" is trouble when you want to use tsc and node-sass. Having to install and learn a third party build tool (like gulp) is a downer. Having to list different command processors for different OS-es is a downer. – Jon Watte Oct 01 '16 at 18:37
7

I don't know the proper answer to this (and would also like to know), but my ugly workaround in case it helps anyone. I'm on Windows, I've ended up creating myself a simple batch script which could contain simply

"%1" "%2"

Then my tasks.json looks something like

{
    "version": "0.1.0",
    "command": "c:\\...\\mytasks.bat"
    "tasks" : [
        {
            "taskName": "myFirstTask",
            "args": "c:\\...\\task1.exe", "${file}"],
        },
        {
            "taskName": "mySecondTask",
            "args": "c:\\...\\task2.exe", "${file}"],
        },
    ]
}
Jonathan Corwin
  • 960
  • 1
  • 7
  • 11
  • I finally got this working. Somewhere in the last 9 months or so VS Code started adding the taskName to arg 1 on the task. So my batch file becomes: "%2" "%3" instead of what you have. If this stays consistent I might come back to edit this solution. – phil Feb 25 '16 at 22:54
6

You can list more than one task in the tasks property. Something like:

"tasks": [
    {
        "taskName": "build",
        ...
    },
    {
         "taskName": "package",
         ...
    }
]
Dirk Bäumer
  • 1,183
  • 9
  • 7
  • 7
    They have to use the same command, though. You can only vary the arguments. – Edward B. May 05 '15 at 15:47
  • Yes Edward B. for some reason every current blog post out there assumes you are just starting with VS Code and have no tasks yet :S. But you have to set the "suppressTaskName": true, on the root node and can then set "taskName" it in the subtasks in order to use different commands. See example of @Dan with `tsc` and `mocha` tasks. – Bart Jan 11 '16 at 14:50
4

This functionality was added in Visual Studio Code v1.9 (January 2017). Example and text come from the release notes:

{
  "version": "0.1.0",
  "tasks": [
    {
      "taskName": "tsc",
      "command": "tsc",
      "args": ["-w"],
      "isShellCommand": true,
      "isBackground": true,
      "problemMatcher": "$tsc-watch"
    },
    {
      "taskName": "build",
      "command": "gulp",
      "args": ["build"],
      "isShellCommand": true
    }
  ]
}

Commands per task

You can now define different commands per task (#981). This allows running different commands for different tasks without writing your own shell script. A tasks.json file using commands per task looks like [the above.]

vossad01
  • 11,552
  • 8
  • 56
  • 109
3

This Seems To Be A VSCode Bug As Of v0.5.0

so I've added this answer to show a working example of what was previously explained by @hurelu. My tasks.json:

{
    "version": "0.1.0",
    "command": "gulp",
    "isShellCommand": true,
    "args": [
        "--no-color"
    ],
    "tasks": [
        {
            "taskName": "--verbose",
            "isBuildCommand": true,
            "showOutput": "always",
            "args": [
                "vet"
            ],
            "problemMatcher": [
                "$jshint",
                "$jshint-stylish"
            ]
        },
        {
            "taskName": "vet",
            "isTestCommand": true,
            "showOutput": "always",
            "args": [],
            "problemMatcher": [
                "$jshint",
                "$jshint-stylish"
            ]
        }
    ]
}

My gulp.js:

/// <reference path="typings/tsd.d.ts" />

var gulp = require('gulp');
var jshint = require('gulp-jshint');
var jscs = require('gulp-jscs');
var util = require('gulp-util');
var gulpprint = require('gulp-print');
var gulpif = require('gulp-if');
var args = require('yargs').argv;

gulp.task('vet', function () {
    log('Analyzing source with JSHint and JSCS');

    return gulp
        .src
        ([
            './src/**/*.js',
            './*.js'
        ])
        .pipe(gulpif(args.verbose, gulpprint()))
        .pipe(jscs())
        .pipe(jshint())
        .pipe(jshint.reporter('jshint-stylish', { verbose: true }))
        .pipe(jshint.reporter('fail'));
});

gulp.task('hello-world', function () {
    console.log('This is our first Gulp task!');
});

////////////
function log(msg) {
    if (typeof (msg) === 'object') {
        for (var item in msg) {
            if (msg.hasOwnProperty(item)) {
                util.log(util.colors.blue(msg[item]));
            }
        }
    } else {
        util.log(util.colors.blue(msg));
    }

}

Notice the first task uses isBuildCommand so CTRL+SHFT+B launches and the next task is isTestCommand so CTRL+SHFT+T launches. However, in order to get the the first task to accept args the task name and args had to be reversed.

As of VSCode 0.5.0 the above works but the following does not:

{
    "version": "0.1.0",
    "command": "gulp",
    "isShellCommand": true,
    "args": [
        "--no-color"
    ],
    "tasks": [
        {
            "taskName": "vet",
            "isBuildCommand": true,
            "showOutput": "always",
            "args": [
                "--verbose"
            ],
            "problemMatcher": [
                "$jshint",
                "$jshint-stylish"
            ]
        },
        {
            "taskName": "vet",
            "isTestCommand": true,
            "showOutput": "always",
            "args": [],
            "problemMatcher": [
                "$jshint",
                "$jshint-stylish"
            ]
        }
    ]
}

Here's output from task.json with correct task and args order:

[10:59:29] Using gulpfile ~/Workspaces/Examples/Gulp/pluralsight-gulp/gulpfile.js
[10:59:29] Task 'default' is not in your gulpfile
[10:59:29] Please check the documentation for proper gulpfile formatting

Here's the correct output from the tasks.json with the taskname and arg reversed when using args:

[11:02:44] Using gulpfile ~/Workspaces/Examples/Gulp/pluralsight-gulp/gulpfile.js
[11:02:44] Starting 'vet'...
[11:02:44] Analyzing source with JSHint and JSCS
[gulp] src/server/app.js
[gulp] src/client/app/app.module.js
[gulp] src/client/test-helpers/bind-polyfill.js
[gulp] src/client/test-helpers/mock-data.js
[gulp] src/server/routes/index.js
[gulp] src/client/app/core/config.js
[gulp] src/client/app/core/constants.js
[gulp] src/client/app/core/core.module.js
[gulp] src/client/app/core/dataservice.js
[gulp] src/client/app/core/dataservice.spec.js
[gulp] src/client/app/customers/customer-detail.controller.js
[gulp] src/client/app/customers/customer-detail.controller.spec.js
[gulp] src/client/app/customers/customers.controller.js
[gulp] src/client/app/customers/customers.controller.spec.js
[gulp] src/client/app/customers/customers.module.js
[gulp] src/client/app/customers/customers.route.js
[gulp] src/client/app/customers/customers.route.spec.js
[gulp] src/client/app/dashboard/dashboard.controller.js
[gulp] src/client/app/dashboard/dashboard.controller.spec.js
[gulp] src/client/app/dashboard/dashboard.module.js
[gulp] src/client/app/dashboard/dashboard.route.js
[gulp] src/client/app/dashboard/dashboard.route.spec.js
[gulp] src/client/app/layout/ht-sidebar.directive.js
[gulp] src/client/app/layout/ht-sidebar.directive.spec.js
[gulp] src/client/app/layout/ht-top-nav.directive.js
[gulp] src/client/app/layout/layout.module.js
[gulp] src/client/app/layout/shell.controller.js
[gulp] src/client/app/layout/shell.controller.spec.js
[gulp] src/client/app/layout/sidebar.controller.js
[gulp] src/client/app/layout/sidebar.controller.spec.js
[gulp] src/client/app/widgets/ht-img-person.directive.js
[gulp] src/client/app/widgets/ht-widget-header.directive.js
[gulp] src/client/app/widgets/widgets.module.js
[gulp] src/client/tests/server-integration/dataservice.spec.js
[gulp] src/server/routes/utils/errorHandler.js
[gulp] src/server/routes/utils/jsonfileservice.js
[gulp] src/client/app/blocks/exception/exception-handler.provider.js
[gulp] src/client/app/blocks/exception/exception-handler.provider.spec.js
[gulp] src/client/app/blocks/exception/exception.js
[gulp] src/client/app/blocks/exception/exception.module.js
[gulp] src/client/app/blocks/logger/logger.js
[gulp] src/client/app/blocks/logger/logger.module.js
[gulp] src/client/app/blocks/router/router-helper.provider.js
[gulp] src/client/app/blocks/router/router.module.js
[gulp] gulpfile.js
[gulp] karma.conf.js
[11:02:48] Finished 'vet' after 4.37 s
GJSmith3rd
  • 806
  • 5
  • 7
2

As of the February 2017 release, you can use Terminal Runner and compose multiple tasks by setting up dependency tasks. It's a little funky in that it will open up a separate integrated terminal for each task, which you have to watch to see if things work and remember to close (they "stack"), and you don't get a "done" notification, but it gets the job done. The functionality is preliminary but it is promising. Here's is an example to run tsc and jspm for a Cordova app.

{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [{
        "taskName": "tsc",
        "command": "tsc",
        "isShellCommand": true,
        "args": ["-p", "."],
        "showOutput": "always",
        "problemMatcher": "$tsc"
    }, {
        "taskName": "jspm",
        "command": "jspm",
        "isShellCommand": true,
        "args": ["bundle-sfx", "www/app/main.js", "www/dist/bundle.js", "--inline-source-maps", "--source-map-contents"],
        "showOutput": "always"
    },
    {
        "taskName": "build",
        "isBuildCommand": true,
        "dependsOn": ["tsc", "jspm"]
    }]
}
Racil Hilan
  • 24,690
  • 13
  • 50
  • 55
Jason
  • 941
  • 1
  • 10
  • 19
1

The following worked for me:

tasks.json:

{
    "version": "0.1.0",
    "command": "cmd",
    "isShellCommand": true,
    "args": [
        "/c"
    ],
    "tasks": [
        {
            "taskName": "bower",
            "args" : ["gulp bower"],
            "isBuildCommand": true,
            "showOutput": "always"
        },
        {
            "taskName": "unittest",
            "suppressTaskName": true,
            "args" : ["dnx -p ${cwd}\\test\\MyProject.UnitTests test"],
            "isTestCommand": true,
            "showOutput": "always"
        }
    ]
}

MyProject.UnitTests\project.json:

 "commands": {
    "test": "xunit.runner.dnx"
  }

Run bower : Ctrl + Shift + B from vscode Run tests : Ctrl + Shift + T from vscode

AlexandruC
  • 3,527
  • 6
  • 51
  • 80
1

This works for me...

I know there is a lot of different answers here but my approach was a little bit different again so I thought I would add my 2 pence worth.

I am on windows and use an external batch file to run my commands. It’s similar to Jonathan's answer above but I don’t pipe any commands to it which means my “tasks.json” file is different.

I might change this approach over time (for example I haven’t got around to playing with gulp just yet) but this method is working perfectly fine for me at the moment.

I am using handlebars for html templating, babel so I can use ES6 code and a code linter to pick up errors. At the end, the batch file launches a browser with my start page (index.html)

Here is my batch file named run_tasks.bat:

@ECHO OFF
@ECHO Startz!
@ECHO Running Handlebars!

call handlebars html_templates -e html -f dist/html_templates.js

@ECHO Linting ES6 code

call eslint -c eslint.json src

@ECHO Running Babel ES6 to ES5

call babel src --out-dir dist --source-maps

@ECHO Now startzing page up in browser!
index.html

@ECHO Donezz it!

And here is my tasks.json file:

{ 
    "version": "0.1.0",
    "command": "${workspaceRoot}/run_tasks.bat",
    "isShellCommand": true,
    "isWatching": true,
    "showOutput": "always",

    "args": [],

    "tasks": [
        {
            "taskName": "build",
            "isBuildCommand": true,
            "isWatching": true,
            "showOutput": "always"
        }
}

Then, in VSCode I press “CTRL + SHIFT + B” to run my batch file.

Ocean Airdrop
  • 2,793
  • 1
  • 26
  • 31
1

I have an Electron app that needs to compile a less stylesheet then build and launch the program. I used @Ocean's solution which worked for me...nothing else worked.

Both my tasks.json and build-tasks.bat file are in the .vscode directory in the root of the project.

build-tasks.bat

@ECHO OFF
@ECHO Begin!
@ECHO Compiling Less

call lessc ./css/styles.less ./css/styles.css

@ECHO Build Electron App and Launch

call electron ./app.js

@ECHO Finished!

tasks.json

{
    "version": "0.1.0",
    "command": "${workspaceRoot}\\.vscode\\build-tasks.bat",
    "isShellCommand": true,
    "isWatching": true,
    "showOutput": "always",

    "args": [],

    "tasks": [
        {
            "taskName": "build",
            "isBuildCommand": true,
            "isWatching": true,
            "showOutput": "always"
        }
    ]
}
lamarant
  • 3,243
  • 2
  • 25
  • 30
0

Thanks to this thread, I now have c# / dnxcore50 build and test debug etc working in vscode on osx with this:

{
"version": "0.1.0",
"command": "bash",
"args": [
],
"tasks": [
    {
        "taskName": "xbuild",
        "args": [
            "./src/Service.Host/Service.Host.csproj"
        ],          

        "showOutput": "always",
        "problemMatcher": "$msCompile",
        "isBuildCommand": true
    },
    {
        "taskName": "dnx",
        "args" : ["-p", "./test/Service.Tests.Unit", "test"],
        "isTestCommand": true,
        "showOutput": "always"    
    }      
]
}

I am sure linux would be basicly the same. The only thing that is anoying me is having to maintain the .csproj files just for debuging. I am looking forward to a way to debug with dnx, though I have not looked for a couple of weeks now.

Mark Jones
  • 1,461
  • 1
  • 14
  • 23