npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

bundlemonkey

v0.7.6

Published

Bundlemonkey is a userscript bundler designed to make developing browser userscripts blazing fast and efficient.

Readme

Bundlemonkey

Bundlemonkey is a userscript bundler designed to make developing browser userscripts blazing fast and efficient.

With TypeScript support and type-safe header comments, managing your code becomes a breeze.

Works well with Tampermonkey, Violentmonkey or Greasemonkey.

Features

  • Lightning-Fast Builds
    Incredibly fast bundling speeds, thanks to esbuild.

  • TypeScript Support

  • Module Bundling

  • Type-Safe Header Comments
    Write userscript header metadata in a type-safe and straightforward way. This not only minimizes errors but also makes your code much more maintainable.

  • Watch mode

Compilation Example

source

// src/sample/message.ts

export const message = "Hello from sample script and bundlemonkey!";
// src/sample/index.user.ts

import { defineUserScript } from "bundlemonkey";
import { message } from "./message";

export default defineUserScript({
  name: "Sample userscript",
  version: "1.0.0",
  description: "Write userscripts with ease using bundlemonkey!",
  match: ["https://example.com/*"],
  main: () => {
    console.log(message);
  },
});

output

// ==UserScript==
// @name         Sample userscript
// @version      1.0.0
// @description  Write userscripts with ease using bundlemonkey!
// @match        https://example.com/*
// ==/UserScript==

// src/sample/message.ts
var message = "Hello from sample script and bundlemonkey!";

// src/sample/index.user.ts
void (() => {
  console.log(message);
})();

Quick Start

1. Setup

You can set up new project quickly using the template (1a), or do it manually (1b).

1a. Use template

npx bundlemonkey --create

# or like
pnpx bundlemonkey --create
bunx bundlemonkey --create

1b. Setup manually

Install Bundlemonkey using npm, pnpm, or bun:

npm install --save bundlemonkey

# or like
pnpm add bundlemonkey
bun add bundlemonkey

Create a directory for your userscripts named with the slug under src directory. Your project structure might look like this:

├── src/ # configurable
│   ├── script-a/
│   │   ├── index.user.ts
│   │   └── some-module.ts
│   └── script-b/
│       └── index.user.ts
├── dist/ # configurable
│   └── # bundled code goes here
├── bundlemonkey.config.ts # optional
└── package.json

[!TIP] Source scripts are collected by glob src/*/index.user.{ts,js} by default, and srcDir is configurable.

2. Write your code

Head into any of the source scripts (index.user.ts or index.user.js) and start writing your code! See Define UserScript section for more details.

3. Build

Run the following command to compile your code:

npx bundlemonkey

# or like
pnpx bundlemonkey
bunx bundlemonkey

Bundlemonkey compiles your code into dist directory.

Watch mode and Remote watch mode are supported as well, so you can have it rebuild your scripts automatically. See CLI docs below for more details.

Define Userscript

Each source script must define its main code, name, version, etc. using defineUserScript and export it as the default export. It might look like:

import { defineUserScript } from "bundlemonkey";

export default defineUserScript({
  name: "Sample userscript",
  version: "1.0.0",
  description: "Write userscripts with ease using bundlemonkey!",
  match: ["https://example.com/*"],
  config: {
    message: "hello!",
  },
  main: (config) => {
    // your main code here!
    console.log(config.message)
  },
});

Props of defineUserScript

Please see docs of Tampermonkey or Violentmonkey for more details about props other than config and main.

✅ - required

name|type|default :---|:---|:--- config|T extends any main ✅|(config: T) => unknown|--- name ✅|string|--- namespace|string| copyright|string| version ✅|string|--- description|string| icon|string| grant|Grant[] \| "none"|[] author|string| homepage|string| antiFeature|AntiFeature[]|[] require|string[]|[] resource|{ name: string; url: string; }[]|[] match|string[]|[] excludeMatch|string[]|[] include|string[]|[] exclude|string[]|[] runAt|RunAt| runIn|string[]|[] sandbox|"raw" \| "JavaScript" \| "DOM"| injectInto|"page" \| "content" \| "auto"| tag|string[]|[] connect|string[]|[] noframes|boolean|false updateURL|string| downloadURL|string| supportURL|string| unwrap|boolean|false topLevelAwait|boolean|false

Config

Config for the script which is intended to be modifiable by the users of your script.

If present, the value will be defined at the beginning of the compiled userscript as a variable named userscriptConfig to make it easy for users to edit.

For example:

export default defineUserScript({
  // ...
  config: {
    /**
     * Edit this to change the message
     * @type string
     */
    message: "hello!"
  },
  main: (config) => {
    window.alert(config.message);
  },
});

