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

@ericsanchezok/synergy-plugin

v3.0.23

Published

`definePlugin()` is the only source of plugin identity, capabilities, contributions, and executable handlers. Authors do not write `plugin.json`; `synergy-plugin build` generates it with runtime/UI bundles and integrity metadata.

Readme

Synergy Plugin API 4

definePlugin() is the only source of plugin identity, capabilities, contributions, and executable handlers. Authors do not write plugin.json; synergy-plugin build generates it with runtime/UI bundles and integrity metadata.

import z from "zod"
import { capability, definePlugin, event, operation, workbenchPanel } from "@ericsanchezok/synergy-plugin"

export default definePlugin({
  id: "example",
  version: "1.0.0",
  description: "Example plugin",
  compatibility: { synergy: ">=3.0.11" },
  assets: [{ source: "src/prompts", target: "runtime/prompts" }],
  capabilities: [capability("workspace.read"), capability("ui.hostActions")],
  contributions: [
    event({ id: "example.changed", payload: z.object({ reason: z.string() }) }),
    operation({
      id: "example.get",
      type: "query",
      input: z.object({}),
      output: z.object({ scopeId: z.string() }),
      async handler(_input, context) {
        return { scopeId: context.scopeId }
      },
    }),
    workbenchPanel({
      id: "main",
      label: "Example",
      surface: "side",
      cardinality: "singleton",
      component: { source: "./src/ui.tsx" },
    }),
  ],
})

Definition Rules

  • Plugin IDs use lowercase letters, digits, dots, and hyphens and begin with a letter.
  • Contribution IDs are unique within each contribution kind. A command operation and its ui.textAction may intentionally share a local ID; generated runtime handler IDs remain kind-qualified.
  • A contribution's requires entries must exist in top-level capabilities.
  • operation() defaults to expose: ['ui']; add sdk explicitly for public SDK access.
  • Zod and JSON Schema are accepted for operation, event, and tool schemas.
  • activate() runs once per runtime generation and does not receive Scope or Session state.
  • Top-level assets map project-relative files or directories into package-relative targets. Asset contents are integrity-checked and included in the generation hash.
  • The plugin and plugin-kit npm package versions follow the Synergy product release version; package major versions do not select a Plugin API family.
  • apiVersion stays "4.0" for the stable API4 family. Set compatibility.synergy only when the plugin needs a newer additive host feature; otherwise the GA baseline is generated automatically.
  • Stable API4 types and behavior remain backward compatible. Avoid experimental.* in published stable plugins because those surfaces may change or disappear.

Contribution Factories

Executable factories: operation, tool, hook, cliCommand, authProvider, lifecycleInstall, lifecycleUpgrade, and lifecycleUninstall.

Declarative factories: event, agent, skill, mcp, workbenchPanel, navigationItem, messageRenderer, composerAction, composerExtension, selectionExtension, textAction, messageSlot, settings, theme, and icon.

The generated manifest contains declarations only. Runtime startup reports its actual handler IDs, and the host requires an exact match.

Invocation Context

Every executable call receives a fresh PluginInvocationContext with request ID, Scope, optional Session, actor, cancellation, logger, scoped events, and only the Host Services allowed by approved capabilities. Plugins never receive a raw Synergy client, server URL, or token.

Capabilities govern Host Services; they do not claim to restrict direct OS access by the external process. task.delegate exposes start/run/current/get/cancel; run() waits for a native Cortex Task and returns its terminal snapshot, while current() reads the durable owner of the invoking child Session. Non-agent callers must provide an explicit parent Session/message for start() in the active Scope. Contributed Agents are registered in Synergy's native Agent registry. Set hidden: true for an owner-only Agent that must stay out of ordinary prompt and native-task exposure.

asset.write exposes context.asset.create() and returns a host-owned attachment. shell.execute exposes argv-only context.shell.run() through the ordinary permission and sandbox boundary. cliCommand() registers executable commands under synergy <pluginId> <command>. MCP contributions use strict shared local/remote schemas and are installed atomically under qualified ${pluginId}::${contributionId} names.

runtime.endpoint.read exposes context.runtimeEndpoint.get(). It accepts no arguments and returns only the current loopback HTTP origin plus an opaque listener generation. It never returns a token, route, SDK client, or wider server configuration. Loopback and wildcard binds are served over loopback and return a normalized http://127.0.0.1:<port> URL; a bind that excludes loopback makes the service fail closed. External process management remains plugin-owned.

task.delegate is the plugin capability; task is the separate runtime permission evaluated by the current control profile. task.start() parent binding failures expose PluginHostServiceErrorCode.TASK_PARENT_REQUIRED or TASK_PARENT_SCOPE_MISMATCH. Host Service error codes survive process IPC.

agent.call exposes bounded Sessionless Agent work only to an executable contribution that lists it in requires. context.agent.call() waits for text; context.agent.start() returns a call ID immediately and reports its memory-only terminal result to the same plugin generation and Scope through agent.call.after. By default a plugin may call only a hidden Agent owned by its active generation; capability constraints may allow additional Agent names, permitted model roles, and lower host runtime/input/output ceilings. Calls may choose an allowed Synergy role but never a concrete provider/model ID. Neither path has tools, Session history, or Cortex lifecycle.

Trusted UI

UI API 5 uses PluginComponentProps<Context> with one context property for every executable surface. The public service types cover environment/navigation, session collections and messages, draft/editor/submission, workbench resources, commands, overlays and lifetime. Specialized settings values, changes and save status live in context.settings. Import host components through @ericsanchezok/synergy-plugin/components, semantic icon types through /icons, formatting through /format, and Skin schemas through /skin.

import type { PluginComponentProps } from "@ericsanchezok/synergy-plugin"
import { EmptyState } from "@ericsanchezok/synergy-plugin/components"

export default function Panel({ context }: PluginComponentProps) {
  return <EmptyState title={context.surface.id} description="Plugin content" />
}

Plugin Kit generates artifacts.ui.apiVersion, named exports and hashes for the full JS/CSS/font/image graph. The host shares Solid, scopes styles and portals, and disposes registrations by generation. UI 4 executable surfaces require a rebuild and migration; backend API4 compatibility remains independent. See UI contributions for services, Shells, Skins and real-host preview, and UI 4 migration for the breaking changes.

Runtime and Data

External plugins run in one process per active pluginId + version + generation; enabled Scopes share it and receive separate invocation contexts. Trusted built-ins may use inProcess. The process boundary is crash/resource cleanup isolation, not an OS security sandbox.

The runtime transport protocol is host-owned. runtime.protocolVersion is diagnostic provenance, not a plugin feature gate or compatibility contract; use apiVersion and compatibility.synergy instead.

Plugins own their business data, schema, concurrency, backup, migration, and deletion. Synergy stores only installation metadata, approval, Scope enablement, declarative settings, and plugin credentials.

Integrity Contract

@ericsanchezok/synergy-plugin/integrity owns the canonical manifest and permissions hash functions used by plugin-kit signing, marketplace metadata, installation verification, and approval records. The permissions hash binds capability constraints, contribution requirements, operation exposure, and trusted UI presence. Tooling and hosts must import this contract rather than reimplement its serialization or payload.

Toolchain

synergy-plugin build
synergy-plugin validate --runtime-discovery
synergy-plugin test
synergy-plugin pack
synergy-plugin dev --server-url http://127.0.0.1:PORT

Live reload requires an explicit isolated SYNERGY_HOME. Successful rebuilds publish a new generation atomically; failed builds leave the previous generation active.

See docs/plugins for architecture, lifecycle, marketplace, security, and UI guidance.