@aiderdesk/aiderdesk 0.61.0 → 0.61.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (22) hide show
  1. package/out/resources/skills/extension-creator/SKILL.md +320 -0
  2. package/out/resources/skills/extension-creator/assets/templates/Component.jsx.template +76 -0
  3. package/out/resources/skills/extension-creator/assets/templates/ConfigComponent.jsx.template +38 -0
  4. package/out/resources/skills/extension-creator/assets/templates/folder-extension/config.ts.template +29 -0
  5. package/out/resources/skills/extension-creator/assets/templates/folder-extension/index.ts.template +42 -0
  6. package/out/resources/skills/extension-creator/assets/templates/folder-extension/package.json +12 -0
  7. package/out/resources/skills/extension-creator/assets/templates/folder-extension/tsconfig.json +23 -0
  8. package/out/resources/skills/extension-creator/assets/templates/folder-extension-with-config/index.ts.template +80 -0
  9. package/out/resources/skills/extension-creator/assets/templates/single-file.ts.template +30 -0
  10. package/out/resources/skills/extension-creator/assets/templates/ui-component-external.ts.template +91 -0
  11. package/out/resources/skills/extension-creator/assets/templates/ui-component.ts.template +79 -0
  12. package/out/resources/skills/extension-creator/references/command-definition.md +170 -0
  13. package/out/resources/skills/extension-creator/references/config-components.md +427 -0
  14. package/out/resources/skills/extension-creator/references/event-types.md +156 -0
  15. package/out/resources/skills/extension-creator/references/examples-gallery.md +583 -0
  16. package/out/resources/skills/extension-creator/references/extension-interface.md +240 -0
  17. package/out/resources/skills/extension-creator/references/extension-types.md +186 -0
  18. package/out/resources/skills/extension-creator/references/in-repo-flow.md +132 -0
  19. package/out/resources/skills/extension-creator/references/install-targets.md +96 -0
  20. package/out/resources/skills/extension-creator/references/project-global-flow.md +76 -0
  21. package/out/resources/skills/extension-creator/references/ui-components.md +663 -0
  22. package/package.json +1 -1
