npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@useatlas/plugin-sdk

v0.0.7

Published

Type definitions and helpers for authoring Atlas plugins

Downloads

91

Readme

@useatlas/plugin-sdk

Type definitions and helpers for authoring Atlas plugins. Plugins extend Atlas with new datasources, context providers, interaction surfaces, actions, and sandbox backends.

Quick Start

import { createPlugin } from "@useatlas/plugin-sdk";
import { z } from "zod";

export const myPlugin = createPlugin({
  configSchema: z.object({ url: z.string() }),
  create: (config) => ({
    id: "my-datasource",
    types: ["datasource"] as const,
    version: "1.0.0",
    config,
    connection: {
      create: () => makeConnection(config.url),
      dbType: "postgres",
    },
  }),
});

Register in atlas.config.ts:

import { defineConfig } from "@atlas/api/lib/config";
import { myPlugin } from "./my-plugin";

export default defineConfig({
  plugins: [myPlugin({ url: process.env.MY_DB_URL! })],
});

Plugin Types

Atlas has five plugin types. Each extends AtlasPluginBase with variant-specific fields.

Datasource (AtlasDatasourcePlugin)

Connect to a database. Provides a connection factory, SQL dialect hints, and optional entity definitions.

| Field | Type | Required | Description | |-------|------|----------|-------------| | connection.create() | () => PluginDBConnection | Yes | Factory that returns a connection with query() and close() | | connection.dbType | PluginDBType | Yes | Database type identifier (postgres, mysql, clickhouse, snowflake, duckdb, or custom) | | entities | EntityProvider | No | Semantic layer fragments merged into the table whitelist at boot | | dialect | string | No | SQL dialect guidance injected into the agent system prompt |

Reference: clickhouse

Context (AtlasContextPlugin)

Inject knowledge into the agent. Context plugins load additional system prompt fragments, semantic layer extensions, or external metadata.

| Field | Type | Required | Description | |-------|------|----------|-------------| | contextProvider.load() | () => Promise<string> | Yes | Returns context string appended to the agent system prompt | | contextProvider.refresh() | () => Promise<void> | No | Cache invalidation hook |

Reference: yaml-context

Interaction (AtlasInteractionPlugin)

Add communication surfaces. Interaction plugins mount HTTP routes or manage non-HTTP transports (stdio, SSE).

| Field | Type | Required | Description | |-------|------|----------|-------------| | routes | (app: Hono) => void | No | Mount Hono routes for webhooks, OAuth, etc. Optional for non-HTTP transports |

Reference: slack, mcp

Action (AtlasActionPlugin)

Enable agent side-effects. Action plugins provide AI SDK tools with approval controls.

| Field | Type | Required | Description | |-------|------|----------|-------------| | actions | PluginAction[] | Yes | Array of action definitions | | actions[].name | string | Yes | Tool name | | actions[].tool | ToolSet[string] | Yes | AI SDK tool definition | | actions[].actionType | string | Yes | Category identifier (e.g. jira:create) | | actions[].reversible | boolean | Yes | Whether the action can be undone | | actions[].defaultApproval | ActionApprovalMode | Yes | auto, manual, or admin-only | | actions[].requiredCredentials | string[] | Yes | Config fields needed at runtime |

Reference: jira, email

Sandbox (AtlasSandboxPlugin)

Provide code isolation for the explore tool. Sandbox plugins create backends that execute shell commands in an isolated environment.

| Field | Type | Required | Description | |-------|------|----------|-------------| | sandbox.create(semanticRoot) | (string) => PluginExploreBackend | Yes | Factory that creates an explore backend | | sandbox.priority | number | No | Higher = tried first. Built-in: Vercel=100, E2B=90, Daytona=85, nsjail=75, sidecar=50, just-bash=0. Plugin default: 60 | | security | object | No | Informational metadata about isolation guarantees |

Reference: nsjail, vercel-sandbox

Base Fields

All plugins share these fields from AtlasPluginBase:

| Field | Type | Required | Description | |-------|------|----------|-------------| | id | string | Yes | Unique identifier (e.g. clickhouse-datasource) | | type | PluginType | Yes | One of datasource, context, interaction, action, sandbox | | version | string | Yes | SemVer version | | name | string | No | Human-readable display name | | config | TConfig | No | Plugin-specific configuration | | initialize(ctx) | (AtlasPluginContext) => Promise<void> | No | Called once at server boot. Throw to block startup | | healthCheck() | () => Promise<PluginHealthResult> | No | Periodic health probe | | teardown() | () => Promise<void> | No | Graceful shutdown (LIFO order) | | hooks | PluginHooks | No | Agent lifecycle and HTTP hooks | | schema | Record<string, PluginTableDefinition> | No | Declarative table definitions for the internal DB |

Lifecycle

register → initialize(ctx) → healthCheck() → ... → teardown()
  1. Register — Plugins are listed in the plugins array in atlas.config.ts. Config is validated at factory call time (before server starts).
  2. Initialize — Called once at server boot with AtlasPluginContext. Throw to signal fatal initialization failure. Context provides:
    • ctx.db — Internal Postgres (auth/audit DB). Null when DATABASE_URL is not set.
    • ctx.connections — Connection registry for analytics datasources.
    • ctx.tools — Tool registry for adding agent tools.
    • ctx.logger — Pino-compatible child logger scoped to the plugin.
    • ctx.config — Resolved Atlas configuration.
  3. Health check — Periodic probe. Return { healthy: false, message } to signal degradation. Never throw.
  4. Teardown — Graceful shutdown in reverse registration order (LIFO).

v1.1 note: AtlasPluginContext will gain executeQuery, conversations, and actions fields for full host-level decoupling. Currently, interaction plugins that need these inject them via config callbacks.

