Creating a module

Module structure, entry point, lifecycle and a complete first example.

Module structure

Modules live in the mods directory at the Toolbox root. A regular module occupies its own folder. The legacy standalone format is a single .js file with limited capabilities; use a folder with module.json for new development.

mods/
    hello-toolbox/
        module.json
        index.js

Toolbox loads the entry point with require(moduleFolder): normally index.js, or another file selected by main in package.json. Toolbox metadata belongs in module.json, not package.json. An automatically updated module also needs manifest.json.

Your first module

Create module.json:

{
    "name": "hello-toolbox",
    "author": "Your name",
    "description": "A minimal Toolbox module",
    "disableAutoUpdate": true
}

Create index.js:

module.exports = function HelloToolbox(mod) {
    const onEnter = () => mod.log(`Hello, ${mod.game.me.name}!`);
    mod.game.on('enter_game', onEnter);
    mod.command.add('hello', () => mod.command.message('Hello from Toolbox!'));

    this.destructor = () => {
        mod.game.removeListener('enter_game', onEnter);
    };
};

Restart Toolbox and connect to the server through it. Entering the game logs a greeting; the hello command replies in game through the command module. Disabling automatic updates during development prevents remote files from replacing local changes.

Exports and lifecycle

A class can also be the entry point:

module.exports.NetworkMod = class Example {
    constructor(mod) {
        this.mod = mod;
        mod.log('Module loaded');
    }

    destructor() {
        this.mod.log('Module unloaded');
    }
};
Export Lifetime
GlobalMod One instance for the loaded module
ClientMod An instance per connected client interface
NetworkMod An instance per game network connection
RequireInterface The interface exposed to dependent modules

A plain function or class export is supported through a compatibility wrapper. Named exports separate client, network and shared logic. Avoid module-level variables for state that must remain independent between game connections.

Toolbox calls the optional destructor() when unloading an instance. Framework hooks, commands and managed timers are cleaned up automatically; remove your own listeners on shared emitters, windows and other resources yourself. Constructors cannot be asynchronous: start asynchronous work from an appropriate event and handle errors.

Next steps

Read metadata and updates, hooks and game state. Network modules handle packets; client modules can install resource files. These are different API scopes.

Sources: doc/mod/main.md, bin/mod.js, bin/mod-legacy-wrapper.js.