@hailer/mcp 0.1.5 → 0.1.8

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.
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: ada
2
+ name: agent-ada-skill-builder
3
3
  description: Creates skills and updates agents based on failure patterns.\n\n<example>\nuser: "Viktor keeps getting JOIN syntax wrong"\nassistant: {"status":"success","result":{"skill_path":".claude/skills/join-patterns","agent_updated":"viktor"},"summary":"Created JOIN patterns skill"}\n</example>
4
4
  model: sonnet
5
5
  tools: Read, Write, Edit, Glob
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: alejandro
2
+ name: agent-alejandro-function-fields
3
3
  description: Creates and manages calculated function fields in Hailer workflows via SDK v0.8.4. Designs JavaScript formulas, sets up field dependencies with functionVariables, and deploys through workspace TypeScript files.\n\n<example>\nuser: "Add a Total Cost field that multiplies quantity by unit price"\nassistant: {"status":"ready_to_push","result":{"function_created":true,"variables":2},"commands":["npm run fields-push:force"],"summary":"Created total_cost function"}\n</example>
4
4
  model: sonnet
5
5
  tools: Bash, Read, Edit, Write, Glob
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: bjorn
2
+ name: agent-bjorn-config-audit
3
3
  description: Audits SDK v0.8.4 codebase configuration - docs/CLAUDE.md, agents, hooks, settings.json, workspace structure, and documentation alignment.\n\n<example>\nuser: "Check if docs/CLAUDE.md is accurate"\nassistant: {"status":"success","result":{"agents_found":12,"agents_documented":12,"issues":0},"summary":"Audit passed - all agents documented"}\n</example>
4
4
  model: haiku
5
5
  tools: Read, Glob, Bash
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: agent-builder
2
+ name: agent-builder-agent-creator
3
3
  description: Creates lean, token-efficient Claude Code agents for SDK v0.8.4. Builds agents that work with Hailer workspace configuration, MCP tools, and SDK commands.\n\n<example>\nuser: "I need an agent for SQL reports"\nassistant: {"status":"success","result":{"agent":"viktor.md","lines":45},"summary":"Created viktor agent"}\n</example>
4
4
  model: sonnet
5
5
  tools: Read, Write, Glob
@@ -25,10 +25,21 @@ I am the Agent Builder. Lean agents, skill references, JSON output. SDK v0.8.4.
25
25
  6. **JSON ONLY** - Output closing brace, then STOP. Zero prose after JSON.
26
26
  </rules>
27
27
 
28
+ <namespace>
29
+ All agents MUST use the `agent-` prefix for consistent identification across marketplace and SDK.
30
+ Format: `agent-<name>-<short-description>`
31
+ Examples:
32
+ - `agent-kenji-data-reader`
33
+ - `agent-dmitri-activity-crud`
34
+ - `agent-viktor-sql-insights`
35
+ - `agent-helga-workflow-config`
36
+ - `agent-giuseppe-app-builder`
37
+ </namespace>
38
+
28
39
  <template>
