Nitejar Docs
Build on NitejarPlugin SDK

Manifest Format

The nitejar-plugin.json schema that every plugin requires.

Every plugin needs a nitejar-plugin.json file at its package root. This manifest tells the runtime what the plugin provides, what permissions it needs, and where to find the entry point.

Minimal manifest

For simple plugins that only contribute an integration handler:

{
  "schemaVersion": 1,
  "id": "nitejar.my-plugin",
  "name": "My Plugin",
  "description": "What this plugin does",
  "entry": "dist/index.js",
  "permissions": []
}

Full manifest

For plugins that contribute integrations, hooks, and skills with permission declarations:

{
  "schemaVersion": 1,
  "id": "com.acme.jira",
  "name": "Acme Jira",
  "version": "1.0.0",
  "description": "Jira integration and triage hooks",
  "entry": "./dist/index.js",
  "engine": {
    "nitejar": ">=0.1.0 <1.0.0",
    "node": ">=20"
  },
  "author": "Acme",
  "license": "MIT",
  "homepage": "https://acme.dev/nitejar-jira",
  "repository": "https://github.com/acme/nitejar-jira",
  "activation": {
    "onStartup": true,
    "onIntegrationTypes": ["jira"],
    "onHooks": ["tool.pre_exec", "response.pre_deliver"]
  },
  "permissions": {
    "network": ["api.atlassian.com"],
    "secrets": ["jira.api_token"],
    "filesystemRead": [],
    "filesystemWrite": [],
    "allowProcessSpawn": false
  },
  "contributes": {
    "integrations": ["jira"],
    "hooks": ["tool.pre_exec", "tool.post_exec", "response.pre_deliver"],
    "skills": ["jira-triage"]
  }
}

Field reference

Required fields

FieldTypeDescription
schemaVersion1Always 1. Will increment if the manifest format changes.
idstringGlobally unique plugin ID. Convention: nitejar.<type> for first-party, reverse domain for third-party (com.acme.jira).
namestringHuman-readable name. Shown in the admin catalog.
entrystringPath to the built ESM entry point, relative to the plugin root.

Optional metadata

FieldTypeDescription
versionstringSemver version string.
descriptionstringOne-liner for catalog cards. Keep it concrete.
authorstringPlugin author name or organization.
licensestringSPDX license identifier.
homepagestringURL to the plugin's documentation or marketing page.
repositorystringURL to the source code repository.

engine

Declares compatibility constraints. The runtime checks these before activation.

FieldTypeDescription
engine.nitejarstringSemver range for Nitejar version compatibility.
engine.nodestringSemver range for Node.js version.

activation

Controls when the plugin is loaded.

FieldTypeDescription
activation.onStartupbooleanLoad this plugin at boot time.
activation.onIntegrationTypesstring[]Load when an integration of these types exists.
activation.onHooksstring[]Load when these hook events are dispatched.

permissions

Declares what the plugin accesses. In self_host_open mode, these are disclosure-only (not enforced at runtime). In self_host_guarded mode, enforcement applies at host-managed API boundaries.

FieldTypeDescription
permissions.networkstring[]Hostnames the plugin needs to reach.
permissions.secretsstring[]Named secret keys the plugin reads.
permissions.filesystemReadstring[]Filesystem paths the plugin reads.
permissions.filesystemWritestring[]Filesystem paths the plugin writes.
permissions.allowProcessSpawnbooleanWhether the plugin spawns child processes.

contributes

Declares what the plugin adds to the runtime.

FieldTypeDescription
contributes.integrationsstring[]Integration type identifiers this plugin provides.
contributes.hooksstring[]Hook event names this plugin handles.
contributes.skillsstring[]Skill IDs this plugin contributes.

Building

Plugins bundle to a single ESM file. Keep @nitejar/plugin-sdk as an external dependency -- the host runtime provides it.

One-liner with esbuild:

npx esbuild src/index.ts \
  --bundle \
  --format=esm \
  --outfile=dist/index.js \
  --platform=node \
  --external:@nitejar/plugin-sdk

Or in your package.json:

{
  "scripts": {
    "build": "npx esbuild src/index.ts --bundle --format=esm --outfile=dist/index.js --platform=node --external:@nitejar/plugin-sdk"
  }
}

Why external? The host runtime already has @nitejar/plugin-sdk loaded. Bundling it in creates duplicate types and breaks instanceof checks.

Publishing to npm

  1. Make sure nitejar-plugin.json and dist/index.js are included in your package.
  2. Set up your package.json:
{
  "name": "nitejar-plugin-my-plugin",
  "version": "0.1.0",
  "type": "module",
  "files": ["dist", "nitejar-plugin.json"],
  "dependencies": {
    "@nitejar/plugin-sdk": "^0.1.0"
  }
}
  1. Run npm publish.
  2. Users install via the app UI: Plugins > Install from npm and enter the package name.