How to Create Custom Plugins Using the TREK Plugin SDK: Permissions and Development Guide

The TREK plugin SDK provides a Node.js toolchain for building isolated plugins that run in child processes, enforcing a strict permission model declared in trek-plugin.json where any unauthorized access throws PERMISSION_DENIED.

The TREK plugin SDK (trek-plugin-sdk) is the official development toolchain for extending TREK instances with custom functionality. By scaffolding a Node.js package that exports a definition via definePlugin, developers can create widgets, page extensions, and third-party integrations that interact with TREK data through a strictly permissioned context object. This guide covers the complete workflow from initial scaffolding to production publishing, with specific attention to the runtime permissions model that governs every interaction.

Scaffolding a New Plugin with the TREK Plugin SDK

The SDK provides an interactive wizard to bootstrap plugin projects. Running npx trek-plugin-sdk create launches a CLI that prompts for:

  • ID and location – the plugin’s directory path
  • Type – widget, page, integration, or trip-page
  • Permissions – initial TREK capabilities the plugin requires

As documented in plugin-sdk/README.md lines 5-13, the wizard optionally initializes a Git repository and installs development dependencies, producing a ready-to-develop folder structure.


# Interactive wizard

npx trek-plugin-sdk create

# Non-interactive with flags

npx trek-plugin-sdk create my-plugin --type widget
cd my-plugin

Live-Reload Development Environment

The dev command starts a local development server on port 4317 that mirrors production constraints while enabling rapid iteration. According to plugin-sdk/README.md lines 21-24, the server:

  • Injects a ctx object restricted to the permissions declared in your manifest
  • Provides a SQLite database (db:own) for private plugin data
  • Hot-reloads code changes without restarting

Access http://localhost:4317/preview to view your widget rendered inside an isolated iframe with the host’s theme applied.

npx trek-plugin-sdk dev

Writing Plugin Code

The definePlugin Export

Every plugin must export a definition created by definePlugin, as implemented in plugin-sdk/src/index.ts. The function accepts a configuration object containing lifecycle hooks and route definitions.

// my-plugin/index.js
const { definePlugin } = require('trek-plugin-sdk')

module.exports = definePlugin({
  async onLoad(ctx) {
    // Initialize private database tables
    await ctx.db.migrate('001', 'CREATE TABLE cache (k TEXT PRIMARY KEY, v TEXT)')
  },

  routes: [
    {
      method: 'GET',
      path: '/status',
      auth: true,
      async handler(req, ctx) {
        return {
          status: 200,
          headers: { 'content-type': 'application/json' },
          body: '{"ok":true}'
        }
      }
    },
  ],
})

The Permissioned Context Object

All interactions with TREK flow through the ctx object injected at runtime. The available methods—ctx.db, ctx.invoke, ctx.notify, and others—are filtered by the permission grants listed in your manifest. If your code attempts to call ctx.db.write() without the corresponding grant, the SDK immediately throws PERMISSION_DENIED.

Understanding the TREK Plugin Permissions Model

Permissions are declared in trek-plugin.json under the grants key. The manifest schema is defined in plugin-sdk/src/manifest.ts, while human-readable descriptions reside in shared/src/i18n/zh/admin.ts lines 220-239.

{
  "id": "my-plugin",
  "apiVersion": 1,
  "grants": [
    "db:own",
    "db:read:trips",
    "ws:broadcast:trip"
  ]
}

Core permission categories include:

  • db:* – Access to database capabilities. db:own grants a private SQLite sandbox, while db:read:* and db:write:* control access to specific TREK entities.
  • ws:broadcast:* – Permission to send real-time WebSocket messages to trips or individual users.
  • http:outbound – Allows the plugin to make external HTTP requests to approved hosts.
  • hook:* – Registers the plugin as an extension provider for features like photo sources or calendar integrations.

At runtime, the loader in server/src/nest/plugins/runtime/plugin-sdk.ts validates every ctx method call against the manifest’s grants array. Unauthorized calls throw PERMISSION_DENIED, which your plugin can catch to implement graceful degradation.

Testing Without a Running Instance

The SDK ships with a testing harness that enforces the exact same permission model as production. Import createMockHost from trek-plugin-sdk/testing to instantiate a mock context for unit testing, as shown in plugin-sdk/README.md lines 82-90.

import { createMockHost } from 'trek-plugin-sdk/testing'

const { ctx, broadcasts } = createMockHost({
  grants: ['db:read:trips', 'ws:broadcast:trip'],
  trips: { 1: { members: [42], data: { id: 1, name: 'Japan' } } },
})

// Exercise your plugin logic against the restricted ctx

Packaging and Publishing

When development is complete, the SDK provides commands to prepare your plugin for distribution:

  1. pack – Creates a signed .trekplugin archive from your build output
  2. publish – Uploads to a GitHub release and opens a PR against the TREK plugin registry

# Create distributable archive

npx trek-plugin-sdk pack .

# Publish to registry (requires GitHub authentication)

npx trek-plugin-sdk publish --repo you/repo --tag v1.0.0

Optional signing via keygen and sign commands provides cryptographic verification for trust-on-first-use scenarios.

Summary

  • Scaffold new plugins using npx trek-plugin-sdk create, selecting the appropriate type and initial permissions.
  • Develop against a live-reload server on port 4317 where the ctx object reflects your declared permissions.
  • Declare all required capabilities in trek-plugin.json under the grants key; the runtime enforces these strictly via PERMISSION_DENIED errors.
  • Test logic offline using createMockHost from the testing submodule to verify behavior under different permission configurations.
  • Distribute by packing into .trekplugin archives and publishing to the registry via the SDK CLI.

Frequently Asked Questions

What permissions do I need to access the database in a TREK plugin?

You must declare db:own in your trek-plugin.json grants to receive a private SQLite sandbox, or specific db:read:* and db:write:* grants to access TREK entity data. Any call to ctx.db without the appropriate permission throws PERMISSION_DENIED instead of executing.

How does the TREK plugin SDK isolate plugins from the host system?

The SDK executes each plugin in a separate child process and injects the trek-plugin-sdk module at runtime. All access to TREK services flows through the ctx object, which is filtered by the permission list in your manifest. This architecture prevents plugins from accessing system resources or data outside their declared grants.

Can I test my plugin without running a full TREK server?

Yes. The SDK provides createMockHost in the trek-plugin-sdk/testing submodule. This function creates a mock ctx object that enforces the same permission model as the production runtime, allowing you to write unit tests that verify behavior when specific grants are missing or present.

What file declares the permissions for a TREK plugin?

The trek-plugin.json file in your plugin root declares permissions under the grants key. This manifest is validated against the schema defined in plugin-sdk/src/manifest.ts and enforced at runtime by the loader in server/src/nest/plugins/runtime/plugin-sdk.ts.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →