1 | # Concurrently
|
2 |
|
3 | [![Build Status](https://github.com/open-cli-tools/concurrently/workflows/Tests/badge.svg)](https://github.com/open-cli-tools/concurrently/actions?workflow=Tests)
|
4 | [![Coverage Status](https://coveralls.io/repos/github/open-cli-tools/concurrently/badge.svg?branch=master)](https://coveralls.io/github/open-cli-tools/concurrently?branch=master)
|
5 |
|
6 | [![NPM Badge](https://nodei.co/npm/concurrently.png?downloads=true)](https://www.npmjs.com/package/concurrently)
|
7 |
|
8 | Run multiple commands concurrently.
|
9 | Like `npm run watch-js & npm run watch-less` but better.
|
10 |
|
11 | ![](docs/demo.gif)
|
12 |
|
13 | **Table of contents**
|
14 | - [Concurrently](#concurrently)
|
15 | - [Why](#why)
|
16 | - [Install](#install)
|
17 | - [Usage](#usage)
|
18 | - [API](#api)
|
19 | - [`concurrently(commands[, options])`](#concurrentlycommands-options)
|
20 | - [`Command`](#command)
|
21 | - [`CloseEvent`](#closeevent)
|
22 | - [FAQ](#faq)
|
23 |
|
24 | ## Why
|
25 |
|
26 | I like [task automation with npm](https://github.com/substack/blog/blob/master/npm_run.markdown)
|
27 | but the usual way to run multiple commands concurrently is
|
28 | `npm run watch-js & npm run watch-css`. That's fine but it's hard to keep
|
29 | on track of different outputs. Also if one process fails, others still keep running
|
30 | and you won't even notice the difference.
|
31 |
|
32 | Another option would be to just run all commands in separate terminals. I got
|
33 | tired of opening terminals and made **concurrently**.
|
34 |
|
35 | **Features:**
|
36 |
|
37 | * Cross platform (including Windows)
|
38 | * Output is easy to follow with prefixes
|
39 | * With `--kill-others` switch, all commands are killed if one dies
|
40 | * Spawns commands with [spawn-command](https://github.com/mmalecki/spawn-command)
|
41 |
|
42 | ## Install
|
43 |
|
44 | The tool is written in Node.js, but you can use it to run **any** commands.
|
45 |
|
46 | ```bash
|
47 | npm install -g concurrently
|
48 | ```
|
49 |
|
50 | or if you are using it from npm scripts:
|
51 |
|
52 | ```bash
|
53 | npm install concurrently --save
|
54 | ```
|
55 |
|
56 | ## Usage
|
57 |
|
58 | Remember to surround separate commands with quotes:
|
59 | ```bash
|
60 | concurrently "command1 arg" "command2 arg"
|
61 | ```
|
62 |
|
63 | Otherwise **concurrently** would try to run 4 separate commands:
|
64 | `command1`, `arg`, `command2`, `arg`.
|
65 |
|
66 | In package.json, escape quotes:
|
67 |
|
68 | ```bash
|
69 | "start": "concurrently \"command1 arg\" \"command2 arg\""
|
70 | ```
|
71 |
|
72 | NPM run commands can be shortened:
|
73 |
|
74 | ```bash
|
75 | concurrently "npm:watch-js" "npm:watch-css" "npm:watch-node"
|
76 |
|
77 | # Equivalent to:
|
78 | concurrently -n watch-js,watch-css,watch-node "npm run watch-js" "npm run watch-css" "npm run watch-node"
|
79 | ```
|
80 |
|
81 | NPM shortened commands also support wildcards. Given the following scripts in
|
82 | package.json:
|
83 |
|
84 | ```javascript
|
85 | {
|
86 | //...
|
87 | "scripts": {
|
88 | // ...
|
89 | "watch-js": "...",
|
90 | "watch-css": "...",
|
91 | "watch-node": "...",
|
92 | // ...
|
93 | },
|
94 | // ...
|
95 | }
|
96 | ```
|
97 |
|
98 | ```bash
|
99 | concurrently "npm:watch-*"
|
100 |
|
101 | # Equivalent to:
|
102 | concurrently -n js,css,node "npm run watch-js" "npm run watch-css" "npm run watch-node"
|
103 |
|
104 | # Any name provided for the wildcard command will be used as a prefix to the wildcard
|
105 | # part of the script name:
|
106 | concurrently -n w: npm:watch-*
|
107 |
|
108 | # Equivalent to:
|
109 | concurrently -n w:js,w:css,w:node "npm run watch-js" "npm run watch-css" "npm run watch-node"
|
110 | ```
|
111 |
|
112 | Exclusion is also supported. Given the following scripts in package.json:
|
113 | ```javascript
|
114 | {
|
115 | // ...
|
116 | "scripts": {
|
117 | "lint:js": "...",
|
118 | "lint:ts": "...",
|
119 | "lint:fix:js": "...",
|
120 | "lint:fix:ts": "...",
|
121 | // ...
|
122 | }
|
123 | // ...
|
124 | }
|
125 | ```
|
126 | ```bash
|
127 | # Running only lint:js and lint:ts
|
128 | # with lint:fix:js and lint:fix:ts excluded
|
129 | concurrently "npm:lint:*(!fix)"
|
130 | ```
|
131 |
|
132 | Good frontend one-liner example [here](https://github.com/kimmobrunfeldt/dont-copy-paste-this-frontend-template/blob/5cd2bde719654941bdfc0a42c6f1b8e69ae79980/package.json#L9).
|
133 |
|
134 | Help:
|
135 |
|
136 | ```
|
137 | concurrently [options] <command ...>
|
138 |
|
139 | General
|
140 | -m, --max-processes How many processes should run at once.
|
141 | New processes only spawn after all restart tries
|
142 | of a process. [number]
|
143 | -n, --names List of custom names to be used in prefix
|
144 | template.
|
145 | Example names: "main,browser,server" [string]
|
146 | --name-separator The character to split <names> on. Example usage:
|
147 | concurrently -n "styles|scripts|server"
|
148 | --name-separator "|" [default: ","]
|
149 | -s, --success Which command(s) must exit with code 0 in order
|
150 | for concurrently exit with code 0 too. Options
|
151 | are:
|
152 | - "first" for the first command to exit;
|
153 | - "last" for the last command to exit;
|
154 | - "all" for all commands;
|
155 | - "command-{name}"/"command-{index}" for the
|
156 | commands with that name or index;
|
157 | - "!command-{name}"/"!command-{index}" for all
|
158 | commands but the ones with that name or index.
|
159 | [default: "all"]
|
160 | -r, --raw Output only raw output of processes, disables
|
161 | prettifying and concurrently coloring. [boolean]
|
162 | --no-color Disables colors from logging [boolean]
|
163 | --hide Comma-separated list of processes to hide the
|
164 | output.
|
165 | The processes can be identified by their name or
|
166 | index. [string] [default: ""]
|
167 | -g, --group Order the output as if the commands were run
|
168 | sequentially. [boolean]
|
169 | --timings Show timing information for all processes.
|
170 | [boolean] [default: false]
|
171 | -P, --passthrough-arguments Passthrough additional arguments to commands
|
172 | (accessible via placeholders) instead of treating
|
173 | them as commands. [boolean] [default: false]
|
174 |
|
175 | Prefix styling
|
176 | -p, --prefix Prefix used in logging for each process.
|
177 | Possible values: index, pid, time, command, name,
|
178 | none, or a template. Example template: "{time}-{pid}"
|
179 | [string] [default: index or name (when --names is set)]
|
180 | -c, --prefix-colors Comma-separated list of chalk colors to use on
|
181 | prefixes. If there are more commands than colors, the
|
182 | last color will be repeated.
|
183 | - Available modifiers: reset, bold, dim, italic,
|
184 | underline, inverse, hidden, strikethrough
|
185 | - Available colors: black, red, green, yellow, blue,
|
186 | magenta, cyan, white, gray
|
187 | or any hex values for colors, eg #23de43
|
188 | - Available background colors: bgBlack, bgRed,
|
189 | bgGreen, bgYellow, bgBlue, bgMagenta, bgCyan, bgWhite
|
190 | See https://www.npmjs.com/package/chalk for more
|
191 | information. [string] [default: "reset"]
|
192 | -l, --prefix-length Limit how many characters of the command is displayed
|
193 | in prefix. The option can be used to shorten the
|
194 | prefix when it is set to "command"
|
195 | [number] [default: 10]
|
196 | -t, --timestamp-format Specify the timestamp in moment/date-fns format.
|
197 | [string] [default: "yyyy-MM-dd HH:mm:ss.SSS"]
|
198 |
|
199 | Input handling
|
200 | -i, --handle-input Whether input should be forwarded to the child
|
201 | processes. See examples for more information.
|
202 | [boolean]
|
203 | --default-input-target Identifier for child process to which input on
|
204 | stdin should be sent if not specified at start of
|
205 | input.
|
206 | Can be either the index or the name of the
|
207 | process. [default: 0]
|
208 |
|
209 | Killing other processes
|
210 | -k, --kill-others Kill other processes if one exits or dies.[boolean]
|
211 | --kill-others-on-fail Kill other processes if one exits with non zero
|
212 | status code. [boolean]
|
213 |
|
214 | Restarting
|
215 | --restart-tries How many times a process that died should restart.
|
216 | Negative numbers will make the process restart forever.
|
217 | [number] [default: 0]
|
218 | --restart-after Delay time to respawn the process, in milliseconds.
|
219 | [number] [default: 0]
|
220 |
|
221 | Options:
|
222 | -h, --help Show help [boolean]
|
223 | -v, -V, --version Show version number [boolean]
|
224 |
|
225 |
|
226 | Examples:
|
227 |
|
228 | - Output nothing more than stdout+stderr of child processes
|
229 |
|
230 | $ concurrently --raw "npm run watch-less" "npm run watch-js"
|
231 |
|
232 | - Normal output but without colors e.g. when logging to file
|
233 |
|
234 | $ concurrently --no-color "grunt watch" "http-server" > log
|
235 |
|
236 | - Custom prefix
|
237 |
|
238 | $ concurrently --prefix "{time}-{pid}" "npm run watch" "http-server"
|
239 |
|
240 | - Custom names and colored prefixes
|
241 |
|
242 | $ concurrently --names "HTTP,WATCH" -c "bgBlue.bold,bgMagenta.bold"
|
243 | "http-server" "npm run watch"
|
244 |
|
245 | - Configuring via environment variables with CONCURRENTLY_ prefix
|
246 |
|
247 | $ CONCURRENTLY_RAW=true CONCURRENTLY_KILL_OTHERS=true concurrently "echo
|
248 | hello" "echo world"
|
249 |
|
250 | - Send input to default
|
251 |
|
252 | $ concurrently --handle-input "nodemon" "npm run watch-js"
|
253 | rs # Sends rs command to nodemon process
|
254 |
|
255 | - Send input to specific child identified by index
|
256 |
|
257 | $ concurrently --handle-input "npm run watch-js" nodemon
|
258 | 1:rs
|
259 |
|
260 | - Send input to specific child identified by name
|
261 |
|
262 | $ concurrently --handle-input -n js,srv "npm run watch-js" nodemon
|
263 | srv:rs
|
264 |
|
265 | - Shortened NPM run commands
|
266 |
|
267 | $ concurrently npm:watch-node npm:watch-js npm:watch-css
|
268 |
|
269 | - Shortened NPM run command with wildcard (make sure to wrap it in quotes!)
|
270 |
|
271 | $ concurrently "npm:watch-*"
|
272 |
|
273 | - Exclude patterns so that between "lint:js" and "lint:fix:js", only "lint:js"
|
274 | is ran
|
275 |
|
276 | $ concurrently "npm:*(!fix)"
|
277 |
|
278 | - Passthrough some additional arguments via '{<number>}' placeholder
|
279 |
|
280 | $ concurrently -P "echo {1}" -- foo
|
281 |
|
282 | - Passthrough all additional arguments via '{@}' placeholder
|
283 |
|
284 | $ concurrently -P "npm:dev-* -- {@}" -- --watch --noEmit
|
285 |
|
286 | - Passthrough all additional arguments combined via '{*}' placeholder
|
287 |
|
288 | $ concurrently -P "npm:dev-* -- {*}" -- --watch --noEmit
|
289 |
|
290 | For more details, visit https://github.com/open-cli-tools/concurrently
|
291 | ```
|
292 |
|
293 | ## API
|
294 | concurrently can be used programmatically by using the API documented below:
|
295 |
|
296 | ### `concurrently(commands[, options])`
|
297 |
|
298 | - `commands`: an array of either strings (containing the commands to run) or objects
|
299 | with the shape `{ command, name, prefixColor, env, cwd }`.
|
300 |
|
301 | - `options` (optional): an object containing any of the below:
|
302 | - `cwd`: the working directory to be used by all commands. Can be overriden per command.
|
303 | Default: `process.cwd()`.
|
304 | - `defaultInputTarget`: the default input target when reading from `inputStream`.
|
305 | Default: `0`.
|
306 | - `handleInput`: when `true`, reads input from `process.stdin`.
|
307 | - `inputStream`: a [`Readable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_readable_streams)
|
308 | to read the input from. Should only be used in the rare instance you would like to stream anything other than `process.stdin`. Overrides `handleInput`.
|
309 | - `pauseInputStreamOnFinish`: by default, pauses the input stream (`process.stdin` when `handleInput` is enabled, or `inputStream` if provided) when all of the processes have finished. If you need to read from the input stream after `concurrently` has finished, set this to `false`. ([#252](https://github.com/kimmobrunfeldt/concurrently/issues/252)).
|
310 | - `killOthers`: an array of exitting conditions that will cause a process to kill others.
|
311 | Can contain any of `success` or `failure`.
|
312 | - `maxProcesses`: how many processes should run at once.
|
313 | - `outputStream`: a [`Writable` stream](https://nodejs.org/dist/latest-v10.x/docs/api/stream.html#stream_writable_streams)
|
314 | to write logs to. Default: `process.stdout`.
|
315 | - `prefix`: the prefix type to use when logging processes output.
|
316 | Possible values: `index`, `pid`, `time`, `command`, `name`, `none`, or a template (eg `[{time} process: {pid}]`).
|
317 | Default: the name of the process, or its index if no name is set.
|
318 | - `prefixColors`: a list of colors as supported by [chalk](https://www.npmjs.com/package/chalk).
|
319 | If concurrently would run more commands than there are colors, the last color is repeated.
|
320 | Prefix colors specified per-command take precedence over this list.
|
321 | - `prefixLength`: how many characters to show when prefixing with `command`. Default: `10`
|
322 | - `raw`: whether raw mode should be used, meaning strictly process output will
|
323 | be logged, without any prefixes, colouring or extra stuff.
|
324 | - `successCondition`: the condition to consider the run was successful.
|
325 | If `first`, only the first process to exit will make up the success of the run; if `last`, the last process that exits will determine whether the run succeeds.
|
326 | Anything else means all processes should exit successfully.
|
327 | - `restartTries`: how many attempts to restart a process that dies will be made. Default: `0`.
|
328 | - `restartDelay`: how many milliseconds to wait between process restarts. Default: `0`.
|
329 | - `timestampFormat`: a [date-fns format](https://date-fns.org/v2.0.1/docs/format)
|
330 | to use when prefixing with `time`. Default: `yyyy-MM-dd HH:mm:ss.ZZZ`
|
331 | - `additionalArguments`: list of additional arguments passed that will get replaced in each command. If not defined, no argument replacing will happen.
|
332 |
|
333 | > **Returns:** an object in the shape `{ result, commands }`.
|
334 | > - `result`: a `Promise` that resolves if the run was successful (according to `successCondition` option),
|
335 | > or rejects, containing an array of [`CloseEvent`](#CloseEvent), in the order that the commands terminated.
|
336 | > - `commands`: an array of all spawned [`Command`s](#Command).
|
337 |
|
338 | Example:
|
339 |
|
340 | ```js
|
341 | const concurrently = require('concurrently');
|
342 | const { result } = concurrently([
|
343 | 'npm:watch-*',
|
344 | { command: 'nodemon', name: 'server' },
|
345 | { command: 'deploy', name: 'deploy', env: { PUBLIC_KEY: '...' } },
|
346 | { command: 'watch', name: 'watch', cwd: path.resolve(__dirname, 'scripts/watchers')}
|
347 | ], {
|
348 | prefix: 'name',
|
349 | killOthers: ['failure', 'success'],
|
350 | restartTries: 3,
|
351 | cwd: path.resolve(__dirname, 'scripts'),
|
352 | });
|
353 | result.then(success, failure);
|
354 | ```
|
355 |
|
356 | ### `Command`
|
357 | An object that contains all information about a spawned command, and ways to interact with it.<br>
|
358 | It has the following properties:
|
359 |
|
360 | - `index`: the index of the command among all commands spawned.
|
361 | - `command`: the command line of the command.
|
362 | - `name`: the name of the command; defaults to an empty string.
|
363 | - `cwd`: the current working directory of the command.
|
364 | - `env`: an object with all the environment variables that the command will be spawned with.
|
365 | - `killed`: whether the command has been killed.
|
366 | - `exited`: whether the command exited yet.
|
367 | - `pid`: the command's process ID.
|
368 | - `stdin`: a Writable stream to the command's `stdin`.
|
369 | - `stdout`: an RxJS observable to the command's `stdout`.
|
370 | - `stderr`: an RxJS observable to the command's `stderr`.
|
371 | - `error`: an RxJS observable to the command's error events (e.g. when it fails to spawn).
|
372 | - `timer`: an RxJS observable to the command's timing events (e.g. starting, stopping).
|
373 | - `close`: an RxJS observable to the command's close events.
|
374 | See [`CloseEvent`](#CloseEvent) for more information.
|
375 | - `start()`: starts the command, setting up all
|
376 | - `kill([signal])`: kills the command, optionally specifying a signal (e.g. `SIGTERM`, `SIGKILL`, etc).
|
377 |
|
378 | ### `CloseEvent`
|
379 | An object with information about a command's closing event.<br>
|
380 | It contains the following properties:
|
381 |
|
382 | - `command`: a stripped down version of [`Command`](#command), including only `name`, `command`, `env` and `cwd` properties.
|
383 | - `index`: the index of the command among all commands spawned.
|
384 | - `killed`: whether the command exited because it was killed.
|
385 | - `exitCode`: the exit code of the command's process, or the signal which it was killed with.
|
386 | - `timings`: an object in the shape `{ startDate, endDate, durationSeconds }`.
|
387 |
|
388 | ## FAQ
|
389 |
|
390 | * Process exited with code *null*?
|
391 |
|
392 | From [Node child_process documentation](http://nodejs.org/api/child_process.html#child_process_event_exit), `exit` event:
|
393 |
|
394 | > This event is emitted after the child process ends. If the process
|
395 | > terminated normally, code is the final exit code of the process,
|
396 | > otherwise null. If the process terminated due to receipt of a signal,
|
397 | > signal is the string name of the signal, otherwise null.
|
398 |
|
399 |
|
400 | So *null* means the process didn't terminate normally. This will make **concurrent**
|
401 | to return non-zero exit code too.
|
402 |
|
403 | * Does this work with the npm-replacements [yarn](https://github.com/yarnpkg/yarn) or [pnpm](https://pnpm.js.org/)?
|
404 |
|
405 | Yes! In all examples above, you may replace "`npm`" with "`yarn`" or "`pnpm`".
|