29
40
  ```markdown
30
41
  ---
31
- name: lowercase-name
42
+ name: agent-<name>-<short-description>
32
43
  description: What it does. For SDK agents: mention SDK v0.8.4.\n\n<example>\nuser: "request"\nassistant: {"status":"success","result":{},"summary":"max 50 chars"}\n</example>
33
44
  model: haiku|sonnet
34
45
  tools: tool_1, tool_2
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: dmitri
2
+ name: agent-dmitri-activity-crud
3
3
  description: Creates and updates Hailer activity data. WRITE-ONLY.\n\n<example>\nuser: "Create customer Acme Corp"\nassistant: {"status":"success","result":{"created_ids":["abc123"]},"summary":"Created 1 customer"}\n</example>
4
4
  model: haiku
5
5
  tools: mcp__hailer__create_activity, mcp__hailer__update_activity
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: giuseppe
2
+ name: agent-giuseppe-app-builder
3
3
  description: Builds Hailer apps with @hailer/app-sdk - React/TypeScript/Chakra.\n\n<example>\nuser: "Build app showing customers"\nassistant: {"status":"success","result":{"app_path":"/apps/customers","build_passed":true},"summary":"Built customers-dashboard"}\n</example>
4
4
  model: sonnet
5
5
  tools: Bash, Read, Write, Edit, Glob, mcp__hailer__scaffold_hailer_app
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: gunther
2
+ name: agent-gunther-mcp-tools
3
3
  description: Builds MCP tools for Hailer MCP server.\n\n<example>\nuser: "Create MCP tool for counting activities"\nassistant: {"status":"success","result":{"tool":"count_activities","registered":true,"build_passed":true},"summary":"Created count_activities tool"}\n</example>
4
4
  model: sonnet
5
5
  tools: Bash, Read, Write, Edit, Glob
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: helga
2
+ name: agent-helga-workflow-config
3
3
  description: Manages Hailer workspace configuration as infrastructure-as-code using SDK v0.8.4. Creates workflows, fields, phases, teams, groups, insights, and document templates via local TypeScript files and SDK commands.\n\n<example>\nuser: "Add a Due Date field to Tasks"\nassistant: {"status":"ready_to_push","result":{"files_edited":["fields.ts"]},"commands":["npm run fields-push:force"],"summary":"Added Due Date field"}\n</example>
4
4
  model: sonnet
5
5
  tools: Bash, Read, Edit, Write, Glob
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: ingrid
2
+ name: agent-ingrid-doc-templates
3
3
  description: Document template specialist for SDK v0.8.4. Creates and manages Hailer document templates (PDF/CSV) with precise field mappings and generation functions.\n\n<example>\nuser: "Create a PDF invoice template"\nassistant: {"status":"ready_to_push","result":{"template_added":true},"commands":["npm run templates-sync:force"],"summary":"Added Invoice template - run command"}\n</example>
4
4
  model: sonnet
5
5
  tools: Bash, Read, Edit, Write, Glob
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: kenji
2
+ name: agent-kenji-data-reader
3
3
  description: LOCAL-FIRST data retrieval for SDK v0.8.4 - reads workspace/ before API. Knows about workflows, fields, phases, templates, functions, teams, groups, and insights.\n\n<example>\nuser: "What fields does Tasks have?"\nassistant: {"status":"success","result":{"fields":["taskName","project","dueDate"]},"source":"local","summary":"Read fields.ts"}\n</example>
4
4
  model: haiku
5
5
  tools: Read, Glob, mcp__hailer__list_workflows_minimal, mcp__hailer__count_activities, mcp__hailer__list_activities, mcp__hailer__list_workflow_phases
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: nora
2
+ name: agent-nora-name-functions
3
3
  description: Creates and manages workflow nameFunction configurations via SDK v0.8.4. Designs JavaScript name generation functions with field dependencies for dynamic activity naming.\n\n<example>\nuser: "Add name function to Employees workflow"\nassistant: {"status":"ready_to_push","result":{"name_function_added":true,"variables":1},"commands":["npm run workflows-push"],"summary":"Added name function to Employees"}\n</example>
4
4
  model: haiku
5
5
  tools: Bash, Read, Edit, Glob
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: svetlana
2
+ name: agent-svetlana-code-review
3
3
  description: Reviews code for bugs, security, and best practices. READ-ONLY.\n\n<example>\nuser: "Review my changes before commit"\nassistant: {"status":"success","result":{"verdict":"REQUEST_CHANGES","critical":2,"warnings":3},"summary":"Found 2 critical issues"}\n</example>
4
4
  model: sonnet
5
5
  tools: Read, Glob, Grep, Bash
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: viktor
2
+ name: agent-viktor-sql-insights
3
3
  description: Creates and manages SQL-like insights over Hailer workflow data via SDK v0.8.4. Designs queries, defines data sources, and deploys through workspace TypeScript files.\n\n<example>\nuser: "Create report showing high priority tasks"\nassistant: {"status":"ready_to_push","result":{"insight_created":true,"sources":1},"commands":["npm run insights-push:force"],"summary":"Created Tasks by Priority insight"}\n</example>
4
4
  model: sonnet
5
5
  tools: Bash, Read, Edit, Write, Glob, mcp__hailer__preview_insight, mcp__hailer__get_insight_data, mcp__hailer__list_workflows, mcp__hailer__get_workflow_schema
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: yevgeni
2
+ name: agent-yevgeni-discussions
3
3
  description: Handles Hailer discussions - reading, posting, membership.\n\n<example>\nuser: "Post update to team discussion"\nassistant: {"status":"success","result":{"posted":true},"summary":"Posted to team discussion"}\n</example>
4
4
  model: haiku
5
5
  tools: mcp__hailer__list_my_discussions, mcp__hailer__fetch_discussion_messages, mcp__hailer__fetch_previous_discussion_messages, mcp__hailer__add_discussion_message, mcp__hailer__join_discussion, mcp__hailer__leave_discussion, mcp__hailer__invite_discussion_members, mcp__hailer__get_activity_from_discussion, mcp__hailer__search_workspace_users
@@ -0,0 +1,315 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Sync Marketplace Agents Hook
4
+ * Watches installed_plugins.json for changes and updates CLAUDE.md
5
+ * with available marketplace agents when plugins are installed/uninstalled.
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const os = require('os');
11
+ const crypto = require('crypto');
12
+
13
+ const PLUGINS_DIR = path.join(os.homedir(), '.claude', 'plugins', 'marketplaces');
14
+ const INSTALLED_PLUGINS = path.join(os.homedir(), '.claude', 'plugins', 'installed_plugins.json');
15
+ const PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR || process.cwd();
16
+ const CLAUDE_MD = path.join(PROJECT_DIR, 'CLAUDE.md');
17
+ const PROJECT_SETTINGS = path.join(PROJECT_DIR, '.claude', 'settings.json');
18
+ const USER_SETTINGS = path.join(os.homedir(), '.claude', 'settings.json');
19
+
20
+ // Store sync state in user's home, keyed by project path hash
21
+ const SYNC_STATE_DIR = path.join(os.homedir(), '.claude', 'sync-state');
22
+ const PROJECT_HASH = crypto.createHash('md5').update(PROJECT_DIR).digest('hex').slice(0, 12);
23
+ const SYNC_STATE = path.join(SYNC_STATE_DIR, `${PROJECT_HASH}.state`);
24
+
25
+ /**
26
+ * Get hash of installed_plugins.json content
27
+ */
28
+ function getInstalledPluginsHash() {
29
+ if (!fs.existsSync(INSTALLED_PLUGINS)) {
30
+ return 'empty';
31
+ }
32
+ const content = fs.readFileSync(INSTALLED_PLUGINS, 'utf-8');
33
+ return crypto.createHash('md5').update(content).digest('hex');
34
+ }
35
+
36
+ /**
37
+ * Check if plugins have changed since last sync
38
+ */
39
+ function pluginsChanged() {
40
+ const currentHash = getInstalledPluginsHash();
41
+
42
+ if (!fs.existsSync(SYNC_STATE)) {
43
+ return true; // First run
44
+ }
45
+
46
+ const lastHash = fs.readFileSync(SYNC_STATE, 'utf-8').trim();
47
+ return currentHash !== lastHash;
48
+ }
49
+
50
+ /**
51
+ * Save current sync state
52
+ */
53
+ function saveSyncState() {
54
+ const currentHash = getInstalledPluginsHash();
55
+ // Ensure sync state directory exists
56
+ if (!fs.existsSync(SYNC_STATE_DIR)) {
57
+ fs.mkdirSync(SYNC_STATE_DIR, { recursive: true });
58
+ }
59
+ fs.writeFileSync(SYNC_STATE, currentHash);
60
+ }
61
+
62
+ /**
63
+ * Get installed plugins from installed_plugins.json
64
+ * Returns Set of "plugin@marketplace" strings
65
+ */
66
+ function getInstalledPlugins() {
67
+ const plugins = new Set();
68
+
69
+ if (!fs.existsSync(INSTALLED_PLUGINS)) {
70
+ return plugins;
71
+ }
72
+
73
+ try {
74
+ const data = JSON.parse(fs.readFileSync(INSTALLED_PLUGINS, 'utf-8'));
75
+ if (data.plugins) {
76
+ for (const pluginKey of Object.keys(data.plugins)) {
77
+ plugins.add(pluginKey);
78
+ }
79
+ }
80
+ } catch (e) {
81
+ // Ignore parse errors
82
+ }
83
+
84
+ return plugins;
85
+ }
86
+
87
+ /**
88
+ * Scan marketplace plugins for agents (all discovered plugins)
89
+ * Supports three structures:
90
+ * - Flat: {marketplace}/agents/ (when plugin name == marketplace name)
91
+ * - Root-level: {marketplace}/{plugin}/agents/ (plugin dirs at marketplace root)
92
+ * - Nested: {marketplace}/plugins/{plugin}/agents/
93
+ */
94
+ function scanMarketplaceAgents(enabledPlugins) {
95
+ const agents = [];
96
+
97
+ if (!fs.existsSync(PLUGINS_DIR)) {
98
+ return agents;
99
+ }
100
+
101
+ const marketplaces = fs.readdirSync(PLUGINS_DIR);
102
+
103
+ for (const marketplace of marketplaces) {
104
+ const marketplacePath = path.join(PLUGINS_DIR, marketplace);
105
+ if (!fs.statSync(marketplacePath).isDirectory()) continue;
106
+
107
+ // Try flat structure first: {marketplace}/agents/
108
+ const flatAgentsPath = path.join(marketplacePath, 'agents');
109
+ if (fs.existsSync(flatAgentsPath)) {
110
+ // For flat structure, plugin name equals marketplace name
111
+ const pluginKey = `${marketplace}@${marketplace}`;
112
+ if (enabledPlugins.has(pluginKey)) {
113
+ const agentFiles = fs.readdirSync(flatAgentsPath).filter(f => f.endsWith('.md'));
114
+
115
+ for (const agentFile of agentFiles) {
116
+ const agentName = path.basename(agentFile, '.md');
117
+ const fullPath = path.join(flatAgentsPath, agentFile);
118
+ const content = fs.readFileSync(fullPath, 'utf-8');
119
+ const frontmatter = parseFrontmatter(content);
120
+
121
+ agents.push({
122
+ marketplace,
123
+ plugin: marketplace,
124
+ name: agentName,
125
+ fullName: `${marketplace}:${agentName}`,
126
+ description: frontmatter.description || '',
127
+ model: frontmatter.model || 'sonnet'
128
+ });
129
+ }
130
+ }
131
+ }
132
+
133
+ // Try root-level plugins: {marketplace}/{plugin}/agents/
134
+ // Each subdirectory with .claude-plugin is a plugin
135
+ const marketplaceContents = fs.readdirSync(marketplacePath);
136
+ for (const item of marketplaceContents) {
137
+ if (item === '.claude-plugin' || item === '.git' || item === 'plugins') continue;
138
+
139
+ const itemPath = path.join(marketplacePath, item);
140
+ if (!fs.statSync(itemPath).isDirectory()) continue;
141
+
142
+ const pluginJsonPath = path.join(itemPath, '.claude-plugin', 'plugin.json');
143
+
144
+ // Check if this is a plugin (has .claude-plugin/plugin.json)
145
+ if (fs.existsSync(pluginJsonPath)) {
146
+ const pluginKey = `${item}@${marketplace}`;
147
+ if (!enabledPlugins.has(pluginKey)) continue;
148
+
149
+ const agentsPath = path.join(itemPath, 'agents');
150
+ if (!fs.existsSync(agentsPath)) continue;
151
+
152
+ const agentFiles = fs.readdirSync(agentsPath).filter(f => f.endsWith('.md'));
153
+
154
+ for (const agentFile of agentFiles) {
155
+ const agentName = path.basename(agentFile, '.md');
156
+ const fullPath = path.join(agentsPath, agentFile);
157
+ const content = fs.readFileSync(fullPath, 'utf-8');
158
+ const frontmatter = parseFrontmatter(content);
159
+
160
+ agents.push({
161
+ marketplace,
162
+ plugin: item,
163
+ name: agentName,
164
+ fullName: `${item}:${agentName}`,
165
+ description: frontmatter.description || '',
166
+ model: frontmatter.model || 'sonnet'
167
+ });
168
+ }
169
+ }
170
+ }
171
+
172
+ // Try nested structure: {marketplace}/plugins/{plugin}/agents/
173
+ const pluginsPath = path.join(marketplacePath, 'plugins');
174
+ if (fs.existsSync(pluginsPath)) {
175
+ const plugins = fs.readdirSync(pluginsPath);
176
+
177
+ for (const plugin of plugins) {
178
+ const pluginKey = `${plugin}@${marketplace}`;
179
+ if (!enabledPlugins.has(pluginKey)) {
180
+ continue;
181
+ }
182
+
183
+ const pluginPath = path.join(pluginsPath, plugin);
184
+ if (!fs.statSync(pluginPath).isDirectory()) continue;
185
+
186
+ const agentsPath = path.join(pluginPath, 'agents');
187
+ if (!fs.existsSync(agentsPath)) continue;
188
+
189
+ const agentFiles = fs.readdirSync(agentsPath).filter(f => f.endsWith('.md'));
190
+
191
+ for (const agentFile of agentFiles) {
192
+ const agentName = path.basename(agentFile, '.md');
193
+ const fullPath = path.join(agentsPath, agentFile);
194
+ const content = fs.readFileSync(fullPath, 'utf-8');
195
+ const frontmatter = parseFrontmatter(content);
196
+
197
+ agents.push({
198
+ marketplace,
199
+ plugin,
200
+ name: agentName,
201
+ fullName: `${plugin}:${agentName}`,
202
+ description: frontmatter.description || '',
203
+ model: frontmatter.model || 'sonnet'
204
+ });
205
+ }
206
+ }
207
+ }
208
+ }
209
+
210
+ return agents;
211
+ }
212
+
213
+ /**
214
+ * Parse frontmatter from markdown
215
+ */
216
+ function parseFrontmatter(content) {
217
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
218
+ if (!match) return {};
219
+
220
+ const frontmatter = {};
221
+ const lines = match[1].split('\n');
222
+
223
+ for (const line of lines) {
224
+ const colonIndex = line.indexOf(':');
225
+ if (colonIndex > 0) {
226
+ const key = line.slice(0, colonIndex).trim();
227
+ let value = line.slice(colonIndex + 1).trim();
228
+ // Clean up description
229
+ if (key === 'description') {
230
+ value = value.replace(/\\n.*/g, '').slice(0, 100);
231
+ }
232
+ frontmatter[key] = value;
233
+ }
234
+ }
235
+
236
+ return frontmatter;
237
+ }
238
+
239
+ /**
240
+ * Generate marketplace agents table
241
+ */
242
+ function generateAgentTable(agents) {
243
+ if (agents.length === 0) {
244
+ return 'No marketplace agents installed.';
245
+ }
246
+
247
+ let table = '| Agent | Plugin | Model | Description |\n';
248
+ table += '|-------|--------|-------|-------------|\n';
249
+
250
+ for (const agent of agents) {
251
+ const desc = agent.description.slice(0, 50) + (agent.description.length > 50 ? '...' : '');
252
+ table += `| \`${agent.fullName}\` | ${agent.plugin} | ${agent.model} | ${desc} |\n`;
253
+ }
254
+
255
+ return table;
256
+ }
257
+
258
+ /**
259
+ * Update CLAUDE.md with marketplace agents
260
+ */
261
+ function updateClaudeMd(agents) {
262
+ if (!fs.existsSync(CLAUDE_MD)) {
263
+ return { updated: false, reason: 'CLAUDE.md not found' };
264
+ }
265
+
266
+ let content = fs.readFileSync(CLAUDE_MD, 'utf-8');
267
+
268
+ const agentTable = generateAgentTable(agents);
269
+
270
+ // Find and update plugin-marketplace section
271
+ const sectionRegex = /(<plugin-marketplace>[\s\S]*?)(No marketplace agents installed\.|(\| Agent \|[\s\S]*?\n)(?=\n\*\*|<\/plugin-marketplace>))/;
272
+
273
+ if (sectionRegex.test(content)) {
274
+ content = content.replace(sectionRegex, `$1${agentTable}\n`);
275
+ fs.writeFileSync(CLAUDE_MD, content);
276
+ return { updated: true, count: agents.length };
277
+ }
278
+
279
+ return { updated: false, reason: 'plugin-marketplace section not found' };
280
+ }
281
+
282
+ /**
283
+ * Main
284
+ */
285
+ function main() {
286
+ // Skip if installed_plugins.json hasn't changed
287
+ if (!pluginsChanged()) {
288
+ process.exit(0);
289
+ }
290
+
291
+ try {
292
+ // Get actually installed plugins from installed_plugins.json
293
+ const installedPlugins = getInstalledPlugins();
294
+
295
+ // Scan agents only from installed plugins
296
+ const agents = scanMarketplaceAgents(installedPlugins);
297
+ const result = updateClaudeMd(agents);
298
+
299
+ // Save sync state
300
+ saveSyncState();
301
+
302
+ // Output info
303
+ console.error(`[sync-agents] Detected plugin changes, found ${agents.length} marketplace agents`);
304
+ if (result.updated) {
305
+ console.error(`[sync-agents] Updated CLAUDE.md`);
306
+ }
307
+
308
+ process.exit(0);
309
+ } catch (error) {
310
+ console.error(`[sync-agents] Error: ${error.message}`);
311
+ process.exit(0); // Don't block on errors
312
+ }
313
+ }
314
+
315
+ main();
@@ -16,6 +16,11 @@
16
16
  "type": "command",