@@ -0,0 +1,240 @@
1
+ # Extension Interface
2
+
3
+ Full TypeScript interface for AiderDesk extensions.
4
+
5
+ ## Extension Interface
6
+
7
+ ```typescript
8
+ interface Extension {
9
+ // Lifecycle
10
+ onLoad?(context: ExtensionContext): Promise<void> | void;
11
+ onUnload?(context: ExtensionContext): Promise<void> | void;
12
+
13
+ // Registration
14
+ getCommands?(context: ExtensionContext): CommandDefinition[];
15
+ getTools?(context: ExtensionContext, mode: string, agentProfile: AgentProfile): ToolDefinition[];
16
+ getAgents?(context: ExtensionContext): AgentProfile[];
17
+ getModes?(context: ExtensionContext): ModeDefinition[];
18
+ getUIComponents?(context: ExtensionContext): UIComponentDefinition[];
19
+
20
+ // UI Component support
21
+ getUIExtensionData?(componentId: string, context: ExtensionContext): Promise<unknown>;
22
+ executeUIExtensionAction?(componentId: string, action: string, args: unknown[], context: ExtensionContext): Promise<unknown>;
23
+
24
+ // Settings configuration (per-extension settings UI)
25
+ getConfigComponent?(context: ExtensionContext): string | undefined;
26
+ getConfigData?(context: ExtensionContext): Promise<unknown>;
27
+ saveConfigData?(configData: unknown, context: ExtensionContext): Promise<unknown>;
28
+
29
+ // Task Events
30
+ onTaskCreated?(event: TaskCreatedEvent, context: ExtensionContext): Promise<void | Partial<TaskCreatedEvent>>;
31
+ onTaskInitialized?(event: TaskInitializedEvent, context: ExtensionContext): Promise<void>;
32
+ onTaskClosed?(event: TaskClosedEvent, context: ExtensionContext): Promise<void>;
33
+
34
+ // Agent Events
35
+ onAgentStarted?(event: AgentStartedEvent, context: ExtensionContext): Promise<void | Partial<AgentStartedEvent>>;
36
+ onAgentFinished?(event: AgentFinishedEvent, context: ExtensionContext): Promise<void | Partial<AgentFinishedEvent>>;
37
+ onAgentStepFinished?(event: AgentStepFinishedEvent, context: ExtensionContext): Promise<void | Partial<AgentStepFinishedEvent>>;
38
+ onAgentProfileUpdated?(context: ExtensionContext, agentId: string, updatedProfile: AgentProfile): Promise<AgentProfile>;
39
+
40
+ // Tool Events
41
+ onToolApproval?(event: ToolApprovalEvent, context: ExtensionContext): Promise<void | Partial<ToolApprovalEvent>>;
42
+ onToolCalled?(event: ToolCalledEvent, context: ExtensionContext): Promise<void | Partial<ToolCalledEvent>>;
43
+ onToolFinished?(event: ToolFinishedEvent, context: ExtensionContext): Promise<void | Partial<ToolFinishedEvent>>;
44
+
45
+ // File Events
46
+ onFileAdded?(event: FileAddedEvent, context: ExtensionContext): Promise<void>;
47
+ onFileDropped?(event: FileDroppedEvent, context: ExtensionContext): Promise<void>;
48
+
49
+ // Prompt Events
50
+ onPromptSubmitted?(event: PromptSubmittedEvent, context: ExtensionContext): Promise<void | Partial<PromptSubmittedEvent>>;
51
+ onPromptStarted?(event: PromptStartedEvent, context: ExtensionContext): Promise<void>;
52
+ onPromptFinished?(event: PromptFinishedEvent, context: ExtensionContext): Promise<void>;
53
+
54
+ // Message Events
55
+ onResponseMessageProcessed?(event: ResponseMessageProcessedEvent, context: ExtensionContext): Promise<void | Partial<ResponseMessageProcessedEvent>>;
56
+
57
+ // Other Events
58
+ onProjectOpen?(context: ExtensionContext): Promise<void>;
59
+ onRuleFilesRetrieved?(context: ExtensionContext, ruleFiles: string[]): Promise<string[]>;
60
+ onSubagentStarted?(event: SubagentStartedEvent, context: ExtensionContext): Promise<void | Partial<SubagentStartedEvent>>;
61
+ onSubagentFinished?(event: SubagentFinishedEvent, context: ExtensionContext): Promise<void>;
62
+ onQuestionAsked?(event: QuestionAskedEvent, context: ExtensionContext): Promise<void>;
63
+ onQuestionAnswered?(event: QuestionAnsweredEvent, context: ExtensionContext): Promise<void>;
64
+ onCommandExecuted?(event: CommandExecutedEvent, context: ExtensionContext): Promise<void>;
65
+ }
66
+ ```
67
+
68
+ ## ExtensionContext
69
+
70
+ ```typescript
71
+ interface ExtensionContext {
72
+ // Logging (backend/dev console only — NOT visible to users in chat UI)
73
+ log(message: string, type: 'info' | 'error' | 'warn' | 'debug'): void;
74
+
75
+ // Project access
76
+ getProjectDir(): string;
77
+ getTaskContext(): TaskContext | null;
78
+ getProjectContext(): ProjectContext;
79
+
80
+ // Settings
81
+ getSetting(key: string): Promise<unknown>;
82
+ updateSettings(updates: Record<string, unknown>): Promise<void>;
83
+
84
+ // Models
85
+ getModelConfigs(): Promise<Model[]>;
86
+
87
+ // UI updates
88
+ triggerUIDataRefresh(componentId?: string, taskId?: string): void;
89
+ triggerUIComponentsReload(): void;
90
+
91
+ // Navigation
92
+ openUrl(url: string, target?: 'external' | 'window' | 'modal-overlay'): Promise<void>;
93
+ openPath(path: string): Promise<boolean>;
94
+ }
95
+ ```
96
+
97
+ ## TaskContext
98
+
99
+ ```typescript
100
+ interface TaskContext {
101
+ // Logging to chat (visible to users in the task's chat UI)
102
+ addLogMessage(level: 'info' | 'error' | 'warning', message?: string): void;
103
+ addLoadingMessage(message?: string, finished?: boolean): void;
104
+
105
+ // Task operations
106
+ updateTask(updates: Partial<TaskData>): Promise<TaskData>;
107
+ runPrompt(prompt: string, mode?: string): Promise<void>;
108
+ runCustomCommand(name: string, args?: string[], mode?: string): Promise<void>;
109
+ runSubagent(agentProfile: AgentProfile, prompt: string): Promise<void>;
110
+ interruptResponse(): Promise<void>;
111
+
112
+ // File operations
113
+ getRepoMap(): string;
114
+ getContextFiles(): ContextFile[];
115
+ addContextFiles(files: ContextFile[]): Promise<void>;
116
+
117
+ // Questions
118
+ askQuestion(text: string, options?: QuestionOptions): Promise<string>;
119
+ }
120
+ ```
121
+
122
+ ## UIComponentDefinition
123
+
124
+ ```typescript
125
+ interface UIComponentDefinition {
126
+ /** Unique component identifier */
127
+ id: string;
128
+
129
+ /** Where in UI to render this component */
130
+ placement: UIComponentPlacement;
131
+
132
+ /** JSX/TSX component as string to be parsed */
133
+ jsx: string;
134
+
135
+ /** Optional flag to load data from extension (default: false) */
136
+ loadData?: boolean;
137
+
138
+ /** Optional flag to disable data caching (default: false) */
139
+ noDataCache?: boolean;
140
+ }
141
+
142
+ type UIComponentPlacement =
143
+ | 'task-status-bar-left'
144
+ | 'task-status-bar-right'
145
+ | 'task-usage-info-bottom'
146
+ | 'task-messages-top'
147
+ | 'task-messages-bottom'
148
+ | 'task-input-above'
149
+ | 'task-input-toolbar-left'
150
+ | 'task-input-toolbar-right'
151
+ | 'tasks-sidebar-header'
152
+ | 'tasks-sidebar-bottom'
153
+ | 'task-message-above'
154
+ | 'task-message-below'
155
+ | 'task-message-bar'
156
+ | 'task-top-bar-left'
157
+ | 'task-top-bar-right'
158
+ | 'task-state-actions'
159
+ | 'task-state-actions-all'
160
+ | 'header-left'
161
+ | 'header-right'
162
+ | 'welcome-page';
163
+ ```
164
+
165
+ ## UIComponentProps
166
+
167
+ Props available to UI components via the `data` prop (React is globally available, not a prop):
168
+
169
+ ```typescript
170
+ interface UIComponentProps {
171
+ // Context data
172
+ projectDir?: string;
173
+ task?: TaskData;
174
+ agentProfile?: AgentProfile;
175
+ models: Model[];
176
+ providers: ProviderProfile[];
177
+
178
+ // UI library
179
+ ui: UIComponents;
180
+
181
+ // Icons library (organized by icon set)
182
+ icons: Record<string, Record<string, IconComponent>>;
183
+
184
+ // Extension actions
185
+ executeExtensionAction: (action: string, ...args: unknown[]) => Promise<unknown>;
186
+
187
+ // Data from getUIExtensionData() (if loadData: true)
188
+ data?: unknown;
189
+
190
+ // Message-specific (for message placements)
191
+ message?: MessageData;
192
+ }
193
+
194
+ interface UIComponents {
195
+ Button: Component;
196
+ Checkbox: Component;
197
+ Input: Component;
198
+ Select: Component;
199
+ TextArea: Component;
200
+ IconButton: Component;
201
+ RadioButton: Component;
202
+ MultiSelect: Component;
203
+ Slider: Component;
204
+ DatePicker: Component;
205
+ Chip: Component;
206
+ ModelSelector: Component;
207
+ Tooltip: Component;
208
+ LoadingOverlay: Component;
209
+ ConfirmDialog: Component;
210
+ }
211
+ ```
212
+
213
+ ## Metadata
214
+
215
+ Metadata is defined as a **static property** on the extension class:
216
+
217
+ ```typescript
218
+ export default class MyExtension implements Extension {
219
+ static metadata = {
220
+ name: 'My Extension',
221
+ version: '1.0.0',
222
+ description: 'What this extension does',
223
+ author: 'Author Name',
224
+ capabilities: ['events', 'commands'],
225
+ };
226
+ }
227
+ ```
228
+
229
+ **Important:** Metadata must be a `static` property on the class. Do NOT use a separate `export const metadata = { ... }` — the extension loader reads it from `ExtensionClass.metadata`.
230
+
231
+ ```typescript
232
+ interface ExtensionMetadata {
233
+ name: string;
234
+ version: string;
235
+ description?: string;
236
+ author?: string;
237
+ capabilities?: string[];
238
+ iconUrl?: string;
239
+ }
240
+ ```
@@ -0,0 +1,186 @@
1
+ # Extension Types
2
+
3
+ AiderDesk supports two types of extensions: single-file and folder extensions.
4
+
5
+ ## Single-File Extensions
6
+
7
+ **When to use:** Simple extensions with no npm dependencies
8
+
9
+ **Location:** `packages/extensions/extensions/my-extension.ts`
10
+
11
+ **Structure:**
12
+ ```typescript
13
+ import type { Extension, ExtensionContext } from '@aiderdesk/extensions';
14
+
15
+ export default class MyExtension implements Extension {
16
+ static metadata = {
17
+ name: 'My Extension',
18
+ version: '1.0.0',
19
+ description: 'What this extension does',
20
+ author: 'Author Name',
21
+ capabilities: ['events', 'commands'],
22
+ };
23
+
24
+ async onLoad(context: ExtensionContext): Promise<void> {
25
+ context.log('Extension loaded', 'info');
26
+ }
27
+ }
28
+ ```
29
+
30
+ **Advantages:**
31
+ - Simple structure
32
+ - Easy to maintain
33
+ - No build step required
34
+
35
+ **Limitations:**
36
+ - Cannot use npm dependencies
37
+ - All code in one file
38
+ - No separate config or logger files
39
+
40
+ ## Folder Extensions
41
+
42
+ **When to use:** Complex extensions with npm dependencies or multiple files
43
+
44
+ **Location:** `packages/extensions/extensions/my-extension/`
45
+
46
+ **Structure:**
47
+ ```
48
+ packages/extensions/extensions/my-extension/
49
+ ├── index.ts # Main extension file (implements Extension)
50
+ ├── package.json # npm dependencies
51
+ ├── tsconfig.json # TypeScript config (module: ES2020+)
52
+ ├── README.md # Documentation
53
+ ├── config.ts # Optional: persistent config storage
54
+ ├── logger.ts # Optional: local logger
55
+ ├── constants.ts # Optional: extension constants
56
+ └── resources/ # Optional: WASM, queries, assets
57
+ ```
58
+
59
+ **package.json:**
60
+ ```json
61
+ {
62
+ "name": "my-extension",
63
+ "version": "1.0.0",
64
+ "main": "index.ts",
65
+ "dependencies": {
66
+ // Required packages
67
+ }
68
+ }
69
+ ```
70
+
71
+ **tsconfig.json:**
72
+ ```json
73
+ {
74
+ "compilerOptions": {
75
+ "target": "ES2020",
76
+ "module": "ES2020",
77
+ "moduleResolution": "node",
78
+ "esModuleInterop": true,
79
+ "strict": true
80
+ }
81
+ }
82
+ ```
83
+
84
+ **Advantages:**
85
+ - Can use npm dependencies
86
+ - Modular structure
87
+ - Separate config and logger files
88
+ - Can include resources (WASM, queries, assets)
89
+
90
+ **Requirements:**
91
+ - Must have package.json
92
+ - Must have tsconfig.json with ES2020+ module
93
+ - Must set `hasDependencies: true` in extensions.json
94
+
95
+ ## Choosing Extension Type
96
+
97
+ **When:** Extension needs npm packages
98
+
99
+ **Then:** Use folder extension
100
+
101
+ **When:** Extension is simple with no dependencies
102
+
103
+ **Then:** Use single-file extension
104
+
105
+ **When:** Extension needs multiple files
106
+
107
+ **Then:** Use folder extension
108
+
109
+ **When:** Extension needs resources (WASM, queries)
110
+
111
+ **Then:** Use folder extension
112
+
113
+ ## Common Patterns by Type
114
+
115
+ ### Single-File: Simple Event Handler
116
+
117
+ ```typescript
118
+ import type { Extension, ExtensionContext, AgentStartedEvent } from '@aiderdesk/extensions';
119
+
120
+ export default class SimpleExtension implements Extension {
121
+ static metadata = {
122
+ name: 'Simple Extension',
123
+ version: '1.0.0',
124
+ description: 'Simple event handler',
125
+ author: 'Author Name',
126
+ capabilities: ['events'],
127
+ };
128
+
129
+ async onLoad(context: ExtensionContext): Promise<void> {
130
+ context.log('Simple extension loaded', 'info');
131
+ }
132
+
133
+ async onAgentStarted(
134
+ event: AgentStartedEvent,
135
+ context: ExtensionContext
136
+ ): Promise<void | Partial<AgentStartedEvent>> {
137
+ context.log('Agent started', 'info');
138
+ return { contextMessages: [...event.contextMessages] };
139
+ }
140
+ }
141
+ ```
142
+
143
+ ### Folder: Extension with Config and Dependencies
144
+
145
+ ```
146
+ tree-sitter-repo-map/
147
+ ├── index.ts # Main extension with getTools()
148
+ ├── package.json # tree-sitter dependencies
149
+ ├── tsconfig.json # ES2020 module
150
+ ├── config.ts # Config storage
151
+ ├── logger.ts # Extension logger
152
+ ├── constants.ts # Extension constants
153
+ └── resources/
154
+ └── queries/ # Language queries
155
+ ```
156
+
157
+ ## Updating extensions.json
158
+
159
+ ### Single-File Entry
160
+
161
+ ```json
162
+ {
163
+ "id": "my-extension",
164
+ "name": "My Extension",
165
+ "description": "Description of what it does",
166
+ "file": "extensions/my-extension.ts",
167
+ "type": "single",
168
+ "capabilities": ["onLoad", "onAgentStarted"]
169
+ }
170
+ ```
171
+
172
+ ### Folder Entry
173
+
174
+ ```json
175
+ {
176
+ "id": "my-extension",
177
+ "name": "My Extension",
178
+ "description": "Description",
179
+ "folder": "extensions/my-extension",
180
+ "type": "folder",
181
+ "hasDependencies": true,
182
+ "capabilities": ["onLoad", "getCommands", "onAgentStarted"]
183
+ }
184
+ ```
185
+
186
+ **Note:** Always set `hasDependencies: true` for folder extensions, even if they don't have dependencies yet. This ensures proper loading.
@@ -0,0 +1,132 @@
1
+ # In-Repo Installation Flow
2
+
3
+ This flow covers developing extensions **inside the AiderDesk codebase** at `packages/extensions/extensions/`. These extensions ship with the application and are available to all users by default.
4
+
5
+ ## When to Use This Flow
6
+
7
+ Only when:
8
+ 1. The current working project **is** the AiderDesk repository itself
9
+ 2. The user explicitly chooses "In-Repo" as the installation target
10
+ 3. The extension is meant to be a built-in feature, not a personal or project-specific tool
11
+
12
+ ## Process
13
+
14
+ 1. **Determine extension type** — single-file or folder
15
+ 2. **Create extension file(s)** in `packages/extensions/extensions/`
16
+ 3. **Implement Extension interface methods**
17
+ 4. **Export metadata and default class**
18
+ 5. **Update `packages/extensions/extensions.json`** — register the extension
19
+ 6. **Update `docs-site/docs/extensions/examples.md`** — document it
20
+ 7. **Verify with type checking and code-checker**
21
+
22
+ ## Directory Structure
23
+
24
+ ### Single-File In-Repo Extension
25
+
26
+ ```
27
+ packages/extensions/extensions/
28
+ └── my-extension.ts # Everything in one file
29
+ ```
30
+
31
+ ### Folder In-Repo Extension
32
+
33
+ ```
34
+ packages/extensions/extensions/
35
+ └── my-extension/
36
+ ├── index.ts # Main extension file
37
+ ├── package.json # npm dependencies (must run npm install)
38
+ ├── tsconfig.json # TypeScript config (module: ES2020+)
39
+ ├── README.md # Documentation
40
+ ├── config.ts # Optional: persistent config storage
41
+ ├── logger.ts # Optional: local logger
42
+ ├── constants.ts # Optional: extension constants
43
+ └── resources/ # Optional: WASM, queries, assets
44
+ ```
45
+
46
+ ## Step-by-Step
47
+
48
+ ### Step 1: Determine type
49
+
50
+ - **Single-file**: No npm dependencies, simple logic
51
+ - **Folder**: Needs npm packages, multiple files, resources
52
+
53
+ ### Step 2: Create the extension
54
+
55
+ Use the templates:
56
+ - [single-file.ts.template](../assets/templates/single-file.ts.template)
57
+ - [folder-extension/](../assets/templates/folder-extension/)
58
+ - [folder-extension-with-config/index.ts.template](../assets/templates/folder-extension-with-config/index.ts.template)
59
+
60
+ Create files in `packages/extensions/extensions/{name}/` or `packages/extensions/extensions/{name}.ts`.
61
+
62
+ ### Step 3: Implement interface
63
+
64
+ Same as any extension — implement required methods, export metadata and class.
65
+
66
+ Reference: [extension-interface.md](extension-interface.md)
67
+
68
+ ### Step 4: Register in extensions.json
69
+
70
+ **This step is unique to In-Repo extensions.**
71
+
72
+ Add an entry to `packages/extensions/extensions.json`:
73
+
74
+ **Single-file entry:**
75
+ ```json
76
+ {
77
+ "id": "my-extension",
78
+ "name": "My Extension",
79
+ "description": "Description of what it does",
80
+ "file": "extensions/my-extension.ts",
81
+ "type": "single",
82
+ "capabilities": ["onLoad", "onAgentStarted"]
83
+ }
84
+ ```
85
+
86
+ **Folder entry:**
87
+ ```json
88
+ {
89
+ "id": "my-extension",
90
+ "name": "My Extension",
91
+ "description": "Description",
92
+ "folder": "extensions/my-extension",
93
+ "type": "folder",
94
+ "hasDependencies": true,
95
+ "capabilities": ["onLoad", "getCommands", "onAgentStarted"]
96
+ }
97
+ ```
98
+
99
+ **Important:** Always set `hasDependencies: true` for folder extensions, even if they don't have dependencies yet.
100
+
101
+ ### Step 5: Document in examples.md
102
+
103
+ Add an entry to the table in `docs-site/docs/extensions/examples.md`:
104
+
105
+ | Extension | Description | Capabilities | Type |
106
+ |-----------|-------------|-------------|------|
107
+ | My Extension | What it does | events, commands | folder |
108
+
109
+ Include extension name, description, capabilities, and type.
110
+
111
+ ### Step 6: Install dependencies (folder extensions only)
112
+
113
+ If this is a folder extension with npm dependencies:
114
+
115
+ ```bash
116
+ cd packages/extensions
117
+ npm install
118
+ ```
119
+
120
+ ### Step 7: Verify
121
+
122
+ - Run type checking: `npm run typecheck`
123
+ - Run tests if applicable: `npm run test`
124
+ - Verify extension loads without errors
125
+ - Check that extension appears in extensions list
126
+
127
+ ## What NOT to do (In-Repo)
128
+
129
+ - Do NOT use `@/` imports in extension files — use relative imports or `@aiderdesk/extensions` package imports only
130
+ - Do NOT forget to update `extensions.json` — the extension won't load without registration
131
+ - Do NOT forget to update `examples.md` — users won't know about the extension
132
+ - Do NOT place files outside `packages/extensions/extensions/` unless there's a specific reason (e.g., shared utilities should go in `packages/extensions/src/`)
@@ -0,0 +1,96 @@
1
+ # Installation Targets
2
+
3
+ AiderDesk extensions can be installed in three locations, each with different purposes and workflows.
4
+
5
+ ## Target Options
6
+
7
+ ### 1. Current Project (`.aider-desk/extensions/`)
8
+
9
+ **Use when:** The extension is specific to this project and should travel with the codebase.
10
+
11
+ **Location:** `{projectDir}/.aider-desk/extensions/`
12
+
13
+ **Characteristics:**
14
+ - Project-scoped: only available when working in this project
15
+ - Committed to version control alongside the project
16
+ - Shared with team members via git
17
+ - No need to update any registry or manifest files
18
+ - Simple drop-in: just create the file/folder in the directory
19
+
20
+ **Best for:** Project-specific tools, domain-specific rules, team conventions, repo-specific integrations.
21
+
22
+ ---
23
+
24
+ ### 2. Global (`~/.aider-desk/extensions/`)
25
+
26
+ **Use when:** The extension is a personal utility you want available across all projects.
27
+
28
+ **Location:** `~/.aider-desk/extensions/`
29
+
30
+ **Characteristics:**
31
+ - User-scoped: available in every project you work on
32
+ - Not committed to any repository (lives in home directory)
33
+ - Private to your environment
34
+ - No need to update any registry or manifest files
35
+ - Simple drop-in: just create the file/folder in the directory
36
+
37
+ **Best for:** Personal productivity tools, custom commands, cross-project utilities, personal preferences.
38
+
39
+ ---
40
+
41
+ ### 3. In-Repo (`packages/extensions/`) — **Only when working inside the AiderDesk project**
42
+
43
+ **Use when:** You are developing an extension that ships *with* AiderDesk itself, as part of the application.
44
+
45
+ **Location:** `packages/extensions/extensions/{name}/` or `packages/extensions/extensions/{name}.ts`
46
+
47
+ **Characteristics:**
48
+ - Ships with the AiderDesk application as a built-in extension
49
+ - Available to all users by default
50
+ - Requires updating `packages/extensions/extensions.json` (the extension registry)
51
+ - Requires updating documentation in `docs-site/docs/extensions/examples.md`
52
+ - Must follow monorepo conventions (no `@/` imports, proper tsconfig/package.json)
53
+ - Subject to the full AiderDesk development workflow (type checking, testing, etc.)
54
+
55
+ **Best for:** Core features, official integrations, extensions that should be available out-of-the-box.
56
+
57
+ ## How to Choose
58
+
59
+ Ask the user at the start of every extension creation session:
60
+
61
+ > "Where should this extension be installed? **Current project** (project-scoped, shared with team), **Global** (personal, available everywhere), or **In-Repo** (ships with AiderDesk, only available when working in the aider-desk project)?"
62
+
63
+ **Decision tree:**
64
+
65
+ ```
66
+ Is the current project the AiderDesk codebase itself?
67
+ ├── YES → Offer all 3 options (Project, Global, In-Repo)
68
+ │ In-Repo means: packages/extensions/ + update extensions.json + update docs
69
+
70
+ └── NO → Offer only 2 options (Project, Global)
71
+ Project = .aider-desk/extensions/ in current project
72
+ Global = ~/.aider-desk/extensions/
73
+ ```
74
+
75
+ ## Key Differences Summary
76
+
77
+ | Aspect | Project | Global | In-Repo |
78
+ |--------|---------|--------|---------|
79
+ | Location | `.aider-desk/extensions/` | `~/.aider-desk/extensions/` | `packages/extensions/extensions/` |
80
+ | Scope | This project only | All projects | All users (ships with app) |
81
+ | Version controlled | Yes (with project) | No | Yes (with AiderDesk) |
82
+ | Update extensions.json | No | No | **Yes** |
83
+ | Update examples.md docs | No | No | **Yes** |
84
+ | npm install needed | No | No | **Yes** (if folder extension) |
85
+ | Available immediately | Yes | Yes | After build/restart |
86
+
87
+ ## Shared Rules (All Targets)
88
+
89
+ Regardless of target, these rules always apply:
90
+
91
+ - Implement the `Extension` interface correctly
92
+ - Export `metadata` object with name, version, description, author, capabilities
93
+ - Export class as `default`
94
+ - Never use `@/` imports in extension files
95
+ - Store config files inside the extension directory
96
+ - Use proper TypeScript (ES2020+ modules for folder extensions)