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

@moxxy/sdk

v0.10.0

Published

Typed public surface for the moxxy framework: event types, define* factories, lifecycle hook signatures.

Readme


What this package is

@moxxy/sdk is the typed contract between the moxxy runtime and everything that plugs into it. Providers, modes, tools, channels, compactors, cache strategies, isolators, transcribers, view renderers, tunnel providers, agents, commands, and skills all use it as their interface to the runtime.

The package exports:

  • define* factories, the only blessed way to author each kind of block.
  • The MoxxyEvent discriminated union, covering every event the runtime can emit or replay.
  • ClientSession and SessionLike, the views channels and modes see.
  • Lifecycle hook signatures (onTurnStart, onAssistantMessage, and so on).
  • Small helper utilities that do not pull the runtime along: token accounting, compactor helpers, zod-to-JSON-Schema, tool gating, embedding caching, retryable-error classification.

It is the only moxxy package safe to depend on from a published plugin. @moxxy/core is the runtime, and plugins never import it.

Why depend on the SDK

  • Zero runtime dependencies. The package builds without pulling anything into your bundle. zod is declared as a peer dependency so your plugin and the host agree on one copy.
  • One contract, every block. The shape is consistent across tools, channels, providers, compactors, and the rest. Once you have written one plugin you know how to write the next.
  • Strict TypeScript. defineTool is generic on its zod schema so handler arguments are fully inferred. Types double as documentation.
  • Type-only views into the runtime. SessionLike exposes only what a channel needs and keeps the rest of the registry private.
  • Event-log first. Every block is reactive over a single typed event stream. No hidden globals, easy to record and replay.

Installation

npm install @moxxy/sdk zod
# or: pnpm add @moxxy/sdk zod
# or: yarn add @moxxy/sdk zod

zod is a peer dependency. The SDK does not ship it.

Requirements: Node.js 20.10 or later. Strict TypeScript is recommended.

Quickstart

A tool plugin in nine lines:

import { definePlugin, defineTool, z } from '@moxxy/sdk';

export default definePlugin({
  name: '@acme/moxxy-plugin-greet',
  tools: [
    defineTool({
      name: 'greet',
      description: 'Return a greeting for the given name.',
      inputSchema: z.object({ name: z.string() }),
      handler: ({ name }) => `Hello, ${name}!`,
    }),
  ],
});

Add a "moxxy" block to your package.json and moxxy auto-discovers it on the next launch:

{
  "moxxy": { "plugin": { "entry": "./dist/index.js", "kind": "tools" } }
}

That is the whole setup. moxxy plugins list will show your tool on the next session start.

What the SDK gives you

define* factories

| Factory | Defines | |---|---| | definePlugin | A bundle of any of the below. The discoverable unit. | | defineTool | A callable tool with a zod-typed input, optional permission, isolation, and compact display config. | | defineProvider | An LLM backend such as Anthropic, OpenAI, or a custom service. | | defineMode | A loop strategy. The agent's iteration topology (default, goal, research, and so on). | | defineCompactor | A context-window compaction strategy (summarise, drop, hybrid). | | defineCacheStrategy | Where to place provider cache breakpoints. | | defineChannel | A user-facing surface (TUI, HTTP, Telegram, web). | | defineCommand | A /slash command surfaced in every channel that hosts commands. | | defineSkill | A prompt-only Markdown skill (frontmatter + body). | | defineAgent | A subagent kind dispatchable from the parent loop. | | defineTranscriber | A speech-to-text backend wired into every audio-capable channel. | | definePermission | A permission rule contributed to the resolver chain. | | defineViewRenderer | A target for the agent-authored UI primitives. | | defineTunnelProvider | A public-URL tunnel for HTTP channels (cloudflared, ngrok). | | defineIsolator (via @moxxy/plugin-security) | A capability sandbox. The SDK exports the Isolator interface and the ISOLATION_RANK ordering. |

Types and events

import type {
  MoxxyEvent,            // the discriminated union of every event in the log
  EventLogReader,        // a stable view over the session's event log
  ClientSession,         // what channels and slash-commands see
  SessionLike,           // what modes, providers, and tools see
  PendingToolCall,
  PermissionDecision,
  ApprovalRequest, ApprovalDecision,
  ToolDef, ProviderDef, ModeDef, CompactorDef, CacheStrategyDef,
  Plugin, PluginSpec,
  Skill, SkillDef, SkillFrontmatter, SkillScope,
} from '@moxxy/sdk';

