NoteGenNOTEGEN.

API and type reference

Look up NoteGen's TypeScript contracts for manifests, lifecycle, PluginContext, data objects, and stable errors.

@notegen/plugin-api is the public TypeScript contract shared by plugin code and the NoteGen host. It provides types, an API-version constant, and a few authoring helpers. It does not connect to a service or let a plugin bypass PluginContext to obtain more authority.

Updated 2026-09-10: all four SDK packages are published on npm and the signed official marketplace is live; community submissions remain closed. API details describe the current development branch, so unreleased additions require the matching source version. Remote installation also requires a NoteGen build with plugin support and the production root public key.

Install and import

Install it as a development dependency:

pnpm add -D @notegen/plugin-api

A plugin entry normally imports only types:

import type { PluginActivate } from "@notegen/plugin-api";

export const activate: PluginActivate = async (ctx) => {
  ctx.commands.handle("com.example.hello.open", async () => {
    await ctx.ui.showNotice("Hello from NoteGen");
  });
};

import type disappears after compilation. If you use runtime values such as PluginError, isPluginError, PLUGIN_API_VERSION, or definePluginManifest, the builder must include the package code in the final single-file entry.

The package has no runtime dependencies and does not require DOM types in the TypeScript project.

Runtime value exports

ExportType or purpose
PLUGIN_API_VERSIONConcrete host API version described by this package; currently "0.1.0"
PLUGIN_ERROR_CODESRead-only list of every stable PluginErrorCode
PluginErrorError class with code, message, and optional details
isPluginError(value)Structurally recognizes a known plugin error across Workers or realms
definePluginManifest(manifest)Preserves literal manifest types and checks the v1 shape at compile time

definePluginManifest is an identity helper. It does not read or generate plugin.json, and it does not replace CLI or host validation.

Manifest JSON Schema

The package also publishes an editor-oriented JSON Schema through this deep entry point:

@notegen/plugin-api/plugin-manifest-v1.schema.json

For example, associate it with each plugin's plugin.json in a VS Code workspace .vscode/settings.json file:

{
  "json.schemas": [
    {
      "fileMatch": ["**/plugin.json"],
      "url": "./node_modules/@notegen/plugin-api/schema/plugin-manifest-v1.schema.json"
    }
  ]
}

The schema provides field completion, type hints, and structural diagnostics while editing. It does not replace notegen-plugin validate: namespace ownership, locale files, API/application compatibility, and packaged-file checks remain authoritative in the CLI and NoteGen host. Do not add a $schema property to plugin.json; strict manifest validation rejects undeclared fields.

Manifest and contribution types

CategoryExports
Main manifestPluginManifestV1, PluginAuthor, PluginPlatform, PluginActivationEvent
PermissionsPluginPermissionName, PluginPermissionScope, PluginPermissionDeclaration, PluginPermissionDeclarations
CommandsPluginCommandContribution
SettingsPluginSettingContribution, PluginSettingOption, PluginSettingValue
Status barPluginStatusBarContribution, PluginStatusBarUpdate
MenusPluginMenuLocation, PluginMenuContribution
AggregatePluginContributions

These types describe the maximum shape an author may declare, but TypeScript is not a security boundary. During import or installation, the host still rejects duplicate or unknown fields, explicit null, incompatible versions, invalid permission scopes, and broken contribution references. See Plugin configuration for the complete JSON rules.

Lifecycle types

interface PluginModule {
  activate: (context: PluginContext) => void | Promise<void>;
  deactivate?: () => void | Promise<void>;
}

type PluginActivate = PluginModule["activate"];
type PluginDeactivate = NonNullable<PluginModule["deactivate"]>;

interface PluginDisposable {
  readonly dispose: () => void;
}

The entry must export a named activate and may export deactivate. Event subscriptions and command handlers return PluginDisposable; call dispose() when the registration is no longer needed. The host also clears registrations owned by the stopped runtime instance.

PluginAbortSignal is the cancellation contract implemented by marketplace and development runtimes:

interface PluginAbortSignal {
  readonly aborted: boolean;
  readonly reason: unknown;
  readonly throwIfAborted: () => void;
  readonly addEventListener: (
    type: "abort",
    listener: PluginAbortListener,
    options?: { once?: boolean },
  ) => void;
  readonly removeEventListener: (
    type: "abort",
    listener: PluginAbortListener,
  ) => void;
}

It is not a native browser AbortSignal. Do not use instanceof AbortSignal or depend on undeclared DOM methods. See How plugins run.

PluginContext reference

MemberMain methodsPermission or declaration requirement
pluginid, version, apiVersionRead-only instance metadata
signalthrowIfAborted() and abort listenersNone; used to stop asynchronous work
commandshandle(commandId, handler)Command must be declared in the manifest
workspacegetCurrent(), onDidChangeNone; returns only an opaque ID and display name
calendarresolveDay(options)None; accepts an IANA time zone and HH:mm day boundary
notesRead, list, search, create, write, move, delete, and change eventsCorresponding notes.* permissions
attachmentsread, createSeparate attachments.read and attachments.create grants
editorActive editor, selection, snapshot, edits, and eventseditor.read; edits also require editor.write
loginfo, warning, errorLocal diagnostic messages; no automatic console capture
storage.deviceget, set, deletePlugin-private local KV
storage.workspaceget, set, deleteLocal KV partitioned by workspace ID
uiNotices, status bar, declarative views, and dialogsStatus-bar and view IDs must be declared
networkfetch(request)network.fetch, limited to user-approved HTTPS origins
i18nt(key, values?)Uses locale files declared by the manifest
settingsget, onDidChangeKey must be declared by contributes.settings

