Skip to main content

Overview

EnConvo’s extension system is fully open source, allowing you to create custom extensions tailored to your needs. Extensions are built with TypeScript/JavaScript and can access EnConvo’s powerful APIs.

Extension Repository

All official extensions are open source on GitHub

Getting Started

Prerequisites

  • Node.js 18+ installed
  • Basic TypeScript/JavaScript knowledge
  • EnConvo installed on your Mac

Extension Structure

my-extension/
├── package.json       # Extension metadata
├── src/
│   ├── index.ts      # Entry point
│   └── commands/     # Command handlers
├── assets/           # Icons and images
└── README.md         # Documentation

Creating Your First Extension

1

Initialize Project

npx create-enconvo-extension my-extension
cd my-extension
npm install
2

Configure Metadata

Edit package.json:
{
  "name": "my-extension",
  "displayName": "My Extension",
  "description": "My custom EnConvo extension",
  "version": "1.0.0",
  "enconvo": {
    "commands": [
      {
        "name": "hello",
        "title": "Say Hello",
        "description": "A simple hello command"
      }
    ]
  }
}
3

Write Command Handler

Edit src/index.ts:
import { Command, showToast } from '@enconvo/api';

export default class HelloCommand implements Command {
  async run(input: string): Promise<string> {
    showToast({ title: 'Hello!', message: input });
    return `Hello, ${input || 'World'}!`;
  }
}
4

Build and Test

npm run build
npm run dev  # Hot reload during development
5

Install Locally

Settings → Extensions → Install from Folder → Select your extension

Extension API

Core APIs

import {
  Command,          // Base command class
  showToast,        // Show notification
  showHUD,          // Show heads-up display
  getInput,         // Get user input
  getSelection,     // Get selected text
  setClipboard,     // Set clipboard content
  getClipboard,     // Get clipboard content
  openURL,          // Open URL in browser
  runAppleScript,   // Run AppleScript
} from '@enconvo/api';

AI APIs

import {
  chat,             // Send chat message to AI
  complete,         // Get completion
  embed,            // Get text embeddings
  generateImage,    // Generate image
} from '@enconvo/ai';

Storage APIs

import {
  LocalStorage,     // Persistent local storage
  SecureStorage,    // Encrypted storage for API keys
} from '@enconvo/storage';

UI APIs

import {
  Form,             // Form UI components
  List,             // List UI components
  Detail,           // Detail view
  Action,           // Actions/buttons
} from '@enconvo/ui';

Command Types

Simple Command

Returns text output:
export default class SimpleCommand implements Command {
  async run(input: string): Promise<string> {
    // Process input and return result
    return `Processed: ${input}`;
  }
}

Form Command

Shows a form for input:
import { Form, FormCommand } from '@enconvo/api';

export default class FormCommand implements FormCommand {
  async getForm(): Promise<Form> {
    return {
      fields: [
        { name: 'topic', type: 'text', label: 'Topic' },
        { name: 'length', type: 'dropdown', options: ['short', 'medium', 'long'] }
      ]
    };
  }
  
  async run(values: Record<string, any>): Promise<string> {
    return `Writing about ${values.topic} (${values.length})`;
  }
}

List Command

Shows a selectable list:
import { List, ListCommand } from '@enconvo/api';

export default class ListCommand implements ListCommand {
  async getItems(query: string): Promise<ListItem[]> {
    return [
      { title: 'Item 1', subtitle: 'Description', value: '1' },
      { title: 'Item 2', subtitle: 'Description', value: '2' }
    ];
  }
  
  async onSelect(item: ListItem): Promise<string> {
    return `Selected: ${item.value}`;
  }
}

Using AI in Extensions

import { chat, ChatMessage } from '@enconvo/ai';

export default class AICommand implements Command {
  async run(input: string): Promise<string> {
    const messages: ChatMessage[] = [
      { role: 'system', content: 'You are a helpful assistant.' },
      { role: 'user', content: input }
    ];
    
    const response = await chat({
      messages,
      model: 'gpt-4',
      temperature: 0.7
    });
    
    return response.content;
  }
}

Best Practices

try {
  const result = await riskyOperation();
  return result;
} catch (error) {
  showToast({ title: 'Error', message: error.message, style: 'failure' });
  return 'An error occurred';
}
import { showLoading, hideLoading } from '@enconvo/api';

showLoading('Processing...');
const result = await longOperation();
hideLoading();
import { SecureStorage } from '@enconvo/storage';

const apiKey = await SecureStorage.get('api-key');
Include clear README with usage examples and configuration instructions.

Publishing Extensions

Prepare for Publication

  1. Update version in package.json
  2. Write comprehensive README
  3. Add screenshots/GIFs
  4. Test thoroughly

Submit to Store

  1. Create GitHub repository
  2. Open issue in enconvo/extensions
  3. Follow submission template
  4. Wait for review

Share Directly

Share your extension via:
  • GitHub repository link
  • Direct .zip file
  • npm package

Debugging

Development Mode

Run with hot reload:
npm run dev

Console Logging

console.log('Debug info:', data);
// View in EnConvo → Debug → Console

Extension Logs

View logs: Settings → Extensions → [Extension] → View Logs

Resources