Helpers

  • zodToJsonSchema converts a zod schema to JSON Schema for provider tool calls.
  • isRetryableError and toFriendlyError classify provider errors uniformly.
  • estimateContextTokens and runCompactionIfNeeded are scaffolding for custom compactors.
  • CachedEmbeddingProvider wraps any EmbeddingProvider with on-disk caching.
  • dispatchToolCall invokes a tool through the full gating, permission, and isolation pipeline.
  • summarizeSessionTokensFromEvents and summarizeTokensByModel give pure token accounting over the event log.

Lifecycle hooks

A plugin can declare optional hooks: onInit, onTurnStart, onBeforeProviderCall, onToolCall, onToolResult, onEvent, onTurnEnd, and onShutdown. All are strongly typed and fire in plugin-registration order. The SDK exposes the hook context types. @moxxy/core invokes them at the right point in the loop.

Authoring a plugin

A tool plugin with the minimum surface:

import { definePlugin, defineTool, z } from '@moxxy/sdk';

export default definePlugin({
  name: '@acme/moxxy-plugin-weather',
  tools: [
    defineTool({
      name: 'get_weather',
      description: 'Fetch current weather for a city.',
      inputSchema: z.object({ city: z.string() }),
      // Handler args are inferred from the zod schema.
      handler: async ({ city }) => {
        const res = await fetch(`https://wttr.in/${encodeURIComponent(city)}?format=j1`);
        return res.json();
      },
      // Optional: gate the call, declare capabilities, customise the compact display.
      permission: { action: 'prompt' },
      isolation: { capabilities: { net: { mode: 'allowlist', hosts: ['wttr.in'] } } },
      compact: { verb: 'Fetching weather for', noun: { one: 'city', other: 'cities' }, previewKey: 'city' },
    }),
  ],
});

A provider plugin:

import {
  definePlugin,
  defineProvider,
  type LLMProvider,
  type ProviderRequest,
  type ProviderEvent,
} from '@moxxy/sdk';

class MyLlmClient implements LLMProvider {
  readonly name = 'my-llm';
  readonly models = MODELS;
  async *stream(req: ProviderRequest): AsyncIterable<ProviderEvent> {
    // call your backend; yield message_start / text_delta / tool_use_* / message_end
  }
  async countTokens(req: Pick<ProviderRequest, 'model' | 'messages' | 'system' | 'tools'>) {
    return 0; // or a real estimate
  }
}

const MODELS = [
  { id: 'flagship', contextWindow: 200_000, supportsTools: true, supportsStreaming: true },
];

export default definePlugin({
  name: '@acme/moxxy-provider-my-llm',
  providers: [
    defineProvider({
      name: 'my-llm',
      models: MODELS,
      createClient: (_config) => new MyLlmClient(),
    }),
  ],
});

A mode (loop strategy):

import { definePlugin, defineMode, type ModeContext, type MoxxyEvent } from '@moxxy/sdk';

async function* runMyMode(ctx: ModeContext): AsyncIterable<MoxxyEvent> {
  // emit events, call providers, dispatch tools, return when the turn ends.
}

export default definePlugin({
  name: '@acme/moxxy-mode-my',
  modes: [defineMode({
    name: 'my-mode',
    description: 'One-line summary surfaced in the /mode picker.',
    run: runMyMode,
  })],
});

Per-block author guides for skill, plugin, tool, channel, provider, loop strategy, compactor, and cache strategy live in the monorepo at .claude/agents/.

Architectural rules

Three invariants keep the framework swappable:

  1. @moxxy/sdk has zero internal dependencies. Enforced in CI via pnpm check:deps.
  2. @moxxy/core does not import any plugin. Plugins flow into core through the SDK only.
  3. Plugins never import @moxxy/core. If you find yourself wanting to, the missing piece belongs in the SDK.

Docs

Full documentation lives at docs.moxxy.ai: concepts, plugin author guides, channel guides, and recipes.

License

MIT. See the repository root for the full text.