Skip to main content

API Reference

This page provides complete API documentation for the extension system.

Extension Interface

The main interface that all extensions must implement. All methods are optional - implement only what you need.

interface Extension {
// Lifecycle
onLoad?(context: ExtensionContext): void | Promise<void>;
onUnload?(): void | Promise<void>;

// Registration
getTools?(context: ExtensionContext, mode: string, agentProfile: AgentProfile): ToolDefinition[];

getCommands?(context: ExtensionContext): CommandDefinition[];
getModes?(context: ExtensionContext): ModeDefinition[];
getAgents?(context: ExtensionContext): AgentProfile[];

// UI Components
getUIComponents?(context: ExtensionContext): UIComponentDefinition[];
getUIExtensionData?(componentId: string, context: ExtensionContext): Promise<unknown>;
executeUIExtensionAction?(componentId: string, action: string, args: unknown[], context: ExtensionContext): Promise<unknown>;

// Agent Profile Updates
onAgentProfileUpdated?(context: ExtensionContext, agentId: string, updatedProfile: AgentProfile): Promise<AgentProfile>;

// Event Handlers - See Events Reference for details
onTaskCreated?(event, context): Promise<void | Partial<Event>>;
onPromptTemplate?(event, context): Promise<void | Partial<PromptTemplateEvent>>;
// ... and more event handlers
}

ExtensionContext

Passed to all extension methods, providing access to AiderDesk APIs.

interface ExtensionContext {
// Logging
log(message: string, type?: 'info' | 'error' | 'warn' | 'debug'): void;

// Project access
getProjectDir(): string;
getProjectContext(): ProjectContext;

// Task access
getTaskContext(): TaskContext | null;

// Memory access
getMemoryContext(): MemoryContext;

// Model access
getModelConfigs(): Promise<Model[]>;

// Settings access
getSetting(key: string): Promise<unknown>;
updateSettings(updates: Partial<SettingsData>): Promise<void>;

// UI refresh
triggerUIDataRefresh(componentId?: string, taskId?: string): void;
triggerUIComponentsReload(): void;

// Navigation
openUrl(url: string, target?: 'external' | 'window' | 'modal-overlay'): Promise<void>;
openPath(path: string): Promise<boolean>;
}

Methods

MethodDescription
log(message, type?)Log a message to AiderDesk console and log files
getProjectDir()Get the current project directory path
getTaskContext()Get the current task context (null if no task active)
getProjectContext()Get the project context for project operations
getMemoryContext()Get the memory context for store/retrieve/delete memory operations
getModelConfigs()Get all available model configurations
getSetting(key)Get a setting value (supports dot-notation)
updateSettings(updates)Update multiple settings at once
triggerUIDataRefresh(componentId?, taskId?)Trigger UI component data refresh
triggerUIComponentsReload()Reload all UI component definitions for this extension
openUrl(url, target?)Open URL in external browser, new window, or modal overlay
openPath(path)Open file or directory in system's default application

TaskContext

Safe subset of Task capabilities exposed to extensions.

