├── example ├── basic │ ├── index.js │ ├── README.md │ ├── package.json │ └── bitrunnerfile.js ├── dependencies │ ├── index.js │ ├── package.json │ ├── .jshintrc │ ├── bitrunnerfile.js │ └── README.md └── README.md ├── .npmignore ├── .jshintrc ├── .gitignore ├── package.json ├── LICENSE ├── src ├── fetch.js ├── task.js └── taskrunner.js ├── bin └── cli.js └── README.md /example/basic/index.js: -------------------------------------------------------------------------------- 1 | console.log('basic example'); 2 | -------------------------------------------------------------------------------- /example/dependencies/index.js: -------------------------------------------------------------------------------- 1 | console.log('basic example'); 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .jshintrc 2 | .travis.yml 3 | Gruntfile.js 4 | tests 5 | -------------------------------------------------------------------------------- /example/basic/README.md: -------------------------------------------------------------------------------- 1 | # Bais example 2 | This will show you a really basic example where we are defining a task that adds `use strict;` to the source. The only task defined is called `build`. 3 | 4 | #### run it 5 | From example/basic directory 6 | 7 | ``` 8 | npm install bit-runner -g 9 | npm install 10 | bitrunner build 11 | ``` 12 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | ## bit runner Examples 2 | 3 | ### [Basic](https://github.com/MiguelCastillo/bit-runner/tree/master/example/basic) 4 | Example to show a really basic task 5 | 6 | ### [Dependencies](https://github.com/MiguelCastillo/bit-runner/tree/master/example/dependencies) 7 | Example to show how you can setup tasks that depend on other tasks 8 | -------------------------------------------------------------------------------- /example/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "basic", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Miguel Castillo ", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "bit-runner": "~0.0.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "newcap": true, 11 | "noarg": true, 12 | "quotmark": "single", 13 | "undef": true, 14 | "unused": true, 15 | "globals": { 16 | "require": true, 17 | "module": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/dependencies/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dependencies", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Miguel Castillo ", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "bit-runner": "0.0.1" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example/dependencies/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "newcap": true, 11 | "noarg": true, 12 | "quotmark": "single", 13 | "undef": true, 14 | "unused": true, 15 | "globals": { 16 | "require": true, 17 | "module": true 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/basic/bitrunnerfile.js: -------------------------------------------------------------------------------- 1 | var bitRunner = require('bit-runner'); 2 | 3 | /** 4 | * JavaScript pipeline 5 | */ 6 | function buildPipeline(task) { 7 | task 8 | .load('index.js') 9 | .then(function(moduleMeta) { 10 | console.log('Pre transform:\n', moduleMeta.source); 11 | }) 12 | .then(function(moduleMeta) { 13 | moduleMeta.source = '"use strict;"\n' + moduleMeta.source; 14 | }) 15 | .then(function(moduleMeta) { 16 | console.log('Post transform:\n', moduleMeta.source); 17 | }); 18 | } 19 | 20 | bitRunner.register('build', buildPipeline); 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Logs 4 | logs 5 | *.log 6 | 7 | # Runtime data 8 | pids 9 | *.pid 10 | *.seed 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # Compiled binary addons (http://nodejs.org/api/addons.html) 22 | build/Release 23 | 24 | # Dependency directory 25 | # Commenting this out is preferred by some people, see 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 27 | node_modules 28 | 29 | # Users Environment Variables 30 | .lock-wscript 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bit-runner", 3 | "version": "0.0.3", 4 | "description": "JavaScript task runner with a fluent workflow for processing your assests", 5 | "author": "Miguel Castillo ", 6 | "main": "src/taskrunner.js", 7 | "bin": { 8 | "bitrunner": "bin/cli.js" 9 | }, 10 | "scripts": {}, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/MiguelCastillo/bit-runner.git" 14 | }, 15 | "dependencies": { 16 | "minimist": "~1.1.0", 17 | "liftoff": "~2.0.2", 18 | "interpret": "~0.5.0" 19 | }, 20 | "devDependencies": { 21 | "bit-loader": "~0.1.3", 22 | "jshint-stylish": "~1.0.0" 23 | }, 24 | "browser": {}, 25 | "directories": { 26 | "test": "tests" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /example/dependencies/bitrunnerfile.js: -------------------------------------------------------------------------------- 1 | var bitRunner = require('bit-runner'); 2 | 3 | 4 | /** 5 | * JavaScript pipeline 6 | */ 7 | function buildPipeline(task) { 8 | task 9 | .load('package.json') 10 | .then(function(moduleMeta) { 11 | console.log(moduleMeta); 12 | }) 13 | .then(function(moduleMeta) { 14 | console.log(moduleMeta); 15 | }); 16 | } 17 | 18 | 19 | /** 20 | * CoffeeScript pipeline 21 | */ 22 | function releasePipeline(task) { 23 | task 24 | .load('bitrunnerfile.js') 25 | .then(function(moduleMeta) { 26 | console.log(moduleMeta); 27 | }); 28 | } 29 | 30 | 31 | /** 32 | * Minify pipeline 33 | */ 34 | function minifyPipeline(task) { 35 | task 36 | .load('.jshintrc') 37 | .then(function(moduleMeta) { 38 | console.log(moduleMeta); 39 | }); 40 | } 41 | 42 | 43 | bitRunner 44 | .register('default', ['build']) 45 | .register('build', ['release', 'minify'], buildPipeline) 46 | .register('release', ['minify'], releasePipeline) 47 | .register('minify', minifyPipeline); 48 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 miguel @manchagnu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /example/dependencies/README.md: -------------------------------------------------------------------------------- 1 | # Task dependency example 2 | A task can sepecify dependencies on other tasks in order to define a uniform task sequence that executes as a single unit. The output from one task is *piped* to the next task in the sequence to avoid unnecessary I/O. 3 | 4 | This example will show you how you can define multiple tasks, and establish dependencies amongst them. The primary task is `build`, which has a dependency on `release` and `minify` (two artificial tasks). Furthermore, the `release` task has a dependency on `minify`. 5 | 6 | This setup will makes sure that before `build` runs, `release` and `minify` do. And before `release` runs, `minify` does. When you run the `build` task, this creates a sequence like this: 7 | 1. `build` -> [`release`, `minify`] 8 | 2. `release` -> `minify` 9 | 10 | The end result is executing the tasks in the following order: 11 | 1. `minify` 12 | 2. `release` 13 | 3. `build` 14 | 15 | One thing that is important to note is that registered tasks can be chained in any way you need. And when a task is executed by the `cli`, their execution sequence is completely independent from other tasks' execution sequence. For example, you could run `bitrunner build`, and that task will run completely independent from the `bitrunner release`. This allows maximum reuse of tasks where you can create a bunch little micro tasks that you chain together in whatever way you need. 16 | 17 | #### run it 18 | From example/dependencies directory 19 | 20 | ``` 21 | npm install bit-runner -g 22 | npm install 23 | bitrunner build 24 | ``` 25 | -------------------------------------------------------------------------------- /src/fetch.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var Bitloader = require('bit-loader'); 3 | var util = Bitloader.Utils; 4 | 5 | 6 | /** 7 | * FetchFactory provides a fetch interface that is used by bit loader 8 | * to load files from storage. 9 | * 10 | * @private 11 | * 12 | * @param {Bitloader} loader - bit loader instance 13 | */ 14 | function fetchFactory(loader) { 15 | // Compile is called with the module meta as the context. 16 | function compile() { 17 | return new loader.Module({code: (void 0)}); 18 | } 19 | 20 | // Creates module meta objects that bit loader gets back 21 | function moduleMetaFactory(source) { 22 | return { 23 | compile: compile, 24 | source: source 25 | }; 26 | } 27 | 28 | // Return fetch interface 29 | return { 30 | // The only interface that is needed by bit loader 31 | fetch: function(name) { 32 | // Read file from disk and return a module meta 33 | return readFile(name) 34 | .then(moduleMetaFactory, util.forwardError); 35 | } 36 | }; 37 | } 38 | 39 | 40 | /** 41 | * Read file from storage. You can very easily replace this with a routine 42 | * that loads data using XHR. 43 | * 44 | * @private 45 | * 46 | * @param {string} fileName - Name of the file to read 47 | * 48 | * @returns {Promise} 49 | */ 50 | function readFile(fileName) { 51 | return new Bitloader.Promise(function(resolve, reject) { 52 | var filecontent = ''; 53 | var stream = fs.createReadStream(fileName); 54 | stream.setEncoding('utf8'); 55 | 56 | stream 57 | .on('readable', function() { 58 | filecontent += stream.read(); 59 | }) 60 | .on('end', function() { 61 | resolve(filecontent); 62 | }) 63 | .on('error', reject); 64 | }); 65 | } 66 | 67 | 68 | module.exports = fetchFactory; 69 | -------------------------------------------------------------------------------- /bin/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var Liftoff = require('liftoff'); 4 | var argv = require('minimist')(process.argv.slice(2)); 5 | var tasks = argv._.length ? argv._ : ['default']; 6 | 7 | 8 | var bitrunner = new Liftoff({ 9 | name: 'bit-runner', 10 | configName: 'bitrunnerfile', 11 | extensions: require('interpret').jsVariants, 12 | v8flags: ['--harmony'] 13 | }) 14 | .on('require', function (name /*, module*/) { 15 | console.log('Loading:',name); 16 | }) 17 | .on('requireFail', function (name, err) { 18 | console.log('Unable to load:', name, err); 19 | }) 20 | .on('respawn', function (flags, child) { 21 | console.log('Detected node flags:', flags); 22 | console.log('Respawned to PID:', child.pid); 23 | }); 24 | 25 | 26 | bitrunner.launch({ 27 | cwd: argv.cwd, 28 | configPath: argv.bitrunnerfile, 29 | require: argv.require, 30 | completion: argv.completion, 31 | verbose: argv.verbose 32 | }, invoke); 33 | 34 | 35 | function invoke (env) { 36 | if (argv.verbose) { 37 | console.log('LIFTOFF SETTINGS:', this); 38 | console.log('CLI OPTIONS:', argv); 39 | console.log('CWD:', env.cwd); 40 | console.log('LOCAL MODULES PRELOADED:', env.require); 41 | console.log('SEARCHING FOR:', env.configNameRegex); 42 | console.log('FOUND CONFIG AT:', env.configPath); 43 | console.log('CONFIG BASE DIR:', env.configBase); 44 | console.log('YOUR LOCAL MODULE IS LOCATED:', env.modulePath); 45 | console.log('LOCAL PACKAGE.JSON:', env.modulePackage); 46 | console.log('CLI PACKAGE.JSON', require('../package')); 47 | } 48 | 49 | if (process.cwd() !== env.cwd) { 50 | process.chdir(env.cwd); 51 | console.log('Working directory changed to', env.cwd); 52 | } 53 | 54 | if (!env.modulePath) { 55 | console.log('Local bit-runner not found in:', env.cwd); 56 | process.exit(1); 57 | } 58 | 59 | if (env.configPath) { 60 | require(env.configPath); 61 | } 62 | else { 63 | console.log('No bitrunnerfile found.'); 64 | } 65 | 66 | var bitrunner = require(env.modulePath); 67 | var i, length; 68 | for (i = 0, length = tasks.length; i < length; i++) { 69 | bitrunner.run(tasks[i]); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/task.js: -------------------------------------------------------------------------------- 1 | var fetchFactory = require('./fetch'); 2 | var Bitloader = require('bit-loader'); 3 | var util = Bitloader.Utils; 4 | 5 | 6 | /** 7 | * @class 8 | * 9 | * Task that can be executed by the task runner 10 | */ 11 | function Task(taskrunner, name, deps, cb, parent) { 12 | var task = this; 13 | var loader = (parent && parent._loader) || new Bitloader({}, {fetch: fetchFactory}); 14 | var src; 15 | 16 | this._loader = loader; 17 | this._parent = parent; 18 | this._tasks = {}; 19 | this.name = name; 20 | this.init = init.bind(this); 21 | this.run = run.bind(this); 22 | this.load = load.bind(this); 23 | this.then = then.bind(this); 24 | 25 | // Make sure to tell the parent we are their child! 26 | if (parent) { 27 | parent.setTask(name, this); 28 | } 29 | 30 | 31 | function init(args) { 32 | src = []; 33 | 34 | if (typeof(cb) === 'function') { 35 | cb.apply(task, [task].concat(args)); 36 | } 37 | 38 | return task; 39 | } 40 | 41 | function run() { 42 | if (deps.length) { 43 | var sequence = deps.reduce(function(runner, name) { 44 | return runner.then(subtask(name), util.printError); 45 | }, Bitloader.Promise.resolve()); 46 | 47 | return sequence.then(function() { 48 | if (src.length) { 49 | return loader.import(src); 50 | } 51 | }, util.printError); 52 | } 53 | else if (src.length) { 54 | return loader.import(src); 55 | } 56 | } 57 | 58 | function load() { 59 | src = src.concat.apply(src, arguments); 60 | return task; 61 | } 62 | 63 | function then(cb) { 64 | loader.transform.use(cb); 65 | return task; 66 | } 67 | 68 | function subtask(name) { 69 | return function() { 70 | return taskrunner.subtask(name, task); 71 | }; 72 | } 73 | } 74 | 75 | 76 | Task.prototype.getTask = function(name) { 77 | return this._tasks[name]; 78 | }; 79 | 80 | 81 | Task.prototype.setTask = function(name, task) { 82 | if (this._tasks[name]) { 83 | throw new TypeError('Subtask "' + name + '" already exists'); 84 | } 85 | 86 | this._tasks[name] = task; 87 | }; 88 | 89 | 90 | Task.prototype.init = function() {}; 91 | Task.prototype.run = function() {}; 92 | Task.prototype.load = function() {}; 93 | Task.prototype.then = function() {}; 94 | 95 | 96 | module.exports = Task; 97 | -------------------------------------------------------------------------------- /src/taskrunner.js: -------------------------------------------------------------------------------- 1 | var Task = require('./task'); 2 | var Bitloader = require('bit-loader'); 3 | var util = Bitloader.Utils; 4 | var slice = Array.prototype.slice; 5 | 6 | 7 | /** 8 | * @class 9 | * 10 | * Interface for registering and running tasks 11 | */ 12 | function TaskRunner() { 13 | this._tasks = {}; 14 | this._factory = {}; 15 | 16 | // Bind so that we do not lose the context 17 | this.register = register.bind(this); 18 | this.run = runtask.bind(this); 19 | this.subtask = runsubtask.bind(this); 20 | } 21 | 22 | 23 | /** Convenieve promise provider */ 24 | TaskRunner.prototype.Promise = Bitloader.Promise; 25 | 26 | /** Convenience utilities */ 27 | TaskRunner.prototype.util = util; 28 | 29 | /** Method to register a task */ 30 | TaskRunner.prototype.register = function() {}; 31 | 32 | 33 | /** 34 | * Method to run a task without providing back a wayt to tell when the task is 35 | * done. 36 | * 37 | * @param {string} name - Name of the task to run 38 | * 39 | * @returns {TaskRunner} 40 | */ 41 | TaskRunner.prototype.run = function() {}; 42 | 43 | 44 | /** 45 | * Method to run a subtask task and return a promise that will be resolved when the 46 | * subtask is finished 47 | * 48 | * @param {string} name - Name of the task to run 49 | * 50 | * @returns {Promise} 51 | */ 52 | TaskRunner.prototype.subtask = function() {}; 53 | 54 | 55 | /** @private */ 56 | function register(name, deps, cb) { 57 | if (!util.isString(name)) { 58 | throw new TypeError('Must provide a name for the task'); 59 | } 60 | 61 | if (util.isFunction(deps)) { 62 | cb = deps; 63 | deps = []; 64 | } 65 | 66 | if (this._factory.hasOwnProperty(name)) { 67 | throw new TypeError('Task "' + name + '" is already registered'); 68 | } 69 | 70 | // Set a task factory 71 | this._factory[name] = taskFactory.call(this, name, deps, cb); 72 | return this; 73 | } 74 | 75 | 76 | /** @private */ 77 | function runtask(name) { 78 | var task = this._tasks[name] || (this._tasks[name] = createTask.call(this, name)); 79 | _run(task, slice.call(arguments, 1)); 80 | return this; 81 | } 82 | 83 | 84 | /** @private */ 85 | function runsubtask(name, parent) { 86 | var subtask = parent.getTask(name) || createTask.call(this, name, parent); 87 | return _run(subtask, slice.call(arguments, 2)); 88 | } 89 | 90 | 91 | /** @private */ 92 | function _run(task) { 93 | return task 94 | .init(slice.call(arguments, 1)) 95 | .run(); 96 | } 97 | 98 | 99 | /** @private */ 100 | function createTask(name, parent) { 101 | var factory = this._factory.hasOwnProperty(name); 102 | 103 | if (!factory) { 104 | throw new TypeError('Task "' + name + '" has not yet been registered'); 105 | } 106 | 107 | return this._factory[name](parent); 108 | } 109 | 110 | 111 | /** @private */ 112 | function taskFactory(name, deps, cb) { 113 | var taskRunner = this; 114 | return function factory(parent) { 115 | return new Task(taskRunner, name, deps, cb, parent); 116 | }; 117 | } 118 | 119 | 120 | module.exports = new TaskRunner(); 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bit-runner 2 | JS Task Runner that's easily configured to run complex sequences of tasks. 3 | 4 | > The underlying engine is [bit loader](https://github.com/MiguelCastillo/bit-loader) to provide the *transformation* workflow. 5 | 6 | 7 | ### Summary 8 | bit runner's primary goal is to executes tasks. But the pipeline that executes these tasks is optimaized to reduce I/O operations by piping data from one task to another. 9 | 10 | So, what is a task? A task is a sequence of *actions* that are executed to process your assests. *You* define what these actions are. An action can be to simply add `use strict;` to your JavaScript. 11 | 12 | A task can also sepecify dependencies on other tasks. This allows you to define a uniform *task sequence* that executes as a single unit, where the output from one task is *piped* to the next task in the sequence to reduce unnecessary I/O. 13 | 14 | An important feature of the ability to set dependencies is that you can piece together complex sequences of micro tasks - tasks that do small jobs. When a task is executed by the `cli`, its execution sequence is completely independent from other tasks' execution sequence. For example, you could run `bitrunner build`, and that task will run completely independent from `bitrunner release`, even if they have common task dependencies and they are executed simultaneously. This allows for elegant compositions of sequences of micro tasks. 15 | 16 | > Quick note: A task is what bit runner executes. Actions is what a task executes. Bit runner executes a sequence of tasks, and a task executes a sequence of actions. 17 | 18 | 19 | #### Oversimplified illustration of a task sequence 20 | 21 | - Task: read from disk 22 | - Action: read `file1.js` 23 | - Task: transpile 24 | - Action: run [babel](https://babeljs.io/) 25 | - Task: build 26 | - Action: add `use strict` 27 | - Action: add `# sourceURL` 28 | - Action: load dependencies 29 | - Task: minify 30 | - Action: run [uglify](https://github.com/mishoo/UglifyJS2) 31 | 32 | In all that sequence, there was only one read from disk! 33 | 34 | 35 | ### Setup 36 | 37 | #### Install 38 | 39 | First, you need to install *bit-runner* globally so that the bit-runner cli can be added to the *PATH*. This way you can call `bitrunner` from anywhere. 40 | ``` 41 | npm install bit-runner -g 42 | ``` 43 | 44 | Now that you have the cli in your *PATH*, you need to install bit-runner in your project. So from your project's root directory: 45 | ``` 46 | npm install bit-runner --save-dev 47 | ``` 48 | 49 | #### Configuration 50 | When you execute bit runner's cli, it automatically loads `bitrunnerfile.js` from your project in order to load your tasks. Here is a basic configuration with a single task called `build`: 51 | 52 | ``` javascript 53 | var bitRunner = require('bit-runner'); 54 | 55 | /** 56 | * JavaScript pipeline 57 | */ 58 | function buildPipeline(task) { 59 | task 60 | .load('index.js') 61 | .then(function action(moduleMeta) { 62 | moduleMeta.source = "'use strict;'\n" + moduleMeta.source; 63 | }) 64 | .then(function action(moduleMeta) { 65 | moduleMeta.source = coffeescript.compile(moduleMeta.source); 66 | }); 67 | } 68 | 69 | bitRunner.register('build', buildPipeline); 70 | ``` 71 | 72 | #### Running it 73 | So, you have installed bit-runner and created a configuration in your project. Now you are ready to run your task(s). From your project's root directory: 74 | 75 | ``` 76 | bitrunner build 77 | ``` 78 | 79 | You can call bitrunner with a list of tasks, in which case bit runner is going to run them in parallel. Or if you don't provide a task name, then the `default` task is executed. 80 | 81 | The following will execute `build` and `docs` in parallel. 82 | ``` 83 | bitrunner build docs 84 | ``` 85 | 86 | The following will execute `default` 87 | ``` 88 | bitrunner 89 | ``` 90 | 91 | 92 | ### Examples 93 | Please see [examples](https://github.com/MiguelCastillo/bit-runner/tree/master/example) that illustrate different techniques for configuring bit runner. 94 | --------------------------------------------------------------------------------