Publishing a module
A module is an npm package that implements the Module interface from
@prxy/module-sdk. Once
published, you list it in the public registry
and it appears at modules.prxy.monster .
This page covers the end-to-end flow. The faster summary is in the Marketplace overview.
Step 1 — Build the module
// src/index.ts
import type { Module } from '@prxy/module-sdk';
const slackNotifier: Module = {
name: 'slack-notifier',
version: '1.0.0',
async post(ctx) {
if (ctx.response.usage.outputTokens > 5000) {
// ... post to Slack ...
ctx.logger.info('big response — pinged Slack');
}
},
};
export default slackNotifier;Rules:
- ESM only (
"type": "module"in yourpackage.json). - Default export is a
Module(or a factory function returning one). @prxy/module-sdkis a peer dependency, never a regular one — the gateway hoists a single copy.- All errors in
pre()should degrade to{ continue: true }— never throw out ofpre. - All side effects in
post()must be wrapped in try/catch — never throw out ofpost.
Suggested layout
@your-name/your-module/
├── package.json
├── README.md
├── src/index.ts ← default export: Module
└── dist/ ← compiled ESM, what npm publishesSuggested package.json
{
"name": "@your-name/your-module",
"version": "1.0.0",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"files": ["dist", "README.md", "LICENSE"],
"peerDependencies": {
"@prxy/module-sdk": "^1.0.0"
},
"devDependencies": {
"@prxy/module-sdk": "^1.0.0",
"typescript": "^5"
}
}Scope conventions
@prxy-official/*— reserved for modules maintained by ekkOS Technologies Inc. Do not use.@your-name/your-module— your own scope. Pick something distinctive.- Including
prxyin the package name (e.g.@you/prxy-slack-notifier) helps npm discoverability.
Step 2 — Test locally
You can load your module from a file path before publishing:
PRXY_PIPE='exact-cache,patterns,/abs/path/to/dist/index.js'The pipeline loader detects path-style entries and dynamically import()s
them at boot. Compile to ESM with tsc first.
The @prxy/module-sdk/testing helper (createTestContext) lands in
v1.1. For now, construct a RequestContext manually with stubs for
storage, apiKey, and logger.
Step 3 — Publish to npm
npm publish --access publicPublic npm scope is required so cloud users can be served the module without needing your private registry creds.
Step 4 — Submit to the registry
Open a PR to prxy-modules-registry
adding a manifest at modules/@community/your-module.json:
{
"name": "@community/your-module",
"displayName": "Your Module — what it does",
"version": "1.0.0",
"description": "One-line description that's actually useful.",
"author": {
"name": "Your Name",
"github": "your-handle",
"email": "you@example.com"
},
"license": "MIT",
"category": "side-effect",
"tags": ["notifications", "slack"],
"supports": { "cloud": true, "local": true },
"documentation": "https://github.com/your-handle/prxy-slack-notifier#readme",
"repository": "https://github.com/your-handle/prxy-slack-notifier",
"npm": "https://www.npmjs.com/package/@your-name/your-module",
"submittedAt": "2026-04-27T14:30:00Z",
"verified": false,
"dependencies": { "@prxy/module-sdk": "^1.0.0" },
"kind": "free"
}CI validates:
- Manifest matches the JSON schema at
schema/module-manifest.schema.json. - The npm package referenced exists.
- The license is OSI-approved (for free modules — paid modules can be proprietary).
A maintainer reviews and merges. The marketplace site rebuilds within an hour.
Step 5 — (Optional) Request verification
Open a follow-up issue on the registry repo titled “Verification request: @your-name/your-module”. A maintainer reviews:
- Source code (no telemetry, no exfiltration of
apiKey.providerKey) - Conformance to the SDK lifecycle contract
- Docs quality
- Test coverage
If accepted, the manifest’s verified: true and a ✅ badge appears on the
module’s marketplace page.
Distribution checklist
Before you publish:
- Tests cover the happy path AND the storage-unavailable fallback.
- README explains what the module does, when to use it, the full config schema, the metrics it emits, and a link to source.
- Module name in the
Moduleobject matches the npm package’s basename. - All side effects in
post()are wrapped in try/catch. -
pre()errors degrade to{ continue: true }instead of throwing. -
package.jsonhas"type": "module"and ESM exports. -
@prxy/module-sdkis inpeerDependencies(NOT regular dependencies).
Versioning
Follow semver. Major-bump for breaking changes to your module’s config or behaviour, minor for additive features, patch for bug fixes.
The SDK itself follows semver too — keep your peer dep loose enough to allow patch and minor SDK upgrades:
{
"peerDependencies": {
"@prxy/module-sdk": "^1.0.0"
}
}Breaking changes to the Module interface major-bump @prxy/module-sdk. The
gateway runs the version listed in your peer dep, falling back to whatever it
ships with if compatible.