interface TaskContext {
readonly data: TaskData;

// Context Files
getContextFiles(): Promise<ContextFile[]>;
addFile(path: string, readOnly?: boolean): Promise<void>;
addFiles(...files: ContextFile[]): Promise<void>;
dropFile(path: string): Promise<void>;
getAddableFiles(searchRegex?: string): Promise<string[]>;
getAllFiles(useGit?: boolean): Promise<string[]>;
getUpdatedFiles(): Promise<UpdatedFile[]>;

// Context Messages
getContextMessages(): Promise<ContextMessage[]>;
addContextMessage(message: ContextMessage, updateContextInfo?: boolean): Promise<void>;
removeMessage(messageId: string): Promise<void>;
removeLastMessage(): Promise<void>;
removeMessagesUpTo(messageId: string): Promise<void>;
loadContextMessages(messages: ContextMessage[]): Promise<void>;

// Message Helpers
addUserMessage(id: string, content: string, promptContext?: PromptContext): void;
addToolMessage(id: string, serverName: string, toolName: string, input?: unknown, response?: string, usageReport?: UsageReportData, promptContext?: PromptContext, saveToDb?: boolean, finished?: boolean): void;
addResponseMessage(message: ResponseMessage, saveToDb?: boolean): Promise<void>;

// Execution
runPrompt(prompt: string, mode?: string): Promise<void>;
runCustomCommand(name: string, args?: string[], mode?: string): Promise<void>;
runSubagent(agentProfile: AgentProfile, prompt: string): Promise<void>;
runCommand(command: string): Promise<void>;
interruptResponse(): Promise<void>;
generateText(modelId: string, systemPrompt: string, prompt: string): Promise<string | undefined>;

// User Interaction
askQuestion(text: string, options?: QuestionOptions): Promise<string>;
addLogMessage(level: 'info' | 'error' | 'warning', message?: string): void;
addLoadingMessage(message?: string, finished?: boolean): void;

// Todos
getTodos(): Promise<TodoItem[]>;
addTodo(name: string): Promise<TodoItem[]>;
updateTodo(name: string, updates: Partial<TodoItem>): Promise<TodoItem[]>;
deleteTodo(name: string): Promise<TodoItem[]>;
clearAllTodos(): Promise<TodoItem[]>;
setTodos(items: TodoItem[], initialUserPrompt?: string): Promise<void>;

// Task Management
updateTask(updates: Partial<TaskData>): Promise<TaskData>;
getTaskDir(): string;
getTaskAgentProfile(): Promise<AgentProfile | null>;
isInitialized(): boolean;

// Context Operations
getRepoMap(): string;
generateContextMarkdown(): Promise<string | null>;
clearContext(): Promise<void>;
resetContext(): Promise<void>;
compactConversation(instructions?: string): Promise<void>;
handoffConversation(focus?: string, execute?: boolean): Promise<void>;
updateAutocompletionWords(words?: string[]): Promise<void>;

// Git
addToGit(path: string): Promise<void>;

// Questions
answerQuestion(answer: string, userInput?: string): Promise<boolean>;

// Queued Prompts
getQueuedPrompts(): QueuedPromptData[];
sendQueuedPromptNow(promptId: string): Promise<void>;
removeQueuedPrompt(promptId: string): void;

// Redo
redoLastUserPrompt(mode?: string, updatedPrompt?: string): Promise<void>;
}

ProjectContext

Safe subset of Project capabilities exposed to extensions.

interface ProjectContext {
readonly baseDir: string;

// Task Management
createTask(params: CreateTaskParams): Promise<TaskData>;
getTask(taskId: string): TaskContext | null;
getTasks(): Promise<TaskData[]>;
getMostRecentTask(): TaskContext | null;
forkTask(taskId: string, messageId: string): Promise<TaskData>;
duplicateTask(taskId: string): Promise<TaskData>;
deleteTask(taskId: string): Promise<void>;

// Configuration
getAgentProfiles(): AgentProfile[];
getCommands(): CommandsData;
getProjectSettings(): ProjectSettings;

// History
getInputHistory(): Promise<string[]>;
}

ToolDefinition

Define custom tools that the AI can use.

interface ToolDefinition<TSchema extends z.ZodType = z.ZodType<Record<string, unknown>>> {
name: string; // Tool identifier in kebab-case
description: string; // Description for the LLM
inputSchema: TSchema; // Zod schema for parameter validation
execute: ( // Execute function
input: z.infer<TSchema>,
signal: AbortSignal | undefined,
context: ExtensionContext
) => Promise<unknown>;
}

Example

const myTool: ToolDefinition = {
name: 'run-linter',
description: 'Run the project linter',
inputSchema: z.object({
fix: z.boolean().optional().describe('Auto-fix issues'),
files: z.array(z.string()).optional().describe('Files to lint'),
}),
async execute(input, signal, context) {
// Your implementation
return { results: '...' };
},
};

CommandDefinition

Define custom slash commands.

interface CommandDefinition {
name: string; // Command name in kebab-case
description: string; // Description shown in autocomplete
arguments?: CommandArgument[]; // Optional command arguments
execute: (args: string[], context: ExtensionContext) => Promise<void>;
}

interface CommandArgument {
description: string;
required?: boolean;
options?: string[];
}

Example

const myCommand: CommandDefinition = {
name: 'generate-tests',
description: 'Generate unit tests for a file',
arguments: [
{ description: 'File path', required: true },
{ description: 'Framework (jest, vitest)', required: false },
],
async execute(args, context) {
const filePath = args[0];
const framework = args[1] || 'vitest';
// Your implementation
},
};

ModeDefinition

Define custom chat modes.

interface ModeDefinition {
name: Mode; // Mode identifier
label: string; // Display name
description?: string; // Optional description
icon?: string; // Optional icon from react-icons (e.g., 'FiCode')
}

Example

const planMode: ModeDefinition = {
name: 'plan',
label: 'Plan',
description: 'Plan before coding - no file modifications',
icon: 'FiClipboard',
};

