Skip to content

Scaffold an Ableton extension

How to scaffold an Ableton extension with the Extensions SDK: the minimal file shape, the activate() entry point, and the local build. This is the structure Loophole uses, shown so you can build your own.

An extension is a small Node project that the Extensions CLI bundles and Live loads. The shape:

my-extension/
├── manifest.json name, author, entry, version, minimumApiVersion
├── tsconfig.json nodenext, strict, noEmit, rootDir ./src
├── build.ts esbuild: bundle src/extension.ts to the manifest entry
├── package.json scripts: build (typecheck + bundle), start, package
└── src/
└── extension.ts activate(context): register your commands here

The manifest.json points entry at the bundled output and declares the API version your code targets:

{
"name": "My Extension",
"author": "you",
"entry": "dist/extension.js",
"version": "0.1.0",
"minimumApiVersion": "1.0.0"
}

activate(context) is where you initialize the API and register what your extension does. The pattern, from Ableton’s own examples:

import { initialize, type ActivationContext } from '@ableton-extensions/sdk';
export function activate(context: ActivationContext) {
const api = initialize(context, '1.0.0');
api.commands.registerCommand('myext.run', () => {
// read the Set, do the work, write it back inside one withinTransaction
});
api.ui.registerContextMenuAction('ClipSlot', 'Do the thing…', 'myext.run');
}
  1. Install the SDK and CLI tarballs you downloaded from the Ableton Beta Program (they are local-only; do not commit them).

  2. Bundle and hot-load into a running Live with Dev Mode enabled:

    Terminal window
    npm start # runs your build.ts, then extensions-cli run
  3. Package the installable .ablx:

    Terminal window
    npm run package # bundles --production, then extensions-cli package

Loophole splits every extension into a pure core (the music logic, no SDK) and a thin SDK shell (activate(), the command modules, and the adapter). The core is tested exhaustively without Live; the SDK is imported only inside that shell. The API cheatsheet lists the handful of calls a context-menu extension actually uses.