{"id":13532520,"url":"https://github.com/folke/ultra-runner","last_synced_at":"2025-05-12T15:28:05.452Z","repository":{"id":37024372,"uuid":"235535078","full_name":"folke/ultra-runner","owner":"folke","description":"🏃⛰ Ultra fast monorepo script runner and build tool","archived":false,"fork":false,"pushed_at":"2025-05-02T22:05:43.000Z","size":3315,"stargazers_count":1214,"open_issues_count":53,"forks_count":32,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-05-02T23:18:50.925Z","etag":null,"topics":["build","build-tool","concurrent","hacktoberfest","lerna","monorepo","npm","npm-scripts","parallel","pnpm","script-runn","script-runner","yarn-workspaces"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/ultra-runner","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/folke.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-01-22T09:03:54.000Z","updated_at":"2025-04-16T22:38:23.000Z","dependencies_parsed_at":"2023-12-24T08:25:13.591Z","dependency_job_id":"37df38b9-80be-49fb-8876-b554283fa4b8","html_url":"https://github.com/folke/ultra-runner","commit_stats":{"total_commits":405,"total_committers":12,"mean_commits":33.75,"dds":0.345679012345679,"last_synced_commit":"f8fcd3dc6ecbabd6c9629dba53fc3fcbe828133a"},"previous_names":[],"tags_count":47,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/folke%2Fultra-runner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/folke%2Fultra-runner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/folke%2Fultra-runner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/folke%2Fultra-runner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/folke","download_url":"https://codeload.github.com/folke/ultra-runner/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253765193,"owners_count":21960687,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build","build-tool","concurrent","hacktoberfest","lerna","monorepo","npm","npm-scripts","parallel","pnpm","script-runn","script-runner","yarn-workspaces"],"created_at":"2024-08-01T07:01:11.588Z","updated_at":"2025-05-12T15:28:05.423Z","avatar_url":"https://github.com/folke.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","仓库管理工具","npm"],"sub_categories":[],"readme":"# :runner: :mountain: Ultra Runner\n\n[![github badge](https://github.com/folke/ultra-runner/workflows/Node%20CI/badge.svg)](https://github.com/folke/ultra-runner/actions?query=workflow%3A%22Node+CI%22) [![Coverage Status](https://coveralls.io/repos/github/folke/ultra-runner/badge.svg?branch=master)](https://coveralls.io/github/folke/ultra-runner?branch=master) [![npm](https://img.shields.io/npm/v/ultra-runner)](https://www.npmjs.com/package/ultra-runner) [![GitHub](https://img.shields.io/github/license/folke/ultra-runner)](https://github.com/folke/ultra-runner/blob/master/LICENSE) [![GitHub top language](https://img.shields.io/github/languages/top/folke/ultra-runner)](https://github.com/folke/ultra-runner/) [![Renovate](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com)\n\n**Ultra fast** monorepo script runner and build tool.\n\n## :sparkles: Features\n\n* **zero-config**: works out of the box with your existing monorepo\n* **non-intrusive**: no need to make any changes to your packages.json files\n* **workspaces**: detects packages in existing `lerna`, `yarn`, `npm@7` and `pnpm` workspaces, or recursively searches them\n* **ultra fast builds**: `ultra` keeps track of file changes in your repo and only actually `build` a package when needed\n* **parallel builds**: `ultra` builds your packages concurrently by default\n* **workspace dependencies**: workspace dependencies are automatically resolved and used for parallel builds\n* **execute anything**: one command to run package scripts, `node_modules` binaries or system binaries, recursively in your repository.\n* **faster script execution**: `ultra` hijacks any `npm`, `pnpm`, `yarn` and `npx` calls for faster execution.\n* **concurrency within scripts**: you can add optional configuration to `package.json` to run parts of a script in parallel. No need to change the actual `scripts`\n* **filtering**: filter on package names or subdirectories\n* **monitoring**: node process monitor *(like `top` for node)*\n* **output zooming** when executing multiple commands in parallel, `ultra` will try to keep as much concurrent output on the screen as possible, by only showing the last lines of the commands. Once the commands complete running, a full log is written to the terminal. This is very useful when building a bunch of packages with `--watch` for instance.\n* **missing scripts** when executing scripts recursively, only packages that have the script defined, will execute it.\n\n🎥 [View Demo](assets/demo.svg?sanitize=true)\n\n## Workspaces\n\n## :nerd_face: Smart\n\n**Ultra** parses your `package.json` and hijacks any `npm run`, `yarn` and `npx` calls.\nShell operators like `\u0026\u0026`, `;` and `||` are also interpreted.\n\nFor example:\n\n```json\n{\n  \"scripts\": {\n    \"lint\": \"yarn lint:ts \u0026\u0026 yarn lint:eslint \u0026\u0026 yarn lint:docs\",\n    \"lint:eslint\": \"npx eslint bin/*.js src/*.ts __tests__/*.ts --cache\",\n    \"lint:docs\": \"npx markdownlint README.md\",\n    \"lint:ts\": \"npx tsc -p tsconfig.build.json --noEmit\",\n    \"lint:fix\": \"yarn lint:eslint --fix\"\n  }\n}\n```\n\nRunning `ultra lint`\n![Ultra Lint](assets/ultra-lint.png)\n\nRunning `ultra lint:fix` will spawn exactly **one** child process, directly with the correct command, instead of spawning `yarn` intermediately\n\n**Ultra** will additionally execute any configured `pre` and `post` scripts, just like `npm run` and `yarn run`.\n\n## :palm_tree: Recursive Execution\n\nWhen using `-r` or `--recursive`, the command will be executed in every package of your repository, **excluding the root package**. If you also want to run in the root package, combine `--recursive` with `--root`.\nCommands are always run concurrently with a default concurrency of `10` (can be changed with `--concurrency`)\n\n**Ultra** finds packages based on your monorepo workspace:\n\n* lerna\n* pnpm\n* yarn workspace\n* when no monorepo manager was found, we look recursively for packages\n\nUse `--filter \u003cfilter\u003e` to filter packages in the workspace. The filter argument can use wildcards to filter package names and/or subdirectories:\n\n```shell\n$ ultra -r --filter \"@scope/app\" pwd\n...\n\n$ ultra -r --filter \"@scope/*\" pwd\n...\n\n$ ultra -r --filter \"apps/*\" pwd\n...\n```\n\nWhen the filter is prefixed with a `+`, then all dependencies of the filtered packages will also be included.\nFor example, let's say you have a package \"app1\" that depends on \"lib1\", then using the filter `+app1`, will execute the command\non both `app1` **and** `lib1`, using the workspace topology.\n\n## :package: Builds\n\n`Ultra` automatically detects workspace dependencies, while still allowing parallel builds. Packages are build concurrently as soon as their dependencies are build (also concurrently).\nEvery package directory contains a `.ultra.cache.json` file that contains hashes of all files and build artifacts in your repository. Internally this uses `git ls-files` for files under source control and simple `mtime` timestamps for build artifacts.\nWhen building a package, the current state is compared with the `.ultra.cache.json`. Builds are skipped when no changes were detected.\n\nOptimized builds using the dependency tree and files cache, are automatically triggered when running the `build` script or using `--build` with a custom script or command.\n\nAll commands below will trigger optimized builds.\n\n```shell\n$ ultra -r --build\n...\n\n$ ultra -r build\n...\n\n$ ultra -r --build mycustombuildscript\n...\n```\n\nIf for some reason you want to rebuild a package, use `--rebuild` or `rebuild`.\n\nIf you want some files to be excluded from the `.ultra.cache.json`, you can create a `.ultraignore` file. The format is similar to `.gitignore`. Whenever a file changes that is listed in your `.ultraignore`, a rebuild will **not** be triggered.\n\n## :bar_chart: Monitor\n\nWith `ultra --monitor` you can easily monitor all running node processes on your machine.\n\nFor every process, you can also see the package where the command was executed and a clean command line.\n\n![Monitor](assets/monitor.png)\n\n## :zap: Fast\n\n**Ultra** parses your `package.json` scripts and will only execute the commands that are really needed. Any script interdependencies are resolved during the parsing stage.\nThis ensures there's pretty much no overhead in execution by **Ultra** itself, since it's only running once.\n`yarn run` or `npm run` on the other hand, will spawn new `yarn` or `npm` child processes as needed by the package scripts.\n\n|                          | `npm run`          | `npx`              | `yarn`             | `yarn exec`        | `ultra`            |\n| ------------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ |\n| `package.json` scripts   | :white_check_mark: | :x:                | :white_check_mark: | :x:                | :white_check_mark: |\n| `./node_modules/.bin/`   | :x:                | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |\n| system binaries          | :x:                | :white_check_mark: | :x:                | :white_check_mark: | :white_check_mark: |\n| execution overhead _(1)_ | 250ms              | 60ms               | 220ms              | 200ms              | 65ms               |\n\n  \u003c!-- markdownlint-disable MD033 --\u003e\n\n\u003e \u003csup\u003e**1.** each program was run 10x with the command `true` or `{scripts:{\"true\":\"true}}` to calculate the execution overhead\u003c/sup\u003e\n\nSuppose you would want to run a script that calls 5 other scripts by using `\u0026\u0026` and/or `post`/`pre`.\n\n* Using `yarn`, you would have a total overhead of **2.5s** _(10x 250ms)_\n* Using `ultra`, you hit the overhead only once, so the total overhead would still be **65ms**\n\nTo make execution **ultra** fast, you can [configure](##gear-optional-configuration) which `scripts` should be ran concurrently.\n\n\u003e :grey_exclamation: there's no need to **switch** your scripts over to **ultra**. Even with the optional configuration you can still use `yarn` or `npm` to run your scripts if you want to.\n\nExample builds:\n\n|                                                             | `yarn` | `ultra` not concurrent | `ultra` concurrent |\n| ----------------------------------------------------------- | ------ | ---------------------- | ------------------ |\n| build [Ultra-Runner](https://github.com/folke/ultra-runner) | 8.9s   | 7.2s                   | 5.1s               |\n| build [Devmoji](https://github.com/folke/devmoji)           | 16s    | 13s                    | 8s                 |\n\n## :art: Formatting\n\nThere are three output formats that each can be combined with `--silent` to hide command output.\n\n`--pretty` is the default. It shows output in a hierarchical way and uses spinners to see exactly what's happening.\nMake sure to check out the animation at the top of this page. Every executed step shows the execution time.\n\n`--pretty` combined with `--silent` is useful if you're only interested to see the overview:\n\n`--no-pretty` doesn't use spinners and prefixes command output with the command name. This is useful for logging purposes.\n\nCombining `--no-pretty` with `--silent` shows a flat overview.\n\n`--raw` will show the exact output as you would expect when running the commands stand alone. If the command you're executing is interactive (reads from stdin), then this is the mode you should use.\n\n## :dizzy: Getting Started\n\nInstall with `npm` or `yarn`\n\n\u003e globally\n\n```sh\nnpm install -g ultra-runner\nyarn global add ultra-runner\n```\n\n\u003e locally inside your project. use with `npx ultra`\n\n```shell\nnpm install --dev ultra-runner\nyarn add --dev ultra-runner\n```\n\nNow run `ultra --info` within your repository to see everything related to your monorepo\n\nSee [optional configuration](##gear-optional-configuration) for information on how to setup concurrent script execution.\n\n## :rocket: Usage\n\n```console\n$ ultra --help\nUsage: ultra [options] \u003ccmd\u003e [cmd-options]\n\nWorkspace:\n  --recursive, -r  Run command in every workspace folder concurrently                                      [boolean]\n  --filter         Filter package name or directory using wildcard pattern                                  [string]\n  --root           When using --recursive, also include the root package of the workspace                  [boolean]\n  --concurrency    Set the maximum number of concurrency                                      [number] [default: 10]\n\nStatus:\n  --info  Show workspace dependencies                                                                      [boolean]\n  --list  List package scripts. Also works with --recursive                                                [boolean]\n  --monitor           Show node process list, updated every 2 seconds                                      [boolean]\n  --monitor-interval  Set process list interval in seconds                                     [number] [default: 2]\n\nBuild:\n  --build, -b  Use dependency tree to build packages in correct order                                      [boolean]\n  --rebuild    Triggers a build without checking for file changes                                          [boolean]\n\nFormatting:\n  --pretty  enable pretty output, spinners and separate command output. Default when a TTY [boolean] [default: true]\n  --raw     Output only raw command output                                                                 [boolean]\n  --silent  Skip script output. ultra console logs will still be shown                                     [boolean]\n  --color   colorize output                                                                [boolean] [default: true]\n\nOptions:\n  --version      Show version number                                                                       [boolean]\n  --dry-run, -d  Show what commands would be executed, without actually executing them                     [boolean]\n```\n\n## :gear: Optional Configuration\n\nTo allow parallel execution of your scripts, you can specify scripts that should run concurrently,\nin your `package.json`.\n\n```json\n{\n  \"scripts\": {\n    \"lint:eslint\": \"npx eslint bin/*.js src/*.ts __tests__/*.ts --cache\",\n    \"lint:docs\": \"npx markdownlint *.md\",\n    \"lint:ts\": \"npx tsc -p tsconfig.build.json --noEmit\",\n    \"lint\": \"yarn lint:eslint \u0026\u0026 yarn lint:docs \u0026\u0026 yarn lint:ts\",\n    \"prebuild\": \"yarn lint \u0026\u0026 yarn jest\",\n    \"build\": \"...\"\n  },\n  \"ultra\": {\n    \"concurrent\": [\"lint\"]\n  }\n}\n```\n\n* `yarn build` will run the `lint` and `jest` commands sequentially\n* `ultra build` will run all `lint` commands concurrently and then execute `jest`. (note that we can also add `prebuild` to `concurrent`, since tests don't depend on linting. this way all commands would run concurrently)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffolke%2Fultra-runner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffolke%2Fultra-runner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffolke%2Fultra-runner/lists"}