UIComponentDefinition

Define custom React components that render in AiderDesk's UI.

Important: The jsx property must be a string containing the component code, not a function. The React object is globally available within components (not passed as a prop).

interface UIComponentDefinition {
id: string; // Unique component identifier
placement: UIComponentPlacement; // Where to render the component
jsx: string; // JSX/TSX component as string
loadData?: boolean; // Enable data loading via getUIExtensionData (default: false)
noDataCache?: boolean; // Always fetch fresh data on render (default: false)
}

Example

const myComponent: UIComponentDefinition = {
id: 'my-status-indicator',
placement: 'task-status-bar-right',
loadData: true,
jsx: `
(props) => {
const { ui, data, task } = props;
const { useState } = React;
const { Tooltip } = ui;

const [isHovered, setIsHovered] = useState(false);

return (
<Tooltip content="Task status">
<div
className="flex items-center gap-1 text-xs"
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<span className="w-2 h-2 rounded-full bg-success" />
<span>{task?.name || 'No task'}</span>
</div>
</Tooltip>
);
}
`,
};

Properties

PropertyTypeRequiredDescription
idstringYesUnique identifier for the component
placementUIComponentPlacementYesWhere to render the component (see placements below)
jsxstringYesJSX/TSX component code as a string
loadDatabooleanNoEnable data loading via getUIExtensionData()
noDataCachebooleanNoDisable caching - always fetch fresh data

UIComponentPlacement

Available placement locations for UI components (21 total).

type UIComponentPlacement =
// Task Status Bar
| 'task-status-bar-left' // Left side of task status bar (top of task page)
| 'task-status-bar-right' // Right side of task status bar

// Task Top Bar
| 'task-top-bar-left' // Left side of task top bar (above messages)
| 'task-top-bar-right' // Right side of task top bar

// Task Messages
| 'task-messages-top' // Above all messages
| 'task-messages-bottom' // Below all messages
| 'task-message-above' // Above each message (receives message prop)
| 'task-message-below' // Below each message (receives message prop)
| 'task-message-bar' // In message action bar (receives message prop)

// Task Usage Info
| 'task-usage-info-bottom' // Below usage info (tokens, costs)

// Task Input
| 'task-input-above' // Above input field
| 'task-input-toolbar-left' // Left side of input toolbar
| 'task-input-toolbar-right' // Right side of input toolbar

// Task State Actions
| 'task-state-actions' // Action buttons (when stopped/waiting)
| 'task-state-actions-all' // Action buttons (all states)

// Sidebar
| 'tasks-sidebar-header' // Header of tasks sidebar
| 'tasks-sidebar-bottom' // Bottom of tasks sidebar

// Header
| 'header-left' // Left side of main header
| 'header-right' // Right side of main header

// Welcome Page
| 'welcome-page' // Full welcome page (no task open)
| 'tasks-sidebar-header'
| 'tasks-sidebar-bottom'
| 'task-message-above'
| 'task-message-below'
| 'task-message-bar'
| 'task-top-bar-left'
| 'task-top-bar-right'
| 'task-state-actions';

UI Component Props

Important: The React object is globally available in all UI components (not passed as a prop). Access hooks via React.useState, React.useEffect, etc.

Props passed to UI component functions:

interface UIComponentProps {
// Context data
projectDir?: string; // Project directory path
task?: TaskData; // Current task data
agentProfile?: AgentProfile; // Current agent profile
models: Model[]; // Available AI models
providers: ProviderProfile[]; // Available provider profiles

// UI library
ui: UIComponents; // Pre-built UI components

// Icons library (organized by icon set)
icons: Record<string, Record<string, IconComponent>>;

// Extension integration
executeExtensionAction: (action: string, ...args: unknown[]) => Promise<unknown>;

// Data from getUIExtensionData() (if loadData: true)
data?: unknown;

// Message-specific (for message placements)
message?: MessageData;
}

Using React Hooks

(props) => {
const { useState, useEffect, useCallback } = React;
const [count, setCount] = useState(0);

const handleClick = useCallback(() => {
setCount(count + 1);
}, [count]);

return <button onClick={handleClick}>Count: {count}</button>;
}

Using Icons

The icons prop provides access to all react-icons libraries:

(props) => {
const { icons } = props;
const FiSettings = icons.Fi.FiSettings;
const HiCheck = icons.Hi.HiCheck;

return (
<div>
<FiSettings className="w-4 h-4" />
<HiCheck className="w-5 h-5 text-success" />
</div>
);
}