will be compiled into:

// ==UserScript==
// ...
// ==/UserScript==

var userscriptConfig = {
  /**
   * Edit this to change the message
   * @type string
   */
  message: "hello!"
};

void ((config) => {
  window.alert(config.message);
})(userscriptConfig);

Main

Your main userscript code.

It can be either a synchronous or an asynchronous function, and can receive config as a prop.

Grant

Tampermonkey docs

All APIs supported by Tampermonkey, Violentmonkey and Greasemonkey (GM_*, GM.*, unsafeWindow, window.onurlchange, window.close and window.focus) can be specified.

type Grant =
  | "unsafeWindow"
  | "GM_addElement"
  | "GM_addStyle"
  // ...
  | "GM.addStyle"
  | "GM.setValue"
  // ...
  | "window.onurlchange"
  | "window.close"
  | "window.focus";

AntiFeature

Tampermonkey docs

type AntiFeature = {
  type: "ads" | "tracking" | "miner";
  description: string;
};

RunAt

Tampermonkey docs

type RunAt =
  | "document-end"
  | "document-start"
  | "document-body"
  | "document-idle"
  | "context-menu";

Build Modes

Production Mode

All source scripts will be compiled at once.

Compiled scripts will be located in dist.production directory.

Watch Mode

Bundlemonkey monitors edits to the source scripts. When an edit is detected, it compiles the source and copies the output to the clipboard. Please paste and save it in your userscripts manager's editor for use.

Compiled scripts will be located in dist.dev directory.

Remote Watch Mode

Similar to Watch mode, it monitors edits to the source scripts; however, in this mode, you do not need to paste into the editor every time you make changes.

When a source script is edited, a remote script will be copied to the clipboard only the first time. Once you paste and save this remote script in your userscripts manager's editor, subsequent edits to the source script will be automatically reflected.

You need to allow your userscript manager access to local files to use this mode. Please refer to Tampermonkey's FAQ for more details.

[!TIP] A remote script is a plain userscript that simply @requires the actual userscript code.

CLI

bundlemonkey [--watch [--remote]] [--create]

--watch

Enable Watch mode.

--remote

Use with --watch to enable Remote watch mode.

Configuration

If you need to customize Bundlemonkey’s behavior, you can create a configuration file named bundlemonkey.config.ts or bundlemonkey.config.js in your project’s root directory.

Example

bundlemonkey.config.ts

import type { Config } from "bundlemonkey";

const config: Config = {
  srcDir: "src", // default value
  dist: {
    dev: ".dev", // default value
    production: "dist", // default value
  },
  defaultMeta: {
    author: "John Doe",
    namespace: "johndoe",
    homepage: "https://github.com/johndoe/userscripts",
    updateURL: ({ scriptName }) =>
      `https://github.com/johndoe/userscripts/raw/main/dist/${scriptName}.user.js`,
    downloadURL: ({ scriptName }) =>
      `https://github.com/johndoe/userscripts/raw/main/dist/${scriptName}.user.js`,
  },
};

export default config;

srcDir

  • type: string
  • Default: "src"

Directory where your source scripts are located.

[!NOTE] The glob for collecting the source files is like: <cwd>/<srcDir>/*/index.user.{ts,js}

dist

  • type: object

dist.dev

  • type: string
  • Default: ".dev"

Dist directory in watch mode.

dist.production

  • type: string
  • Default: "dist"

defaultMeta

  • type: object
  • Default: undefined

Default meta used for all userscripts. Metadata defined in defineUserScript overrides this.

All meta properties in defineUserScript can be used here as well, while updateURL/downloadURL have different signatures like below.

defaultMeta.updateURL

  • type: (args: { scriptName: string; version: string }) => string
  • Default: undefined

defaultMeta.downloadURL

  • type: (args: { scriptName: string; version: string }) => string
  • Default: undefined