17
17
  "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/interactive-mode.cjs\"",
18
18
  "timeout": 5
19
+ },
20
+ {
21
+ "type": "command",
22
+ "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/sync-marketplace-agents.cjs\"",
23
+ "timeout": 5
19
24
  }
20
25
  ]
21
26
  }
package/CHANGELOG.md CHANGED
@@ -4,6 +4,69 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.1.8] - 15-12-2025
8
+
9
+ ### Fixed
10
+
11
+ - Corrected marketplace git URL to `git@gitlab.com:hailer-repos/hailer-mcp-marketplace.git`
12
+
13
+ ## [0.1.7] - 15-12-2025
14
+
15
+ ### Changed
16
+
17
+ - **Marketplace Sync Hook**:
18
+ - Changed from session-based to hash-based sync (tracks `installed_plugins.json` changes)
19
+ - Added support for root-level plugin structure: `{marketplace}/{plugin}/agents/`
20
+ - Per-project sync state to avoid unnecessary re-syncs
21
+ - Improved logging when plugin changes detected
22
+
23
+ - **Plugin Documentation**:
24
+ - Restructured CLAUDE.md with separate `<plugin-setup>` and `<plugin-contributing>` sections
25
+ - Clearer instructions for marketplace installation and contribution
26
+
27
+ ## [0.1.5] - 12-12-2025
28
+
29
+ ### Added
30
+
31
+ - **Marketplace System**:
32
+ - `sync-marketplace-agents.cjs` hook - Syncs installed marketplace agents to CLAUDE.md
33
+ - Support for flat and nested plugin structures
34
+ - Individual plugin installation support
35
+
36
+ ### Changed
37
+
38
+ - **Agent Namespace Convention**:
39
+ - All agents renamed to `agent-<name>-<description>` format
40
+ - Examples: `agent-kenji-data-reader`, `agent-viktor-sql-insights`
41
+ - Agent builder updated with namespace template
42
+
43
+ - Updated agents with SDK v0.8.4 compatibility
44
+ - Added `agent-nora-name-functions` for workflow name functions
45
+ - Updated CLAUDE.md marketplace URL
46
+
47
+ ## [0.1.4] - 11-12-2025
48
+
49
+ ### Changed
50
+
51
+ - XML tag format for skills
52
+ - XML tag updates for hooks and client improvements
53
+ - Fixed stale hook reference
54
+
55
+ ## [0.1.3] - 10-12-2025
56
+
57
+ ### Changed
58
+
59
+ - **Agent System Refactor**:
60
+ - XML tag format for agents
61
+ - Multi-agent hook system
62
+ - Replaced skills system with specialized agents
63
+
64
+ ## [0.0.6] - 02-12-2025
65
+
66
+ ### Changed
67
+
68
+ - Updated scaffold-hailer-app skill with improved patterns
69
+
7
70
  ## [0.0.5] - 01-12-2025