Available icon sets: Ai, Bi, Bs, Cg, Ci, Di, Fa, Fc, Fi, Gi, Go, Gr, Hi, Im, Io, Io5, Lu, Md, Pi, Ri, Rx, Si, Sl, Tb, Tfi, Ti, Vsc, Wi

UIComponents

Pre-built UI components available via props.ui:

interface UIComponents {
Button: UIComponent; // Standard button with variants
IconButton: UIComponent; // Button with icon only
Checkbox: UIComponent; // Checkbox input with label
Input: UIComponent; // Text input field
Select: UIComponent; // Dropdown select
MultiSelect: UIComponent; // Multi-value select
TextArea: UIComponent; // Multi-line text input
RadioButton: UIComponent; // Radio button input
Slider: UIComponent; // Range slider
DatePicker: UIComponent; // Date picker
Chip: UIComponent; // Tag/chip component
ModelSelector: UIComponent; // AiderDesk model selector
Tooltip: UIComponent; // Tooltip wrapper
LoadingOverlay: UIComponent; // Loading spinner with message
ConfirmDialog: UIComponent; // Confirmation dialog modal
}

ExtensionMetadata

Metadata describing an extension.

interface ExtensionMetadata {
name: string; // Display name
version: string; // Semantic version (e.g., "1.0.0")
description?: string; // Brief description
author?: string; // Author name or organization
capabilities?: string[]; // Optional capabilities list
}

ToolResult

Result returned by tool execution.

interface ToolResult {
content: Array<
| { type: 'text'; text: string }
| { type: 'image'; source: unknown }
>;
details?: Record<string, unknown>;
isError?: boolean;
}

MemoryContext

Provides access to AiderDesk's memory system — the same underlying vector store used by the built-in memory MCP tools. Available via context.getMemoryContext() in any extension lifecycle hook or method.

interface MemoryContext {
storeMemory(projectId: string, taskId: string, type: MemoryEntryType, content: string): Promise<string>;
retrieveMemories(projectId: string, query: string, limit?: number): Promise<MemoryEntry[]>;
getMemory(id: string): Promise<MemoryEntry | null>;
deleteMemory(id: string): Promise<boolean>;
updateMemory(id: string, content: string): Promise<boolean>;
getAllMemories(): Promise<MemoryEntry[]>;
isMemoryEnabled(): boolean;
setMemoryEnabled(enabled: boolean): void;
}

Methods

MethodReturnsDescription
storeMemory(projectId, taskId, type, content)Promise<string>Store a new memory entry. Returns the created memory ID.
retrieveMemories(projectId, query, limit?)Promise<MemoryEntry[]>Retrieve memories by semantic similarity, ranked by relevance.
getMemory(id)Promise<MemoryEntry | null>Get a single memory by ID.
deleteMemory(id)Promise<boolean>Delete a specific memory by ID. Returns true if successful.
updateMemory(id, content)Promise<boolean>Update the content of an existing memory. Returns true if successful.
getAllMemories()Promise<MemoryEntry[]>Get all stored memories.
isMemoryEnabled()booleanCheck if the memory system is enabled and initialized.
setMemoryEnabled(enabled)voidEnable or disable the memory system. Persists the setting.

MemoryEntryType

Memory entries are categorized by type:

enum MemoryEntryType {
Task = 'task', // Task-specific outcomes and observations
UserPreference = 'user-preference', // Durable user preferences and conventions
CodePattern = 'code-pattern', // Reusable codebase patterns and practices
}

MemoryEntry

interface MemoryEntry {
id: string; // Unique memory identifier
content: string; // Memory content text
type: MemoryEntryType; // Category of memory
taskId?: string; // Associated task ID (if applicable)
projectId?: string; // Associated project directory path
timestamp: number; // Creation timestamp
}

Example

import type { Extension, ExtensionContext, AgentFinishedEvent } from '@aiderdesk/extensions';

export default class MemoryExtension implements Extension {
async onAgentFinished(event: AgentFinishedEvent, context: ExtensionContext) {
const memory = context.getMemoryContext();
if (!memory.isMemoryEnabled()) return;

const projectId = context.getProjectDir();
const taskId = context.getTaskContext()?.data.id ?? '';

// Store a code pattern discovered during the task
await memory.storeMemory(
projectId,
taskId,
'code-pattern',
'Always use clsx for conditional class names in React components',
);

// Retrieve relevant memories
const memories = await memory.retrieveMemories(projectId, 'React class naming conventions');
context.log(`Found ${memories.length} relevant memories`, 'info');
}
}