Config Validation

Use createPlugin() with a Zod schema for typed, validated configuration:

import { createPlugin } from "@useatlas/plugin-sdk";
import { z } from "zod";

const configSchema = z.object({
  url: z.string().url(),
  poolSize: z.number().int().positive().optional(),
});

export const myPlugin = createPlugin({
  configSchema,
  create: (config) => ({
    id: "my-datasource",
    types: ["datasource"] as const,
    version: "1.0.0",
    config,
    connection: { create: () => connect(config.url), dbType: "postgres" },
  }),
});

The factory validates config at call time — invalid config fails fast during startup, not at first use. The configSchema accepts any object with a parse(input) method (Zod schemas satisfy this).

For simple plugins without config validation, use definePlugin():

import { definePlugin } from "@useatlas/plugin-sdk";

export default definePlugin({
  id: "my-context",
  types: ["context"],
  version: "1.0.0",
  contextProvider: { async load() { return "Extra context..."; } },
});

Hooks

Hooks use a matcher + handler pattern inspired by Better Auth. Matchers are optional — omit to always fire.

hooks: {
  beforeQuery: [{
    matcher: (ctx) => ctx.connectionId === "warehouse",
    handler: (ctx) => {
      // Return { sql } to rewrite, throw to reject, return void to pass through
      return { sql: ctx.sql.replace(/SELECT \*/, "SELECT id, name") };
    },
  }],
  afterQuery: [{
    handler: (ctx) => {
      console.log(`Query took ${ctx.durationMs}ms, returned ${ctx.result.rows.length} rows`);
    },
  }],
}

| Hook | Context | Mutation | Description | |------|---------|----------|-------------| | beforeQuery | { sql, connectionId? } | { sql } | Fires before SQL execution. Return to rewrite, throw to reject | | afterQuery | { sql, connectionId?, result, durationMs } | — | Fires after SQL execution | | beforeExplore | { command } | { command } | Fires before explore command. Return to rewrite, throw to reject | | afterExplore | { command, output } | — | Fires after explore command | | onRequest | { path, method, headers } | — | HTTP-level: fires before routing | | onResponse | { path, method, status } | — | HTTP-level: fires after response |

Schema Migrations

Plugins declare internal database tables via the schema property:

schema: {
  slack_installations: {
    fields: {
      team_id: { type: "string", required: true, unique: true },
      bot_token: { type: "string", required: true },
      installed_at: { type: "date" },
    },
  },
},

Run migrations with the CLI:

atlas migrate          # Preview migration SQL
atlas migrate --apply  # Apply to internal DB

Tables are prefixed with the plugin ID to avoid collisions.

$InferServerPlugin

Extract plugin types on the client side without importing server code:

import type { $InferServerPlugin } from "@useatlas/plugin-sdk";
import type { clickhousePlugin } from "@useatlas/clickhouse";

type CH = $InferServerPlugin<typeof clickhousePlugin>;
// CH["Config"]   → { url: string; database?: string }
// CH["Type"]     → "datasource"
// CH["DbType"]   → "clickhouse"
// CH["Actions"]  → never (not an action plugin)
// CH["Security"] → never (not a sandbox plugin)

Works with both createPlugin() factory functions and definePlugin() direct objects.

Available inferred fields: Config, Type, Id, Name, Version, DbType (datasource only), Actions (action only), Security (sandbox only).

CLI

atlas plugin list                              # List installed plugins from atlas.config.ts
atlas plugin create <name> --type <type>       # Scaffold a new plugin (datasource|context|interaction|action|sandbox)
atlas plugin add <package-name>                # Install a plugin package via bun

atlas plugin create generates a plugins/<name>/ directory with src/index.ts, src/index.test.ts, package.json, and tsconfig.json.

Type Guards

import {
  isDatasourcePlugin,
  isContextPlugin,
  isInteractionPlugin,
  isActionPlugin,
  isSandboxPlugin,
} from "@useatlas/plugin-sdk";

if (isDatasourcePlugin(plugin)) {
  // plugin is AtlasDatasourcePlugin — connection, entities, dialect available
}

Reference Implementations

Note: These are workspace packages (@useatlas/*) within the monorepo. Use them as reference when authoring your own plugins.

| Plugin | Type | Package | Description | |--------|------|---------|-------------| | clickhouse | Datasource | @useatlas/clickhouse | ClickHouse HTTP transport adapter | | mysql | Datasource | @useatlas/mysql | MySQL pool-based adapter | | snowflake | Datasource | @useatlas/snowflake | Snowflake callback-based adapter | | duckdb | Datasource | @useatlas/duckdb | DuckDB in-process adapter | | yaml-context | Context | @useatlas/yaml-context | YAML semantic layer context provider | | mcp | Interaction | @useatlas/mcp | MCP server lifecycle (stdio + SSE) | | slack | Interaction | @useatlas/slack | Slack bot (slash commands, threads, OAuth) | | jira | Action | @useatlas/jira | Create JIRA tickets from analysis | | email | Action | @useatlas/email | Send email reports via Resend | | nsjail | Sandbox | @useatlas/nsjail | Linux namespace isolation via nsjail | | sidecar | Sandbox | @useatlas/sidecar | HTTP-isolated container sidecar | | vercel-sandbox | Sandbox | @useatlas/vercel-sandbox | Firecracker microVM via @vercel/sandbox | | daytona | Sandbox | @useatlas/daytona | Daytona managed cloud sandbox | | e2b | Sandbox | @useatlas/e2b | E2B Firecracker microVM (managed) |

Source

The definitive type definitions are in src/types.ts. Factory functions and type guards are in src/helpers.ts.