Addon Kit

Scaffold, deploy and manage Simple Function add-ons from your terminal with the Addon Kit CLI (npm: @servicem8/addon-kit).

The ServiceM8 Addon Kit is a command-line tool (CLI) for building, testing, and deploying ServiceM8 add-ons from your terminal. It provides a modern, repeatable workflow while using the same add-on capabilities, event data, and manifest settings described throughout the Add-on SDK documentation.

For a plain-English walkthrough using an AI coding assistant, see Create a private ServiceM8 Add-on with AI.

Benefits

Addon Kit helps you:

  • Scaffold a working TypeScript add-on project.
  • Define your add-on in a single addon.jsonc file, with editor autocomplete and validation provided by a JSON schema.
  • Bundle TypeScript, multiple source files, and npm dependencies into a deployable serverless function.
  • Validate and deploy an add-on from your terminal, or validate it without deploying by using --dry-run.
  • Manage add-on secrets without putting secret values in source control. Secrets are supplied to your function as environment variables and can be updated without redeploying.
  • Stream live logs from your deployed add-on with addon-kit tail.
  • Use the same deployment workflow locally and in continuous integration (CI).
  • Migrate an existing manifest.json project to the new workflow.

Requirements

Addon Kit requires Node.js 22 or later and a ServiceM8 account. Deploying requires the manage_addons OAuth scope on that account, which addon-kit login requests for you in the browser. A full-access API key also carries this scope, so you can use one instead of browser login (see Authenticate).

Install from npm

Install Addon Kit as a development dependency in your add-on project. A project-local installation keeps the version consistent for everyone working on the add-on and for CI deployments.

npm install --save-dev @servicem8/addon-kit@latest

Run the locally installed CLI with npx:

npx addon-kit --version
npx addon-kit --help

Alternatively, install the CLI globally to make the addon-kit command available outside a project:

npm install --global @servicem8/addon-kit@latest
addon-kit --help

Create and deploy an add-on

From the directory where you want to create your add-on, run:

npx @servicem8/addon-kit@latest init my-addon
cd my-addon
npm install --save-dev @servicem8/addon-kit@latest
npx addon-kit login
npx addon-kit deploy

The first command runs the package directly from npm to scaffold the project and create an addon.jsonc configuration file. The scaffold does not add Addon Kit to package.json, so installing it as a development dependency is what makes npx addon-kit (and the $schema reference in addon.jsonc) available within the new project. addon-kit login opens your browser so you can authorize Addon Kit on your ServiceM8 account. addon-kit deploy validates the configuration, bundles the function, deploys it, and activates the add-on on the authenticated ServiceM8 account.

Once deployed, open a job in ServiceM8 and choose your add-on from the job card's More menu to see it run.

To check that an add-on can be bundled and deployed without making any changes to ServiceM8, run:

npx addon-kit deploy --dry-run

Authenticate

npx addon-kit login

login opens ServiceM8 in your browser and asks you to allow Addon Kit to manage your add-ons. Once you approve, the CLI stores the credentials outside your project and refreshes them automatically. Run npx addon-kit whoami at any time to see which account you are logged in to.

If your function calls the ServiceM8 REST API, include the scopes it needs in both the manifest's oauth.scope and your login request. Automatic activation is limited to manifest scopes held by the deploying credential, so a login with only the default manage_addons scope lets you deploy but leaves your function unable to read or write account data:

npx addon-kit login --scopes "read_jobs read_customers"

Login options:

OptionBehavior
--api-keyPrompt for an account API key instead of opening browser authorization.
--browser=falsePrint the authorization URL without automatically opening it. The browser must still reach the CLI machine's local callback.
--callback-port <port>Change the local callback port from its default, 8976.
--scopes "read_jobs read_customers"Request additional space-separated OAuth scopes. manage_addons is always requested.

Browser login times out after two minutes. Credentials are stored outside the project in ~/.sm8/; OAuth tokens refresh automatically. SM8_HOME selects another credential directory. SM8_API_KEY takes precedence over saved credentials, including OAuth login.

npx addon-kit logout removes local credentials. It does not revoke the ServiceM8 OAuth authorization or unset SM8_API_KEY. Deploy and tail do not start browser login automatically: use login first or supply SM8_API_KEY.

Run npx addon-kit login --help for the installed version's options.

The addon.jsonc configuration file

addon.jsonc combines the add-on manifest with Addon Kit settings such as the project slug and function entry point. JSON with Comments (JSONC) lets you document configuration inline, while the included schema provides validation and autocomplete in compatible editors.

{
  "$schema": "./node_modules/@servicem8/addon-kit/addon-schema.json",
  "slug": "job-weather",
  "name": "Job Weather Forecast",
  "version": "1.0",
  "main": "src/index.ts",
  "oauth": {
    "scope": "read_jobs"
  },
  "actions": [
    {
      "name": "Check Weather",
      "type": "online",
      "entity": "job",
      "iconURL": "https://example.com/icon-512.png",
      "event": "check_weather"
    }
  ]
}

Three keys are specific to Addon Kit and are removed before the manifest is sent to ServiceM8:

KeyDescription
$schemaPath to the JSON schema shipped with the package, for editor validation and autocomplete.
slugUniquely identifies the add-on on your account during deployment (lowercase letters, digits and hyphens). Deploying the same slug updates the existing add-on; changing it creates a new add-on.
mainThe function entry point to bundle. Defaults to index.js.

Every other field has the same meaning as in the Manifest Reference. Migrating an existing add-on is a matter of renaming manifest.json to addon.jsonc and adding a slug; addon-kit init offers to do this for you when run in a directory containing a manifest.json.

Your function

Add-ons deployed with Addon Kit are Simple Function add-ons. addon-kit init scaffolds a working handler:

export const handler = async (event: SM8Event) => {
	// event.eventName, event.eventArgs.jobUUID
	// event.auth.accessToken — a short-lived token for the ServiceM8 REST API
	return { eventResponse: "<html>…</html>" };
};

Your function receives the standard event data, including the short-lived access token used to call the ServiceM8 REST API. addon-kit deploy bundles whatever your entry point imports (TypeScript, multiple files, npm packages) into a single artifact of up to 45 MB.

Structured JSON logging

Your add-on should emit structured JSON logs. Write each log entry as a single JSON object on one line, with a consistent level, message, and relevant context fields so logs are easy to search and filter.

For example, inside your handler:

console.log(JSON.stringify({
  level: "info",
  message: "Processing add-on event",
  eventName: event.eventName,
  accountUUID: event.auth.accountUUID,
}));

Use JSON.stringify without indentation so each entry stays on one line; passing an object directly to console.log does not guarantee JSON output. Apply the same format to warnings and errors, using console.warn or console.error with the corresponding level. When logging an error, include its message and stack explicitly, since JSON.stringify does not include these properties on an Error object by default.

Log only the context you need. Do not log the entire event object, as it contains auth.accessToken, or include API keys or add-on secrets.

To stream live logs from your add-on in your terminal, run:

npx addon-kit tail

Commands

CommandDescription
addon-kit init [name]Scaffold an add-on or migrate a legacy manifest.json project. --yes / -y accepts defaults; --typescript=false selects JavaScript instead of the default TypeScript.
addon-kit loginAuthorize Addon Kit through browser OAuth or an API-key prompt. See the login options above.
addon-kit logoutRemove credentials stored on this machine.
addon-kit whoamiShow the authenticated account and OAuth scopes or API-key access level.
addon-kit deployValidate, bundle, deploy, and activate the add-on. --dry-run validates and bundles locally without authentication or deployment.
addon-kit secret put <key>Create or update a secret using a masked interactive prompt for its value.
addon-kit secret listList secret names only; takes no key argument and never returns values.
addon-kit secret delete <key>Delete a secret after interactive confirmation.
addon-kit tailStream live logs for the single add-on selected by addon.jsonc until Ctrl+C.

Run npx addon-kit <command> --help for command options, including npx addon-kit secret put --help for a nested command. Version 1.2.0 has no top-level add-on list or delete command.

Global flags

FlagBehavior
--config <path> / -c <path>Select a configuration file instead of addon.jsonc. Relative paths are resolved from --cwd or the current directory.
--cwd <directory>Select the working directory for the operation.
--help / -hShow help.
--version / -vPrint the installed CLI version.
--env <name> / -e <name>Listed in help but reserved: not supported in 1.2.0. Passing it to an operation returns an error.

For example, validate another project's bundle with addon-kit deploy --cwd ./my-addon --dry-run. The function's main path is relative to the selected configuration file.

Manage secrets

Run these commands from the deployed add-on's project:

npx addon-kit secret put API_TOKEN
npx addon-kit secret list
npx addon-kit secret delete API_TOKEN

Secret operations require manage_addons or a full-access API key, including listing names. Values are entered interactively, never as command arguments, and are supplied to the function as environment variables. You do not need to submit a code deployment to update a secret; applying the change can run in the background. Version 1.2.0 prints “applied immediately” after a successful put, but this does not mean a queued platform update has finished.

Stream live logs

npx addon-kit tail
npx addon-kit tail --filter '"ERROR"'
npx addon-kit tail --format json
npx addon-kit tail --cwd ./my-addon

tail uses the slug in the selected addon.jsonc and follows new log events until Ctrl+C. It requires an add-on owned by your authenticated account and a deployed ServiceM8-hosted Simple Function. Use browser OAuth with manage_addons or a full-access API key. No AWS CLI installation or AWS account setup is required.

OptionBehavior
--filter <pattern>Apply a CloudWatch Logs filter pattern. Quote patterns containing spaces.
--format prettyHuman-readable output; the default.
--format jsonEmit one JSON object per log event, including its message, timestamps and log stream name.

Log events are written to stdout; connection status and sampling notices go to stderr. Use --cwd or --config to select another project. Extra add-on IDs and log-group lists are not accepted.

The stream includes this add-on's executions across runtime regions and installing accounts. It follows newly ingested events, with a delay from log centralization; it does not retrieve historical logs. Reconnects obtain fresh credentials, but events during connection gaps are not replayed. High-volume streams may be sampled, which the CLI reports. If the log group does not exist yet, invoke the deployed function and retry after logs have been delivered.

Use Addon Kit in CI

Set the SM8_API_KEY environment variable in your CI system, then install dependencies and deploy:

- npm ci
- npx addon-kit deploy

Store SM8_API_KEY as a protected or encrypted CI secret. Do not commit an API key to your repository.


Did this page help you?