8
71
 
9
72
  ### Added
package/CLAUDE.md CHANGED
@@ -22,19 +22,20 @@ Agents return JSON. You interpret it for the user.
22
22
  <agents>
23
23
  | Pattern | Agent | Model |
24
24
  |---------|-------|-------|
25
- | Read data/schema | `kenji` | haiku |
26
- | Activity CRUD | `dmitri` | haiku |
27
- | Discussions/chat | `yevgeni` | haiku |
28
- | Config audit | `bjorn` | haiku |
29
- | Workflows, fields, phases | `helga` | sonnet |
30
- | SQL insights | `viktor` | sonnet |
31
- | Function fields | `alejandro` | sonnet |
32
- | MCP tools | `gunther` | sonnet |
33
- | Hailer apps | `giuseppe` | sonnet |
34
- | Code review | `svetlana` | sonnet |
35
- | New agents | `agent-builder` | sonnet |
36
- | Skills, agent improvements | `ada` | sonnet |
37
- | Document templates | `ingrid` | sonnet |
25
+ | Read data/schema | `agent-kenji-data-reader` | haiku |
26
+ | Activity CRUD | `agent-dmitri-activity-crud` | haiku |
27
+ | Discussions/chat | `agent-yevgeni-discussions` | haiku |
28
+ | Config audit | `agent-bjorn-config-audit` | haiku |
29
+ | Workflows, fields, phases | `agent-helga-workflow-config` | sonnet |
30
+ | SQL insights | `agent-viktor-sql-insights` | sonnet |
31
+ | Function fields | `agent-alejandro-function-fields` | sonnet |
32
+ | MCP tools | `agent-gunther-mcp-tools` | sonnet |
33
+ | Hailer apps | `agent-giuseppe-app-builder` | sonnet |
34
+ | Code review | `agent-svetlana-code-review` | sonnet |
35
+ | New agents | `agent-builder-agent-creator` | sonnet |
36
+ | Skills, agent improvements | `agent-ada-skill-builder` | sonnet |
37
+ | Document templates | `agent-ingrid-doc-templates` | sonnet |
38
+ | Name functions | `agent-nora-name-functions` | sonnet |
38
39
  </agents>
