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

js2max

v1.1.2

Published

Compile JavaScript files into Max for Live (.amxd) devices

Readme

js2max

Write Max for Live devices in JavaScript. Compile to .amxd and drag into Ableton Live.

js2max is a Node.js compiler that takes a JavaScript file written for the Max 9 v8 engine and produces a ready-to-use .amxd device. No visual patching required.

Why?

The Max/MSP visual editor is great for experimentation but painful for serious development:

  • No version control (binary/JSON diffs are unreadable)
  • No code review, no linting, no refactoring tools
  • AI coding assistants can't help you patch
  • Copy-paste logic between devices is manual and error-prone

Max 9 introduced the v8 object — a modern V8 JavaScript engine with full ES6+ support and access to the Live Object Model. Your logic is pure JavaScript; you just need a minimal patch to wire it up.

js2max generates that patch for you.

Quick Start

npx js2max compile effect.js                  # → effect.amxd (drag into Ableton Live)
npx js2max compile effect.js -o effect.maxpat  # → JSON for Max 9

Installation

npm install -g js2max

Or use directly with npx:

npx js2max compile <input.js> [options]

Usage

Write your JavaScript

// @device midi-effect

inlets = 2;
outlets = 1;

function msg_int(value) {
  if (inlet === 0) {
    // Control message
    post("Received:", value, "\n");
    return;
  }
  // MIDI byte — pass through doubled
  outlet(0, value);
}

function bang() {
  outlet(0, "hello", "world");
}

Compile it

# MIDI effect (default) → .amxd
js2max compile effect.js

# Audio effect
js2max compile delay.js --type audio-effect

# Instrument
js2max compile synth.js --type instrument

# Output as .maxpat instead
js2max compile effect.js -o effect.maxpat

CLI Options

| Option | Default | Description | | ------------------------- | ------------------- | -------------------------------------------------------- | | -o, --output <path> | <input>.amxd | Output file path (.amxd or .maxpat) | | -t, --type <type> | midi-effect | Device type: midi-effect, audio-effect, instrument | | --no-embed | (embeds by default) | Reference external .js file instead of embedding | | -w, --device-width <px> | 400 | Max for Live device strip width |

Output Formats

  • .amxd (default) — Binary Max for Live device. Opens directly in Ableton Live (any version with Max for Live support).
  • .maxpat — JSON Max patch. Opens in Max 9. Use -o file.maxpat to select this format.

The .amxd binary format was reverse-engineered from Ableton's own maxdevtools and validated against working devices. It uses a chunk-based container (ampfmetaptch with mx@c header and dlst directory listing).

Decorator Comments

Use comments at the top of your file to configure compilation:

// @device midi-effect          — sets device type (overridden by --type flag)
// @inlet 0 "MIDI input"       — help text for inlet 0
// @inlet 1 "Control"          — help text for inlet 1
// @outlet 0 "Processed MIDI"  — help text for outlet 0

@ui — Device Strip UI Elements

Add interactive controls to your device's presentation view with @ui decorators. The compiler generates Max UI objects, wires them to your v8 inlets/outlets, and auto-layouts them in the device strip.

// @ui live.text "Fire" trigger inlet=0        — button (sends bang on click)
// @ui live.dial "Delay" inlet=1 min=0 max=1000 — rotary dial
// @ui live.slider "Volume" inlet=2 min=0 max=127 — vertical slider
// @ui live.toggle "Active" outlet=0           — LED toggle (driven by code)

Format: // @ui <maxclass> "<label>" [trigger] inlet=N|outlet=N [min=X] [max=Y]

| Parameter | Description | |-----------|-------------| | inlet=N | Wires UI output to v8 inlet N (user controls the code) | | outlet=N | Wires v8 outlet N to UI input (code controls the display) | | trigger | For live.text — button mode (bang on click) instead of toggle | | min/max | Value range for dials and sliders |

Example — MIDI echo with UI:

// @device midi-effect
// @ui live.dial "Delay" inlet=0 min=0 max=1000
// @ui live.dial "Feedback" inlet=2 min=0 max=100
// @ui live.toggle "Activity" outlet=1

inlets = 3;
outlets = 2;

function msg_int(value) {
  if (inlet === 0) { delayTime = value; return; }
  if (inlet === 2) { feedback = value / 100; return; }
  outlet(0, value);
}

Elements are arranged in a row below the title and wrap automatically when they exceed the device width.

How It Works

  1. Parses your .js file to extract inlets, outlets, handler functions, and decorator comments
  2. Selects a template based on device type (MIDI effect, audio effect, or instrument)
  3. Generates the patch JSON with the v8 object wired to the appropriate Max for Live infrastructure (midiin/midiout, plugin~/plugout~, live.thisdevice)
  4. Embeds your JavaScript source directly in the patch (single-file distribution)
  5. Wraps in the .amxd binary container (chunk-based: ampf + meta + ptch with mx@c header and dlst directory)

Examples

See the examples/ directory:

  • hello-world.js — Simplest possible device with a "Say Hello" button
  • midi-echo.js — MIDI delay/echo with Delay/Feedback dials and Activity toggle
  • clip-launcher.js — Live Object Model with Track/Slot dials and Fire/Stop buttons

Max 9 v8 API Quick Reference

The v8 object gives you access to these globals:

// Inlets and outlets (must be in global scope)
inlets = 2;
outlets = 3;
inlet; // read-only: which inlet triggered the current function

// Output
outlet(n, ...args); // send message out outlet n
outlet_array(n, arr); // send JS array (v8 only)
outlet_dictionary(n, dict); // send dictionary (v8 only)

// Message handlers (define as global functions)
function bang() {}
function msg_int(n) {}
function msg_float(f) {}
function list(...args) {}
function anything(msg, ...args) {} // catch-all

// Live Object Model
var api = new LiveAPI(callback, "live_set tracks 0");
api.get("name");
api.set("mute", 1);
api.call("fire");

// Utilities
post("debug message\n"); // print to Max console

Full reference: Max JavaScript User Guide | v8 Reference | Live API

Limitations

  • No audio DSP: JavaScript runs in Max's low-priority thread. Use v8 for MIDI processing, generative tools, control logic, and Live Object Model access — not for real-time audio processing.

Development

git clone https://github.com/ktamas77/js2max.git
cd js2max
npm install
npm run build
npm test

Code Quality

Pre-commit hooks (via husky) automatically run on every commit:

  • TypeScript typecheck (tsc --noEmit)
  • Prettier formatting
  • ESLint linting
npm run typecheck    # type check
npm run lint         # eslint
npm run format       # prettier --write

Changelog

See CHANGELOG.md for release history.

License

MIT