TypeScript icon, indicating that this package has built-in type declarations

0.4.0 • Public • Published


Run JavaScript in Chrome, from the command line.

This module is ideal for quickly testing JS code that is written for the browser, without having to first set up a bundler and serving an index.html.

DISCLAIMER: This is far from production-ready, but so useful for me in daily development that I needed to make a package out of it.

npm i chrode # install
npx chrode script.js # run your script

Chrode uses esbuild to bundle your code before executing it in headless Chrome with puppeteer. Some benefits:

  • Resolving ESM / require imports from node_modules just works
  • Automatically handles TypeScript and JSX
  • Can be used in re-executing watch mode like nodemon

We also add some custom esbuild plugins to make it easy to run performance-oriented scripts which use WebAssembly and Web Workers.


npx chrode script.js
npx chrodemon script.js # same as `npx chrode script.js --watch`


  -h, --help            Print this information.
  -w, --watch           Re-execute on file changes
  -s, --silent          Do not forward console logs to stdout.
  --incognito           Run in an incognito browser context.
  --no-headless         Open the Chrome browser UI that runs your scripts.

Build only

If you only want the bundle produced by Chrode without running it, you can use the chrode-build CLI:

npx chrode-build script.js

This will pipe the build output to the command-line. Note that this is just a far less powerful wrapper around esbuild with the added convenience of our ready-to-use setup and plugins. The bundle that is produced is an ES module without imports and exports, suitable for inclusion in a <script type="module">, or for executing with deno or even node if you avoid incompatible Browser APIs.

A more useful build command is exposed in our JavaScript API:

JavaScript API

import {run, build} from 'chrode';

// same as `chrode script.js`

// with advanced options (same meaning as above)
run('./script.js', {
  watch: true,
  silent: true,
  incognito: true,
  noHeadless: false,

// build only
// the second parameter is an object that directly overrides our input to
let script = await build('./script.js', {minify: true});


You can simply import .wasm and .wat files directly. Both will resolve with a Uint8Array which holds the WebAssembly bytecode. .wat is converted to .wasm behind the scenes.

import wasmBytes from './example.wasm';

// instantiate
let wasmInstance = await WebAssembly.instantiate(wasmBytes);

Web Workers

Files with a .worker.js extension will be resolved by inlining the worker code and exporting a constructor for the worker, without URL. This makes it more convenient to play around with multi-threaded JavaScript, especially if you want to bundle your code as a library.

// script.worker.js
postMessage('hello from worker!');
// script.js
import Worker from './script.worker.js';
let worker = Worker();
worker.onmessage = ({data}) => console.log(data);

When script.js is run with Chrode, this prints "hello from worker!".

Filesystem access

Your scripts can access files on your hard-drive via fetch. The path is resolved relative to the folder where Chrode is run. Example:

let res = await fetch('./package.json');
let packageJson = await res.json();

When executed with Chrode, this prints the name in your package.json.

How does it all work?

  • We bundle your script using esbuild (with custom plugins for WebAssembly and Web Workers)
  • We start a browser context with puppeteer which loads a dummy html page including the bundled script.
  • A static file server serves your current folder to the page
  • We forward console calls and errors in the browser to your console (with puppeteer).
  • For chrodemon, we run esbuild in watch mode and reload the page on changes

What does it mean?

chrode = chrome + node, because it runs scripts, like node, but in chrome.




Package Sidebar


npm i chrode

Weekly Downloads






Unpacked Size

20.5 kB

Total Files


Last publish


  • mitschabaude