See Capabilities and permissions for every method's parameters, return values, permissions, quotas, and failure behavior.

Host data types

CapabilityParameter, result, and event types
WorkspaceWorkspaceInfo, WorkspaceChangeEvent
CalendarResolveDayOptions, ResolvedDay
NotesNoteSnapshot, NoteEntry, read/write/move options, NoteChangeEvent
Editor identityActiveEditorContext
Selection and textEditorSelection, GetEditorTextSnapshotOptions, EditorTextSnapshot
Editor edits and eventsApplyEditorEditOptions, ApplyEditorEditResult, EditorActiveChangeEvent, EditorContentChangeEvent
NetworkPluginNetworkRequest, PluginNetworkResponse
Declarative UIPluginUiDocument, PluginUiBlock, PluginDialogOptions
StoragePluginStorageArea

These objects are call-time snapshots. IDs are opaque and paths are workspace-relative; never infer an absolute path from an ID. Editor data carries a revision, so asynchronous readers must handle StaleRevision correctly.

JSON data boundary

Command arguments, command results, plugin storage values, and declarative UI action arguments share these public types:

type PluginJsonValue =
  | null
  | boolean
  | number
  | string
  | readonly PluginJsonValue[]
  | { readonly [key: string]: PluginJsonValue };

type PluginCommandArgument = PluginJsonValue | undefined;
type PluginCommandResult = PluginJsonValue | void;

PluginJsonValue contains only JSON values that can make a lossless round trip: null, booleans, finite numbers, strings, and recursive arrays or plain objects. An object property or array element cannot be undefined; use null for an explicit empty value or omit an unnecessary object property. Functions, symbols, BigInt, non-finite numbers, cyclic references, and class instances with custom prototypes are rejected. Convert Date, Map, Set, and error objects to plain JSON data first.

undefined has only two top-level command meanings: no argument was supplied to executeCommand, or a handler returned no value. It cannot be nested inside PluginJsonValue. Storage get() returns undefined only when a key does not exist; set() still accepts only PluginJsonValue.

API version values

The manifest's apiVersion is the SemVer range accepted by the plugin:

{
  "apiVersion": "^0.1.0"
}

PLUGIN_API_VERSION and the running ctx.plugin.apiVersion are concrete versions:

import { PLUGIN_API_VERSION } from "@notegen/plugin-api";
import type { PluginActivate } from "@notegen/plugin-api";

export const activate: PluginActivate = async (ctx) => {
  // PLUGIN_API_VERSION === "0.1.0"
  // ctx.plugin.apiVersion === "0.1.0" in the current host
};

The public type of ctx.plugin.apiVersion remains string, because users may run the plugin on a compatible host newer than the SDK used during development. Use it for diagnostics, not as a replacement for the manifest compatibility range.

Handle API errors

Every stable code belongs to PluginErrorCode. Across a Worker boundary, do not rely only on instanceof PluginError; use isPluginError:

import { isPluginError } from "@notegen/plugin-api";
import type { PluginActivate } from "@notegen/plugin-api";

export const activate: PluginActivate = async (ctx) => {
  try {
    await ctx.notes.read({ path: "Templates/example.md" });
  } catch (error) {
    if (isPluginError(error) && error.code === "PermissionDenied") {
      await ctx.ui.showNotice("The selected file is not authorized.");
      return;
    }
    throw error;
  }
};

isPluginError is a value import and must be bundled into the entry. Branch on the stable code; do not match the complete English message. See Capabilities and permissions for the full list.

Single-file loading boundary

The plugin runtime loads one self-contained ESM entry selected by the manifest. It does not resolve relative modules, npm packages, Node.js built-ins, or remote modules from that entry.

  • Prefer import type when only types are needed.
  • Bundle this package's runtime values and other dependencies with notegen-plugin build.
  • Without a bundler, the final entry can depend only on the ctx supplied by NoteGen.
  • The built output must contain no residual static or dynamic imports.

This package does not expose the marketplace catalog, installation records, signature validators, host storage state, Worker/RPC messages, or other host internals.

Continue reading

Additional API types

Forms export PluginFormBlock, PluginFormField, and PluginFormValue. View visibility uses PluginViewState. Search uses SearchNotesOptions and SearchNotesResult. Source-range operations use EditorRangeEdit, ApplyEditorEditsOptions, and SetEditorSelectionOptions. Attachment reads return PluginAttachment.

The SDK has completed its initial npm publication. Changes to published package contents require a package version bump; protocol compatibility changes require coordinated host and SDK updates. Declare the supported protocol range in apiVersion, such as ^0.1.0. Use commit revisions to distinguish unpublished development snapshots.