Gathering detailed insights and metrics for @xarc/run
Gathering detailed insights and metrics for @xarc/run
Gathering detailed insights and metrics for @xarc/run
Gathering detailed insights and metrics for @xarc/run
npm install @xarc/run
Typescript
Module System
Node Version
NPM Version
JavaScript (99.98%)
Shell (0.02%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
Apache-2.0 License
43 Stars
266 Commits
9 Forks
3 Watchers
2 Branches
7 Contributors
Updated on Feb 09, 2025
Latest Version
2.1.3
Package Id
@xarc/run@2.1.3
Unpacked Size
120.24 kB
Size
36.12 kB
File Count
38
NPM Version
11.4.2
Node Version
24.3.0
Published on
Jul 06, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
npm run
enhanced - A powerful task runner and build tool for modern JavaScript projects.
npm run
for npm scriptsThis module provides a command xrun
to run all your npm scripts in package.json
.
And you can run multiple of them concurrently or serially.
Some examples below:
what you want to do | npm command | xrun command |
---|---|---|
run test | npm run test | xrun test |
run lint and test concurrently | N/A | xrun lint test |
run lint and then test serially | N/A | xrun --serial lint test |
Alias for the options:
-s
: --serial
You can write your tasks in JavaScript and run them with xrun
.
This is useful when a shell script is too long to fit in a JSON string, or when it's not easy to do something with shell script.
These APIs are provided: concurrent
, serial
, exec
, env
, and load
.
Put your tasks in a file xrun-tasks.js
and xrun
will load it automatically.
An example xrun-tasks.js
:
1const { load, exec, concurrent, serial } = require("@xarc/run"); 2load({ 3 // 4 // define a task hello, with a string definition 5 // because a string is the task's direct value, it will be executed as a shell command. 6 // 7 hello: "echo hello", 8 // 9 // define a task world, using a JavaScript function to print something 10 // 11 world: () => console.log("world"), 12 // 13 // define a task serialTask, that will execute the three tasks serially, first two are 14 // the hello and world tasks defined above, and 3rd one is a shell command defined with exec. 15 // because the 3rd one is not a direct value of a task, it has to use exec to define a shell command. 16 // 17 serialTask: serial("hello", "world", exec("echo hi from exec")), 18 // 19 // define a task concurrentTask, that will execute the three tasks concurrently 20 // 21 concurrentTask: concurrent("hello", "world", exec("echo hi from exec")), 22 // 23 // define a task nesting, that does complex nesting of concurrent/serial constructs 24 // 25 nesting: concurrent(serial("hello", "world"), serial("serialTask", concurrent("hello", "world"))) 26});
To run the tasks defined above from the command prompt, below are some examples:
what you want to do | command |
---|---|
run hello | xrun hello |
run hello and world concurrently | xrun hello world |
run hello and then world serially | xrun --serial hello world |
exec
and shell scriptsUse exec
to invoke a shell command from JavaScript.
Here are some examples:
shell script in JSON string | shell script using exec in JavaScript | note |
---|---|---|
echo hello | exec("echo hello") | |
FOO=bar echo hello $FOO | exec("FOO=bar echo hello $FOO") | |
echo hello && echo world | exec("echo hello && echo world") | |
echo hello && echo world | serial(exec("echo hello"), exec("echo world")) | using serial instead of && |
exec
supports options
that can set a few things. Some examples below:what you want to do | shell script using exec in JavaScript |
---|---|
setting an env variable | exec("echo hello $FOO", {env: {FOO: "bar"}}) |
provide tty to the shell process | exec("echo hello", {flags: "tty"}) |
using spawn with tty, and setting env | exec("echo hello $FOO", {flags: "tty,spawn", env: {FOO: "bar"}}) |
A task in JavaScript can be just a function.
1load({ 2 hello: () => console.log("hello") 3});
A function task can do a few things:
xrun
will wait for the Promise.xrun
will wait for the stream to end.xrun
to execute further.context.argOpts
.Example:
1load({ 2 // A function task named hello that access parsed options with `context.argOpts` 3 async hello(context) { 4 console.log("hello argOpts:", context.argOpts); 5 return ["foo"]; 6 }, 7 h2: ["hello world"], 8 foo: "echo bar" 9});
concurrent
and serial
Use concurrent
and serial
to define a task that run multiple other tasks concurrently or serially.
Some examples:
echo hello && echo world
:1serial(exec("echo hello"), exec("echo world"));
1concurrent(exec("echo hello"), exec("echo world"));
1serial( 2 exec("echo hello"), 3 () => console.log("world"), 4 "name-of-a-task", 5 concurrent("task1", "task2") 6);
process.env
env
allows you to create a task to set variables in process.env
.
You use it by passing an object of env vars, like env({VAR_NAME: "var-value"})
Examples:
1load({ 2 setEnv: serial(env({ FOO: "bar" }), () => console.log(process.env.FOO)) 3});
A popular CI/CD use case is to start servers and then run tests, which can be achieved using xrun
JavaScript tasks:
1const { concurrent, serial, load, stop } = require("@xarc/run"); 2const waitOn = require("wait-on"); 3 4const waitUrl = url => waitOn({ resources: [url] }); 5 6load({ 7 "start-server-and-test": concurrent( 8 // start the servers concurrently 9 concurrent("start-mock-server", "start-app-server"), 10 serial( 11 // wait for servers concurrently, and then run tests 12 concurrent("wait-mock-server", "wait-app-server"), 13 "run-tests", 14 // Finally stop servers and exit. 15 // This is only needed because there are long running servers. 16 () => stop() 17 ) 18 ), 19 "start-mock-server": "mock-server", 20 "start-app-server": "node lib/server", 21 "wait-mock-server": () => waitUrl("http://localhost:8000"), 22 "wait-app-server": () => waitUrl("http://localhost:3000"), 23 "run-tests": "cypress run --headless -b chrome" 24});
xrun
addsnode_modules/.bin
to PATH. That's whynpx
is not needed to run commands likecypress
that's installed innode_modules
.
@xarc/run
supports provider packages - reusable task libraries that can be shared across projects. This allows teams to standardize common build tasks and workflows.
A provider package is identified by either:
xrunProvider
config in its package.json
@xarc/run
as a dependency1// In your provider package's package.json 2{ 3 "name": "my-build-tasks", 4 "xrunProvider": { 5 "module": "tasks.js" // optional: specify which module exports loadTasks 6 } 7}
1// In your provider's tasks.js (or main module) 2module.exports = { 3 loadTasks(xrun) { 4 // can pass in optional namespace with xrun.load("namespace", {...}) 5 return xrun.load({ 6 build: "webpack --mode=production", 7 test: "jest", 8 lint: "eslint src/", 9 ci: ["lint", "test", "build"] 10 }); 11 } 12};
Provider packages are automatically loaded when:
loadProviderModules: true
in your @xarc/run
configProvider tasks are loaded from:
dependencies
devDependencies
optionalDependencies
Example package.json
:
1{ 2 "name": "my-app", 3 "dependencies": { 4 "my-build-tasks": "^1.0.0" 5 }, 6 "@xarc/run": { 7 "loadProviderModules": true 8 } 9}
Now you can run provider tasks directly:
1xrun build # runs the build task from my-build-tasks 2xrun ci # runs the ci task which executes lint, test, build serially
Not a fan of full API names like concurrent
, serial
, exec
? You can skip them.
concurrent
: Any array of tasks are concurrent, except when they are specified at the top level.exec
: Any string starting with ~$
are treated as shell script.serial
: An array of tasks specified at the top level is executed serially.Example:
1load({ 2 executeSerially: ["task1", "task2"], // top level array serially 3 concurrentArray: [["task1", "task2"]], // Any other array (the one within) are concurrent 4 topLevelShell: "echo hello", // top level string is a shell script 5 shellScripts: [ 6 "~$echo hello", // any string started with ~$ is shell script 7 "~(tty,spawn)$echo hello" // also possible to specify tty and spawn flag between ~ and $ 8 ] 9});
Core Execution Engine
Developer Experience
package.json
--
remaining args supportExtensibility & Organization
Advanced Features
env()
tasksexec()
and spawn optionsStill reading? Maybe you want to take it for a test drive?
Here is a simple sample.
1mkdir xrun-test 2cd xrun-test 3npm init --yes 4npm install rimraf @xarc/run
xrun-tasks.js
:1"use strict"; 2const { load } = require("@xarc/run"); 3 4const tasks = { 5 hello: "echo hello world", // a shell command to be exec'ed 6 jsFunc() { 7 console.log("JS hello world"); 8 }, 9 both: ["hello", "jsFunc"] // execute the two tasks serially 10}; 11 12// Load the tasks into @xarc/run 13load(tasks);
what to do | command |
---|---|
run the task hello | xrun hello |
run the task jsFunc | xrun jsFunc |
run the task both | xrun both |
run hello and jsFunc concurrently | xrun hello jsFunc |
run hello and jsFunc serially | xrun --serial hello jsFunc |
Here is a more complex example to showcase a few more features:
1"use strict"; 2 3const util = require("util"); 4const { exec, concurrent, serial, env, load } = require("@xarc/run"); 5const rimraf = util.promisify(require("rimraf")); 6 7const tasks = { 8 hello: "echo hello world", 9 jsFunc() { 10 console.log("JS hello world"); 11 }, 12 both: { 13 desc: "invoke tasks hello and jsFunc in serial order", 14 // only array at top level like this is default to serial, other times 15 // they are default to concurrent, or they can be marked explicitly 16 // with the serial and concurrent APIs (below). 17 task: ["hello", "jsFunc"] 18 }, 19 // invoke tasks hello and jsFunc concurrently as a simple concurrent array 20 both2: concurrent("hello", "jsFunc"), 21 shell: { 22 desc: "Run a shell command with TTY control and set an env", 23 task: exec({ cmd: "echo test", flags: "tty", env: { foo: "bar" } }) 24 }, 25 babel: exec("babel src -D lib"), 26 // serial array of two tasks, first one to set env, second to invoke the babel task. 27 compile: serial(env({ BABEL_ENV: "production" }), "babel"), 28 // more complex nesting serial/concurrent tasks. 29 build: { 30 desc: "Run production build", 31 task: serial( 32 () => rimraf("dist"), // cleanup, (returning a promise will be awaited) 33 env({ NODE_ENV: "production" }), // set env 34 concurrent("babel", exec("webpack")) // invoke babel task and run webpack concurrently 35 ) 36 } 37}; 38 39load(tasks);
If you'd like to get the command xrun
globally, you can install this module globally.
1$ npm install -g @xarc/run
However, it will still try to require
and use the copy from your node_modules
if you installed it.
If you don't want to use the CLI, you can load and invoke tasks in your JavaScript code using the run
API.
Example:
1const { run, load, concurrent } = require("@xarc/run"); 2const myTasks = require("./tools/tasks"); 3 4load(myTasks); 5// assume task1 and task2 are defined, below will run them concurrently 6run(concurrent("task1", "task2"), err => { 7 if (err) { 8 console.log("run tasks failed", err); 9 } else { 10 console.log("tasks completed"); 11 } 12});
Promise version of
run
isasyncRun
Name your task file xrun-tasks.ts
if you want to use TypeScript.
You need to install a TypeScript runtime to your node_modules
. @xarc/run
supports both tsx (recommended) and ts-node:
1# Recommended: tsx (faster, better ESM support) 2npm install -D tsx typescript 3 4# Alternative: ts-node 5npm install -D ts-node typescript
xrun
automatically detects and loads the appropriate TypeScript runtime when it finds xrun-tasks.ts
, xrun-tasks.tsx
, or xrun-tasks.mts
files. It tries tsx
first, then falls back to ts-node/register
.
Any task can be invoked with the command xrun
:
1$ xrun task1 [task1 options] [<task2> ... <taskN>]
ie:
1$ xrun build
You can pass arguments after --
to shell commands. These arguments are automatically appended to the last shell task:
1$ xrun build -- --watch --verbose 2$ xrun test -- --grep "specific test"
For JavaScript function tasks, parsed options are available via the context
param:
It's also pass as the this
context for the function.
1load({ 2 myTask(context) { 3 console.log("Parsed options:", context.argOpts); 4 } 5});
Common CLI options include:
--serial
, -s
- Execute tasks serially instead of concurrently--cwd <path>
, -w
- Set working directory--list
, -l
- List available tasks--npm
, -n
- Load npm scripts (default: true)--quiet
, -q
- Suppress output--soe <mode>
, -e
- Stop on error mode: no
, soft
, full
For complete CLI reference:
1$ xrun -h
See CLI Options for full details.
To load npm scripts into the npm
namespace, use the --npm
option:
This is enabled by default. To turn it off use --no-npm
option.
1$ xrun --npm test
You can also specify command line options under @xarc/run
in your package.json
.
You can specify your tasks as an array from the command line.
For example, to have xrun
execute the tasks [ task_a, task_b ]
concurrently:
1$ xrun [ task_a, task_b ]
You can also execute them serially with:
1$ xrun --serial [ task_a, task_b ]
You can execute tasks serially, and then some tasks concurrently:
1$ xrun --serial [task_a, task_b, [task_c1, task_c2]]
will execute
task_a
, thentask_b
, and finallytask_c1
andtask_c2
concurrently.
You can pass the whole array in as a single string, which will be parsed as an array with string elements only.
1$ xrun "[task_a, task_b, [task_c1, task_c2]]"
Task name is any alphanumeric string that does not contain /
, or starts with ?
or ~$
.
Tasks can be invoked from command line:
xrun foo/task1
indicates to execute task1
in namespace foo
xrun ?task1
or xrun ?foo/task1
indicates that executing task1
is optional.xrun
treats these characters as special:
/
as namespace separator?
to let you indicate that the execution of a task is optional so it won't fail if the task is not found.~$
to indicate the task to be a string as a shell commandBy prefixing the task name with ?
when invoking, you can indicate the execution of a task as optional so it won't fail in case the task is not found.
For example:
xrun ?foo/task1
or xrun ?task1
won't fail if task1
is not found.A task can be string
, array
, function
, or object
. See reference for details.
You can define @xarc/run tasks and options in your package.json
.
You can also define xrun tasks without JavaScript capability in your package.json
.
They will be loaded into a namespace pkg
.
For example:
1{ 2 "name": "my-app", 3 "@xarc/run": { 4 "tasks": { 5 "task1": "echo hello from package.json", 6 "task2": "echo hello from package.json", 7 "foo": ["task1", "task2"] 8 } 9 } 10}
And you can invoke them with xrun pkg/foo
, or xrun foo
if there are no other namespace with a task named foo
.
Command line options can also be specified under @xarc/run
or xrun
inside your package.json
.
For example:
1{ 2 "name": "my-app", 3 "@xarc/run": { 4 "npm": true 5 } 6}
You can provide a JS function for a task that executes asynchronously. Your function just need to take a callback or return a Promise or a node.js stream.
ie:
1const tasks = { 2 cb_async: (cb) => { 3 setTimeout(cb, 10); 4 }, 5 promise_async: () => { 6 return new Promise(resolve => { 7 setTimeout(resolve, 10); 8 } 9 } 10}
See reference for more detailed information on features such as load tasks into namespace, and setup auto complete with namespace for your shell.
Licensed under the Apache License, Version 2.0
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
0 existing vulnerabilities detected
Reason
license file detected
Details
Reason
Found 0/30 approved changesets -- score normalized to 0
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no SAST tool detected
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More