39
40
 
40
41
  <delegation-protocol>
@@ -52,7 +53,7 @@ OUTPUT (JSON only, no prose):
52
53
  { "status": "success|error|ready_to_push|needs_confirmation", "result": {}, "summary": "max 50 chars" }
53
54
  ```
54
55
 
55
- FLOW: Get IDs first (kenji) → pass to execution agents (dmitri, helga, etc.)
56
+ FLOW: Get IDs first (agent-kenji-data-reader) → pass to execution agents (agent-dmitri-activity-crud, agent-helga-workflow-config, etc.)
56
57
  </delegation-protocol>
57
58
 
58
59
  <push-commands>
@@ -154,6 +155,54 @@ DISABLE: Move to `docs/agents/`
154
155
  WITHOUT AGENTS: Use MCP tools directly
155
156
  </customization>
156
157
 
158
+ <plugin-marketplace>
159
+ Community agents are shared via the Hailer Agent Marketplace (separate git repo).
160
+
161
+ **Marketplace URL:** `git@gitlab.com:hailer-repos/hailer-mcp-marketplace.git`
162
+
163
+ **Installed marketplace agents:**
164
+ No marketplace agents installed.
165
+
166
+ **Use plugin agents:**
167
+ ```
168
+ Task(subagent_type="plugin:agent-name", prompt="...", model="haiku|sonnet")
169
+ ```
170
+
171
+ **Agent sources:**
172
+ - Default agents: `.claude/agents/` (shipped via npm)
173
+ - Community agents: Plugin marketplace (installed separately)
174
+ </plugin-marketplace>
175
+
176
+ <plugin-setup>
177
+ When user asks to install plugins or set up the marketplace:
178
+
179
+ 1. Tell user to run these slash commands:
180
+ ```
181
+ /plugin marketplace add git@gitlab.com:hailer-repos/hailer-mcp-marketplace.git
182
+ /plugin install <plugin-name>
183
+ ```
184
+
185
+ 2. Tell user: "Restart Claude Code to load the new agents."
186
+
187
+ Available plugins: `permissions-handler`, `hailer-agents`
188
+
189
+ After restart, sync hook updates this file automatically with installed agents.
190
+ </plugin-setup>
191
+
192
+ <plugin-contributing>
193
+ To contribute agents to the marketplace:
194
+
195
+ 1. Clone: `git clone git@gitlab.com:hailer-repos/hailer-mcp-marketplace.git`
196
+ 2. Create plugin structure:
197
+ ```
198
+ my-plugin/
199
+ .claude-plugin/plugin.json
200
+ agents/agent-my-agent.md
201
+ ```
202
+ 3. Follow agent structure from `<agent-structure>` section
203
+ 4. Push to repo
204
+ </plugin-contributing>
205
+
157
206
  <directory>
158
207
  ```
159
208
  workspace/ # Local config (check FIRST)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hailer/mcp",
3
- "version": "0.1.5",
3
+ "version": "0.1.8",
4
4
  "config": {
5
5
  "docker": {
6
6
  "registry": "registry.gitlab.com/hailer-repos/hailer-mcp"