Node.js’s younger sibling, Deno, has been evolving. Since its official, buzzy release in May 2020, a lot has changed. The hype has toned down, the runtime has been improved, and the community, alongside the whole module ecosystem, has started to form.
However, even with these changes, Deno still isn’t the “Node.js killer” some might have seen it as. Sure, it comes with great features, like first-class TypeScript support, a secure permission-based system, and URL-based module loading, but it lags behind Node in mind-share and a few basic aspects.
One example of such a feature is a script runner. In Node, there’s package.json, in which you can specify your scripts.
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
}
}
The problem is, there’s no inbuilt package.json or any alternative in Deno. You have to type out the full command any time you want to use it. Tons of config flags don’t make this any better:
deno run --allow-read --allow-write --allow-net --reload example.ts
The way around that is to use a third-party script runner, like Velociraptor. Let’s see what features it has, how it works, and how it can make working with Deno that much better!
The Replay is a weekly newsletter for dev and engineering leaders.
Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.
Velociraptor is arguably the most popular script runner for Deno, with about 500 GitHub stars at the time of this article’s publication. It is inspired by package.json’s scripts and offers a similar out-of-the-box experience to its Node counterpart, but also comes with additional, Deno-specific features.
You can install Velociraptor from deno.land/x, like any other module:
deno install -qAn vr https://deno.land/x/[email protected]/cli.ts
It’s recommended to use vr while assigning a name to the executable. Using a different name may result in some known issues with Git hooks.
Next, create your configuration file — the package.json replacement. It could be either a scripts or a velociraptor file with one of the following extensions:
yml / yamljsontsHere are examples of different config files:
scripts.yaml
scripts: start: deno run --allow-net server.ts test: deno test --allow-net server_test.ts
scripts.json
{
"scripts": {
"start": "deno run --allow-net server.ts",
"test": "deno test --allow-net server_test.ts"
}
}
script.ts
export default {
scripts: {
start: "deno run --allow-net server.ts",
test: "deno test --allow-net server_test.ts",
},
};
We’ll stick with yaml for the rest of this post.
Besides the basic, compact form, scripts can also be defined as objects that allow for passing additional options, like desc for describing the script’s purpose or watch for reloading the script on file change.
scripts:
start:
desc: Runs the server
cmd: deno run --allow-net server.ts
watch: true
In object format, you specify the actual command under the cmd property.
Alongside the configuration file, Velociraptor’s CLI is its most important feature. It’s your yarn or npm run equivalent for the Deno world.
Running plain vr in your terminal will output all defined scripts, while vr run <script> or vr <script> will run the selected script.
vr # list available scripts vr run start # run "start" script vr start # more concise way of running "start" script vr start --prod # run "start" script with "prod" argument
Besides running scripts, Velociraptor also provides an export command for outputting one or more scripts as a standalone executable for use in environments where Velociraptor is not installed.
vr export start # export "start" script ./bin/start --prod # run exported script with "prod" argument vr export start -o output # change output directory from default "bin"
While defining scripts and running them from the CLI should be enough in most cases, Velociraptor goes far beyond that. With its additional features, using a script runner in Deno becomes a much better experience.
Velociraptor allows you to specify some of your Deno CLI options in a clean, structured way with dedicated config properties.
You can specify Deno permissions in an array or object for all scripts at the upper-most allow field, or on a script-by-script basis.
allow:
- read
- write
scripts:
start:
cmd: server.ts
allow:
net: 127.0.0.1
You can also provide paths to files like tsconfig.json, importmap.json, lock files, and PEM certificates for SSL under separate config entries.
scripts:
start:
cmd: server.ts
cert: certificate.pem
lock: lock.json
imap: importmap.json
tsconfig: tsconfig.json
Apart from the above, there are many more additional options you can specify. These include:
inspect for attaching the debuggerreload for recompiling TypeScript (either everything or only specified modules)log for specifying the log levelv8Flags for passing options to the V8 engineunstable, cachedOnly, and othersCheck out the official Velociraptor documentation for more details.
Apart from the Deno CLI options, there are also dedicated fields for environment variables. This includes:
env for listing the variables in the config file directlyenvFile for specifying a dotenv file (or list of files) to load the variables fromThe options can be specified at both the top and script levels and will be combined so that the script receives all needed variables.
# for all scripts
envFile:
- .env
env:
PORT: 8081
scripts:
start:
cmd: deno run --allow-net server.ts
# script-specific
envFile: .start_env
env:
PORT: 8082
One more great feature of Velociraptor allows you to run multiple scripts at once. With composite scripts, complex commands filled with && and other operators can be replaced with a clean list of scripts.
scripts:
start:
- deno run one.ts
- deno run two.ts
test: # With script objects
- deno test test_one.ts
- cmd: deno test test_two.ts
tsconfig: tsconfig.json
The example above runs scripts serially, in order. To run them in parallel, use the pll option.
scripts:
start:
pll: # In parallel
- deno run one.ts
- deno run two.ts
pll can be combined with a serial script list to form even more complex execution flows.
scripts:
start:
- pll:
- deno run one.ts
- deno run two.ts
- deno run three.ts
This enables a new set of possibilities, having complex script flows defined and executed clearly, right from the config file.
Velociraptor comes with inbuilt support for Git hooks. It allows you to effortlessly integrate your scripts with Git hooks and share them with others working on the same repo.
To link a single script to a Git hook, add the gitHook property to it.
scripts:
format:
cmd: deno fmt
gitHook: pre-commit
To attach more than one script to a Git hook, you can use gitHook alongside composite scripts.
With hooks set up, you can install them by running the vr command. If you’d like to prevent this behavior (e.g., for CI configuration), set the VR\_HOOKS environment variable to false.
For more advanced workflows, Velociraptor integrates with GitHub Actions, thanks to a setup-velociraptor action. When combined with setup-deno, you can use vr commands right from your Actions.
steps: - uses: denoland/setup-deno@v1 - uses: jurassiscripts/setup-velociraptor@v1 - run: vr ...
You can install the dedicated extension for autocompletion and other code assistance features for Velociraptor in VS Code. This will autocomplete configuration options in both yaml and json files.
You can still get autocompletion in other editors and IDEs by using TypeScript for your configuration file, alongside proper type annotation.
import { ScriptsConfiguration } from "https://deno.land/x/[email protected]/mod.ts";
const config: ScriptsConfiguration = {
scripts: {
start: "deno run --allow-net server.ts",
test: "deno test --allow-net server_test.ts",
},
};
export default config;
With a great, feature-packed script runner like Velociraptor, Deno becomes much more enjoyable to use. All of your scripts are just vr <script> away; Git hooks integration couldn’t be simpler; and building complex script flows is easy, thanks to composite scripts, structured options, and autocompletion.
If you haven’t already, check out Velociraptor over on GitHub and give it a try!
Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not
server-side
$ npm i --save logrocket
// Code:
import LogRocket from 'logrocket';
LogRocket.init('app/id');
// Add to your HTML:
<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>

Compare mem0 and Supermemory to learn how modern AI apps manage long-term memory beyond RAG and stateless LLM chats.

Animate SVGs with pure CSS: hamburger toggles, spinners, line-draw effects, and new scroll-driven animations, plus tooling tips and fallbacks.

Tailwind CSS is more popular than ever. This guide breaks down v4’s biggest changes, real-world usage, migration paths, and where it fits in the AI future.

Evaluate the top React animation libraries for ease of use, developer experience, and bundle size.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up now