> ## Documentation Index
> Fetch the complete documentation index at: https://docs.enconvo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Developing Extensions

> Create a TypeScript command or Local API route with the Enconvo SDK.

An Enconvo plugin is an ESM package with metadata in `package.json`, commands under `src/`, and optional API routes under `src/api/`. Commands run through Enconvo's extension runtime; a plugin command is a default-exported function, not a class implementing a `Command` interface.

You need Node.js 18 or later, npm or another package manager, and Enconvo running on your Mac.

## Quick start

Create a plugin project in a new folder:

```sh theme={null}
npx -p @enconvo/api enconvo plugin create hello-enconvo
cd hello-enconvo
npm install
npm run dev
```

The project has one command (**Say Hello**), one Local API route, a placeholder icon, and a README. `npm run dev` builds the plugin into Enconvo and rebuilds it whenever you save. Search Enconvo for **Say Hello** to run it.

The plugin name comes from the folder name. Pass `--name`, `--title`, `--description` or `--author` to set them yourself. Pick a name that no plugin installed in Enconvo already uses, because building replaces the installed plugin's files; `plugin create` refuses such names.

To make a plugin that also installs in Codex and Claude Code, start from `--template skills` (a skill) or `--template mcp` (an MCP server) instead. See [Plugin Formats](/extensions/plugin-formats) for those packages, and [Installing Plugins](/extensions/installing-plugins) to try any plugin from a folder, GitHub or a marketplace.

<Note>
  `plugin create`, `plugin validate` and publishing for review need an `@enconvo/api` release newer than 0.1.173. If your version doesn't have them, set the project up by hand as described below.
</Note>

## Set up a project by hand

```text theme={null}
hello-enconvo/
├── package.json
├── tsconfig.json
├── src/
│   ├── hello.ts
│   └── api/
│       └── echo.ts
└── assets/
    └── icon.png
```

Create `package.json`:

```json theme={null}
{
  "$schema": "https://enconvo.com/schemas/extension.json",
  "name": "hello_enconvo",
  "version": "0.1.0",
  "title": "Hello Enconvo",
  "description": "A small example command and API.",
  "author": "Your Name",
  "icon": "icon.png",
  "type": "module",
  "categories": ["Productivity"],
  "commands": [
    {
      "name": "hello",
      "title": "Say Hello",
      "description": "Return a greeting for the input text.",
      "commandType": "command",
      "mode": "no-view"
    }
  ],
  "scripts": {
    "build": "enconvo plugin build",
    "dev": "enconvo plugin build --dev",
    "validate": "enconvo plugin validate"
  }
}
```

The first entry in `categories` picks the section the plugin appears in on the Plugins page and in the store: Productivity, Communication, Developer Tools, Data & Analytics, Finance, Creativity, Business & Operations, Education & Research or Security.

Install the SDK, and the build tools as development dependencies:

```sh theme={null}
npm install @enconvo/api
npm install --save-dev tsup typescript @types/node
```

`enconvo plugin build` compiles your code with the plugin's own `tsup`. Without it, the build has nothing to compile with; newer SDKs stop with an error, and older ones finish without building your commands.

Create `tsconfig.json`:

```json theme={null}
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "lib": ["ES2023", "DOM"],
    "types": ["node"],
    "strict": true,
    "skipLibCheck": true,
    "noEmit": true
  },
  "include": ["src"]
}
```

Put a square PNG, JPEG, WebP or GIF icon of up to 5 MB at `assets/icon.png`.

## Add a command

`commands[].name` matches the source filename. Put this in `src/hello.ts`:

```typescript theme={null}
import { EnconvoResponse, type RequestOptions } from "@enconvo/api";

export default async function main(request: Request) {
  const options = await request.json() as RequestOptions;
  const name = String(options.input_text || "").trim() || "World";
  return EnconvoResponse.text(`Hello, ${name}!`);
}
```

The command key is `hello_enconvo|hello`. Runtime preferences and request parameters are merged into the request body.

## Add a Local API route

Files in `src/api/` are discovered during the build and need no `commands[]` entry. Put this in `src/api/echo.ts`:

```typescript theme={null}
interface EchoParams {
  /** Text to return. @required */
  text: string;
}

/** Return the supplied text. */
export default async function main(request: Request) {
  const params = await request.json() as EchoParams;
  if (typeof params.text !== "string") {
    return Response.json({ error: "text must be a string" }, { status: 400 });
  }
  return Response.json({ text: params.text });
}
```

This becomes `hello_enconvo/echo`. A directory such as `src/api/items/list.ts` becomes `hello_enconvo/items/list`. Use the installed [Local API schemas](/advanced/cli-local-api) for exact request shapes.

## Build and test

```sh theme={null}
npm run build
npm run dev
npx enconvo plugin generate-schema
```

Build from the plugin directory. A good build ends with `ready - built extension successfully`. If it prints an `error` line, fix what it names and build again. Development mode watches files for rebuilds. API schemas are generated into the plugin's `skills/` directory.

Call the route while Enconvo is running:

```sh theme={null}
curl -X POST http://localhost:54535/api/hello_enconvo/echo \
  -H "Content-Type: application/json" -d '{"text":"hi"}'
```

Test a greeting and invalid API input before sharing the plugin. A successful build alone does not test native operations or every provider call.

## Publish to the plugin store

```sh theme={null}
npm run validate
npx enconvo plugin publish
```

`plugin validate` checks the plugin against the store rules without uploading anything; [Validation Codes](/extensions/validation-codes) explains each problem it reports. After a build, it also shows how many files the package will contain and which files are left out. It checks that the name uses only letters, digits, dots, dashes and underscores, that `version` looks like `1.2.3`, that the plugin has a title, and that the icon is a PNG, JPEG, WebP or GIF of up to 5 MB. You can add up to 8 screenshots in a `metadata/` folder; the plugin's page in the store shows them under its description, in file name order.

`plugin publish` builds the plugin and uploads it with the Enconvo account you're signed in with, so Enconvo has to be running and signed in. Enconvo reviews every version before it appears in the store. Until a new plugin is approved, only you can see it; while an update is in review, the store keeps offering the previous version. Raise `version` in `package.json` for every update. Before it builds anything, `plugin publish` asks the store which version it released, and stops with the next version to use when yours isn't higher. A version that is in review, or was turned down, can be submitted again as it is; the new upload replaces it.

The package is made from the built plugin. `.env` files, `node_modules`, version-control folders and `.zip` archives are left out, but check that no other credentials or private files end up in it.

Reviewers follow the [Plugin Store Guidelines](/extensions/publishing-guidelines). Add a `review` object to `package.json` with the prompts they should try, and pass sign-in details for a demo account with `--review-notes`; only reviewers see them.

To add your own AI model or text-to-speech voice to Enconvo's pickers, see [AI Model and Voice Plugins](/extensions/provider-plugins). For SDK building blocks, see [Extension API Reference](/extensions/extension-api-reference). For reusable multi-step processes that do not need a plugin, use [Workflows](/workflows/introduction).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.