runwork 0.5.1 → 0.6.0

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 (116) hide show
  1. package/dist/agents/__tests__/claude-code-stats.test.d.ts +1 -0
  2. package/dist/agents/__tests__/claude-code-stats.test.js +153 -0
  3. package/dist/agents/__tests__/claude-desktop-stats.test.d.ts +1 -0
  4. package/dist/agents/__tests__/claude-desktop-stats.test.js +280 -0
  5. package/dist/agents/__tests__/codex-stats.test.d.ts +1 -0
  6. package/dist/agents/__tests__/codex-stats.test.js +262 -0
  7. package/dist/agents/__tests__/cursor-stats.test.d.ts +1 -0
  8. package/dist/agents/__tests__/cursor-stats.test.js +183 -0
  9. package/dist/agents/__tests__/graceful-degradation.test.d.ts +1 -0
  10. package/dist/agents/__tests__/graceful-degradation.test.js +123 -0
  11. package/dist/agents/__tests__/instruction-hint.test.d.ts +1 -0
  12. package/dist/agents/__tests__/instruction-hint.test.js +69 -0
  13. package/dist/agents/__tests__/intro-skill.test.d.ts +1 -0
  14. package/dist/agents/__tests__/intro-skill.test.js +135 -0
  15. package/dist/agents/__tests__/schema-validation.test.d.ts +1 -0
  16. package/dist/agents/__tests__/schema-validation.test.js +212 -0
  17. package/dist/agents/claude-code.d.ts +16 -1
  18. package/dist/agents/claude-code.js +344 -21
  19. package/dist/agents/claude-desktop.d.ts +10 -1
  20. package/dist/agents/claude-desktop.js +250 -8
  21. package/dist/agents/cline.d.ts +13 -0
  22. package/dist/agents/cline.js +88 -0
  23. package/dist/agents/codex.d.ts +7 -2
  24. package/dist/agents/codex.js +130 -18
  25. package/dist/agents/cursor.d.ts +6 -1
  26. package/dist/agents/cursor.js +164 -7
  27. package/dist/agents/detect.js +30 -7
  28. package/dist/agents/gemini.d.ts +6 -3
  29. package/dist/agents/gemini.js +57 -20
  30. package/dist/agents/generic-adapter.d.ts +23 -0
  31. package/dist/agents/generic-adapter.js +106 -0
  32. package/dist/agents/intro-skill.d.ts +36 -0
  33. package/dist/agents/intro-skill.js +358 -0
  34. package/dist/agents/registry.d.ts +53 -0
  35. package/dist/agents/registry.js +219 -0
  36. package/dist/agents/types.d.ts +44 -1
  37. package/dist/agents/types.js +11 -4
  38. package/dist/agents/utils/instruction-hint.d.ts +11 -0
  39. package/dist/agents/utils/instruction-hint.js +62 -0
  40. package/dist/agents/utils/json-config.js +3 -3
  41. package/dist/agents/windsurf.d.ts +2 -0
  42. package/dist/agents/windsurf.js +26 -9
  43. package/dist/api/client.d.ts +85 -2
  44. package/dist/api/client.js +40 -10
  45. package/dist/auth/__tests__/login-flow.test.d.ts +1 -0
  46. package/dist/auth/__tests__/login-flow.test.js +125 -0
  47. package/dist/auth/login-flow.d.ts +16 -0
  48. package/dist/auth/login-flow.js +101 -1
  49. package/dist/commands/clone.d.ts +9 -1
  50. package/dist/commands/clone.js +40 -12
  51. package/dist/commands/deploy.js +27 -4
  52. package/dist/commands/dev.js +35 -1
  53. package/dist/commands/doctor.d.ts +2 -0
  54. package/dist/commands/doctor.js +82 -0
  55. package/dist/commands/info.js +6 -2
  56. package/dist/commands/init.d.ts +10 -2
  57. package/dist/commands/init.js +58 -15
  58. package/dist/commands/integrations.js +47 -10
  59. package/dist/commands/login.js +31 -4
  60. package/dist/commands/mcp.js +143 -15
  61. package/dist/commands/setup.js +47 -122
  62. package/dist/commands/skills.js +230 -12
  63. package/dist/commands/sync.d.ts +8 -0
  64. package/dist/commands/sync.js +398 -65
  65. package/dist/commands/welcome.js +6 -3
  66. package/dist/generated/version.d.ts +1 -1
  67. package/dist/generated/version.js +1 -1
  68. package/dist/health/__tests__/checks.test.d.ts +1 -0
  69. package/dist/health/__tests__/checks.test.js +223 -0
  70. package/dist/health/checks.d.ts +20 -0
  71. package/dist/health/checks.js +392 -0
  72. package/dist/health/runner.d.ts +2 -0
  73. package/dist/health/runner.js +26 -0
  74. package/dist/health/types.d.ts +12 -0
  75. package/dist/health/types.js +1 -0
  76. package/dist/index.js +32 -0
  77. package/dist/sync/__tests__/change-detect.test.d.ts +1 -0
  78. package/dist/sync/__tests__/change-detect.test.js +123 -0
  79. package/dist/sync/__tests__/hash.test.d.ts +1 -0
  80. package/dist/sync/__tests__/hash.test.js +18 -0
  81. package/dist/sync/change-detect.d.ts +19 -0
  82. package/dist/sync/change-detect.js +136 -0
  83. package/dist/sync/conflict-ui.d.ts +5 -0
  84. package/dist/sync/conflict-ui.js +78 -0
  85. package/dist/sync/executor.d.ts +21 -0
  86. package/dist/sync/executor.js +98 -0
  87. package/dist/sync/hash.d.ts +1 -0
  88. package/dist/sync/hash.js +4 -0
  89. package/dist/sync/types.d.ts +24 -0
  90. package/dist/sync/types.js +1 -0
  91. package/dist/types.d.ts +12 -0
  92. package/dist/ui/__tests__/banner.test.js +17 -1
  93. package/dist/ui/banner.d.ts +1 -1
  94. package/dist/ui/banner.js +27 -2
  95. package/dist/utils/__tests__/resolve.test.d.ts +1 -0
  96. package/dist/utils/__tests__/resolve.test.js +95 -0
  97. package/dist/utils/__tests__/sqlite.test.d.ts +1 -0
  98. package/dist/utils/__tests__/sqlite.test.js +77 -0
  99. package/dist/utils/agent-guidance.d.ts +32 -0
  100. package/dist/utils/agent-guidance.js +106 -0
  101. package/dist/utils/fs.js +2 -2
  102. package/dist/utils/help-json.d.ts +56 -0
  103. package/dist/utils/help-json.js +85 -0
  104. package/dist/utils/resolve.d.ts +12 -0
  105. package/dist/utils/resolve.js +52 -0
  106. package/dist/utils/setup-state.d.ts +3 -0
  107. package/dist/utils/setup-state.js +19 -0
  108. package/dist/utils/sqlite.d.ts +7 -0
  109. package/dist/utils/sqlite.js +24 -0
  110. package/dist/utils/which.d.ts +6 -0
  111. package/dist/utils/which.js +18 -0
  112. package/package.json +7 -3
  113. package/dist/agents/copilot-cli.d.ts +0 -10
  114. package/dist/agents/copilot-cli.js +0 -46
  115. package/dist/agents/copilot-vscode.d.ts +0 -10
  116. package/dist/agents/copilot-vscode.js +0 -37
@@ -1,20 +1,45 @@
1
- import { existsSync, mkdirSync, writeFileSync } from 'fs';
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
- import { homedir } from 'os';
3
+ import { homedir, platform } from 'os';
4
4
  import { execFileSync } from 'child_process';
5
+ import { whichBinary } from '../utils/which.js';
5
6
  import { buildSkillMd } from './types.js';
6
- import { mergeJsonMcpServers } from './utils/json-config.js';
7
+ import { mergeJsonMcpServers, readJsonConfig, writeJsonConfig } from './utils/json-config.js';
8
+ import { writeHintToFile, writeTeamInstructionsToFile } from './utils/instruction-hint.js';
9
+ const PLUGIN_NAME = 'runwork';
10
+ const PLUGIN_VERSION = '1.0.0';
11
+ function getPluginJson() {
12
+ return {
13
+ name: PLUGIN_NAME,
14
+ version: PLUGIN_VERSION,
15
+ description: 'Skills and tools from your Runwork workspace',
16
+ author: { name: 'Runwork' },
17
+ homepage: 'https://www.runwork.ai',
18
+ };
19
+ }
20
+ function getMarketplaceJson() {
21
+ return {
22
+ name: 'runwork',
23
+ owner: { name: 'Runwork' },
24
+ plugins: [
25
+ {
26
+ name: PLUGIN_NAME,
27
+ source: `./plugins/${PLUGIN_NAME}`,
28
+ description: 'Skills and tools from your Runwork workspace',
29
+ },
30
+ ],
31
+ };
32
+ }
7
33
  export class ClaudeCodeAdapter {
8
34
  name = 'Claude Code';
9
35
  slug = 'claude-code';
10
36
  async detect() {
11
- try {
12
- execFileSync('which', ['claude'], { stdio: 'pipe' });
37
+ if (whichBinary('claude'))
13
38
  return true;
14
- }
15
- catch {
39
+ // Fallback: check app bundle on macOS
40
+ if (platform() === 'darwin')
16
41
  return existsSync('/Applications/Claude.app');
17
- }
42
+ return false;
18
43
  }
19
44
  supportsMcpScope(_scope) {
20
45
  return true;
@@ -23,28 +48,326 @@ export class ClaudeCodeAdapter {
23
48
  return true;
24
49
  }
25
50
  async writeMcpServers(servers, scope) {
26
- const filePath = scope === 'project'
27
- ? join(process.cwd(), '.mcp.json')
28
- : join(homedir(), '.claude', 'settings.json');
29
- const entries = {};
30
- for (const s of servers) {
31
- entries[s.name] = {
32
- type: 'http',
33
- url: s.url,
34
- ...(s.headers ? { headers: s.headers } : {}),
35
- };
51
+ if (scope === 'project') {
52
+ // Project scope: write to .mcp.json (standard Claude Code location)
53
+ const filePath = join(process.cwd(), '.mcp.json');
54
+ const entries = {};
55
+ for (const s of servers) {
56
+ entries[s.name] = {
57
+ type: 'http',
58
+ url: s.url,
59
+ ...(s.headers ? { headers: s.headers } : {}),
60
+ ...(s.description ? { description: s.description } : {}),
61
+ };
62
+ }
63
+ mergeJsonMcpServers(filePath, entries, 'mcpServers');
64
+ }
65
+ else {
66
+ // User scope: write MCP config both in global settings and inside the plugin
67
+ const settingsPath = join(homedir(), '.claude', 'settings.json');
68
+ const entries = {};
69
+ for (const s of servers) {
70
+ entries[s.name] = {
71
+ type: 'http',
72
+ url: s.url,
73
+ ...(s.headers ? { headers: s.headers } : {}),
74
+ ...(s.description ? { description: s.description } : {}),
75
+ };
76
+ }
77
+ mergeJsonMcpServers(settingsPath, entries, 'mcpServers');
78
+ // Also write .mcp.json in the plugin directory
79
+ const pluginDir = this.getPluginDir();
80
+ mkdirSync(pluginDir, { recursive: true });
81
+ const pluginMcpPath = join(pluginDir, '.mcp.json');
82
+ const pluginEntries = {};
83
+ for (const s of servers) {
84
+ pluginEntries[s.name] = {
85
+ type: 'http',
86
+ url: s.url,
87
+ ...(s.headers ? { headers: s.headers } : {}),
88
+ ...(s.description ? { description: s.description } : {}),
89
+ };
90
+ }
91
+ writeJsonConfig(pluginMcpPath, pluginEntries);
36
92
  }
37
- mergeJsonMcpServers(filePath, entries, 'mcpServers');
38
93
  }
39
94
  async writeSkills(skills, scope) {
95
+ // Always write to the standard skills directory (guaranteed to work)
40
96
  const baseDir = scope === 'project'
41
97
  ? join(process.cwd(), '.claude', 'skills')
42
98
  : join(homedir(), '.claude', 'skills');
43
99
  for (const skill of skills) {
44
100
  const skillDir = join(baseDir, skill.name);
45
101
  mkdirSync(skillDir, { recursive: true });
46
- const content = buildSkillMd(skill);
47
- writeFileSync(join(skillDir, 'SKILL.md'), content);
102
+ writeFileSync(join(skillDir, 'SKILL.md'), buildSkillMd(skill));
103
+ }
104
+ // User scope: also write as a plugin for native plugin UI support
105
+ if (scope === 'user') {
106
+ const pluginDir = this.getPluginDir();
107
+ // Create plugin.json
108
+ const pluginJsonDir = join(pluginDir, '.claude-plugin');
109
+ mkdirSync(pluginJsonDir, { recursive: true });
110
+ writeFileSync(join(pluginJsonDir, 'plugin.json'), JSON.stringify(getPluginJson(), null, 2));
111
+ // Write skill files inside the plugin
112
+ for (const skill of skills) {
113
+ const skillDir = join(pluginDir, 'skills', skill.name);
114
+ mkdirSync(skillDir, { recursive: true });
115
+ writeFileSync(join(skillDir, 'SKILL.md'), buildSkillMd(skill));
116
+ }
117
+ // Also write to the marketplace directory
118
+ const marketDir = this.getMarketplaceDir();
119
+ const marketPluginJsonDir = join(marketDir, '.claude-plugin');
120
+ mkdirSync(marketPluginJsonDir, { recursive: true });
121
+ writeFileSync(join(marketPluginJsonDir, 'plugin.json'), JSON.stringify(getPluginJson(), null, 2));
122
+ for (const skill of skills) {
123
+ const skillDir = join(marketDir, 'skills', skill.name);
124
+ mkdirSync(skillDir, { recursive: true });
125
+ writeFileSync(join(skillDir, 'SKILL.md'), buildSkillMd(skill));
126
+ }
127
+ // Register in installed_plugins.json
128
+ this.registerPlugin(pluginDir);
129
+ }
130
+ }
131
+ async writeInstructionHint(hint, scope) {
132
+ const filePath = scope === 'project'
133
+ ? join(process.cwd(), '.claude', 'CLAUDE.md')
134
+ : join(homedir(), '.claude', 'CLAUDE.md');
135
+ writeHintToFile(filePath, hint);
136
+ }
137
+ async writeTeamInstructions(instructions, scope) {
138
+ // Write to CLAUDE.md via markers (direct instruction file approach)
139
+ const filePath = scope === 'project'
140
+ ? join(process.cwd(), '.claude', 'CLAUDE.md')
141
+ : join(homedir(), '.claude', 'CLAUDE.md');
142
+ writeTeamInstructionsToFile(filePath, instructions);
143
+ // Also write as a plugin skill (same mechanism as Claude Desktop)
144
+ if (scope === 'user') {
145
+ const skillContent = `---\nname: runwork-team-instructions\ndescription: Team instructions from your Runwork workspace. Always follow these guidelines.\n---\n\n${instructions}`;
146
+ const pluginDir = this.getPluginDir();
147
+ const marketDir = this.getMarketplaceDir();
148
+ for (const dir of [
149
+ join(pluginDir, 'skills', 'runwork-team-instructions'),
150
+ join(marketDir, 'skills', 'runwork-team-instructions'),
151
+ ]) {
152
+ mkdirSync(dir, { recursive: true });
153
+ writeFileSync(join(dir, 'SKILL.md'), skillContent);
154
+ }
155
+ }
156
+ }
157
+ // ── Agent config (model, permissions) ──────────────────────────────
158
+ async writeAgentConfig(config, scope) {
159
+ const settingsPath = scope === 'project'
160
+ ? join(process.cwd(), '.claude', 'settings.json')
161
+ : join(homedir(), '.claude', 'settings.json');
162
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
163
+ let settings = {};
164
+ if (existsSync(settingsPath)) {
165
+ try {
166
+ settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
167
+ }
168
+ catch { /* start fresh */ }
169
+ }
170
+ if (config.modelPreference) {
171
+ settings.model = config.modelPreference;
172
+ }
173
+ if (config.permissionRules) {
174
+ if (!settings.permissions)
175
+ settings.permissions = {};
176
+ const perms = settings.permissions;
177
+ const MANAGED_MARKER = '# runwork-managed';
178
+ if (config.permissionRules.allow) {
179
+ const cleanExisting = this.removeAfterMarker(perms.allow ?? [], MANAGED_MARKER);
180
+ perms.allow = [...cleanExisting, MANAGED_MARKER, ...config.permissionRules.allow];
181
+ }
182
+ if (config.permissionRules.deny) {
183
+ const cleanExisting = this.removeAfterMarker(perms.deny ?? [], MANAGED_MARKER);
184
+ perms.deny = [...cleanExisting, MANAGED_MARKER, ...config.permissionRules.deny];
185
+ }
186
+ if (config.permissionRules.defaultMode) {
187
+ perms.defaultMode = config.permissionRules.defaultMode;
188
+ }
189
+ }
190
+ mkdirSync(join(settingsPath, '..'), { recursive: true });
191
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
192
+ }
193
+ /** Remove the managed marker and all entries after it from a permissions array */
194
+ removeAfterMarker(arr, marker) {
195
+ const idx = arr.indexOf(marker);
196
+ return idx >= 0 ? arr.slice(0, idx) : [...arr];
197
+ }
198
+ // ── Usage stats (passive, best-effort) ─────────────────────────────
199
+ async readUsageStats(lastSyncAt) {
200
+ try {
201
+ const claudeDir = join(homedir(), '.claude');
202
+ if (!existsSync(claudeDir))
203
+ return null;
204
+ // Primary: stats-cache.json has pre-computed daily activity
205
+ // Format: { version, lastComputedDate, dailyActivity: [{ date, messageCount, sessionCount, toolCallCount }] }
206
+ const statsCachePath = join(claudeDir, 'stats-cache.json');
207
+ if (existsSync(statsCachePath)) {
208
+ const statsCache = JSON.parse(readFileSync(statsCachePath, 'utf-8'));
209
+ if (statsCache.dailyActivity && Array.isArray(statsCache.dailyActivity)) {
210
+ const sinceDate = lastSyncAt ? lastSyncAt.slice(0, 10) : '1970-01-01';
211
+ const recentDays = statsCache.dailyActivity.filter((d) => d.date > sinceDate);
212
+ const totalMessages = recentDays.reduce((sum, d) => sum + (d.messageCount ?? 0), 0);
213
+ const totalSessions = recentDays.reduce((sum, d) => sum + (d.sessionCount ?? 0), 0);
214
+ const totalToolCalls = recentDays.reduce((sum, d) => sum + (d.toolCallCount ?? 0), 0);
215
+ if (totalMessages > 0 || totalSessions > 0) {
216
+ return {
217
+ hasNewActivity: true,
218
+ sessionCount: totalSessions,
219
+ messageCount: totalMessages,
220
+ toolCallCount: totalToolCalls,
221
+ tokensUsed: 0,
222
+ aiLinesAdded: 0,
223
+ aiLinesRemoved: 0,
224
+ lastActiveAt: recentDays.length > 0
225
+ ? new Date(recentDays[recentDays.length - 1].date).toISOString()
226
+ : null,
227
+ };
228
+ }
229
+ }
230
+ }
231
+ // Fallback: count session directories modified since last sync
232
+ const sessionEnvDir = join(claudeDir, 'session-env');
233
+ if (existsSync(sessionEnvDir)) {
234
+ const entries = readdirSync(sessionEnvDir);
235
+ const sinceMs = lastSyncAt ? new Date(lastSyncAt).getTime() : 0;
236
+ let recentCount = 0;
237
+ let latestMtime = 0;
238
+ for (const entry of entries) {
239
+ try {
240
+ const stat = statSync(join(sessionEnvDir, entry));
241
+ if (stat.mtimeMs > sinceMs)
242
+ recentCount++;
243
+ if (stat.mtimeMs > latestMtime)
244
+ latestMtime = stat.mtimeMs;
245
+ }
246
+ catch {
247
+ continue;
248
+ }
249
+ }
250
+ if (recentCount > 0) {
251
+ return {
252
+ hasNewActivity: true,
253
+ sessionCount: recentCount,
254
+ messageCount: 0,
255
+ toolCallCount: 0,
256
+ tokensUsed: 0,
257
+ aiLinesAdded: 0,
258
+ aiLinesRemoved: 0,
259
+ lastActiveAt: new Date(latestMtime).toISOString(),
260
+ };
261
+ }
262
+ }
263
+ return null;
264
+ }
265
+ catch {
266
+ return null;
267
+ }
268
+ }
269
+ async readSkillUsage(lastSyncAt) {
270
+ try {
271
+ const results = [];
272
+ const sinceMs = lastSyncAt ? new Date(lastSyncAt).getTime() : 0;
273
+ const skillDirs = [
274
+ join(homedir(), '.claude', 'skills'),
275
+ join(process.cwd(), '.claude', 'skills'),
276
+ ];
277
+ for (const dir of skillDirs) {
278
+ if (!existsSync(dir))
279
+ continue;
280
+ for (const entry of readdirSync(dir)) {
281
+ if (entry === 'runwork')
282
+ continue;
283
+ const skillDir = join(dir, entry);
284
+ try {
285
+ const stat = statSync(skillDir);
286
+ if (stat.mtimeMs > sinceMs) {
287
+ results.push({
288
+ skillName: entry,
289
+ count: 1,
290
+ lastUsedAt: new Date(stat.mtimeMs).toISOString(),
291
+ });
292
+ }
293
+ }
294
+ catch {
295
+ continue;
296
+ }
297
+ }
298
+ }
299
+ return results.length > 0 ? results : null;
300
+ }
301
+ catch {
302
+ return null;
303
+ }
304
+ }
305
+ async readVersion() {
306
+ try {
307
+ const output = execFileSync('claude', ['--version'], { stdio: 'pipe' }).toString().trim();
308
+ return output;
309
+ }
310
+ catch {
311
+ return null;
312
+ }
313
+ }
314
+ // ── Plugin helpers ─────────────────────────────────────────────────
315
+ getPluginsBaseDir() {
316
+ return join(homedir(), '.claude', 'plugins');
317
+ }
318
+ getPluginDir() {
319
+ return join(this.getPluginsBaseDir(), 'cache', 'runwork', PLUGIN_NAME, PLUGIN_VERSION);
320
+ }
321
+ /** The marketplace root (contains marketplace.json and plugins/) */
322
+ getMarketplaceRoot() {
323
+ return join(this.getPluginsBaseDir(), 'marketplaces', 'runwork');
324
+ }
325
+ /** The plugin directory within the marketplace */
326
+ getMarketplaceDir() {
327
+ return join(this.getMarketplaceRoot(), 'plugins', PLUGIN_NAME);
328
+ }
329
+ registerPlugin(pluginDir) {
330
+ const pluginsBase = this.getPluginsBaseDir();
331
+ mkdirSync(pluginsBase, { recursive: true });
332
+ // Register in installed_plugins.json
333
+ const installedPath = join(pluginsBase, 'installed_plugins.json');
334
+ const installed = readJsonConfig(installedPath);
335
+ if (!installed.version)
336
+ installed.version = 2;
337
+ if (!installed.plugins)
338
+ installed.plugins = {};
339
+ installed.plugins[`${PLUGIN_NAME}@runwork`] = [{
340
+ scope: 'user',
341
+ installPath: pluginDir,
342
+ version: PLUGIN_VERSION,
343
+ installedAt: new Date().toISOString(),
344
+ lastUpdated: new Date().toISOString(),
345
+ }];
346
+ writeJsonConfig(installedPath, installed);
347
+ // Write marketplace.json catalog
348
+ const marketRoot = this.getMarketplaceRoot();
349
+ const marketCatalogDir = join(marketRoot, '.claude-plugin');
350
+ mkdirSync(marketCatalogDir, { recursive: true });
351
+ writeFileSync(join(marketCatalogDir, 'marketplace.json'), JSON.stringify(getMarketplaceJson(), null, 2));
352
+ // Register in known_marketplaces.json
353
+ const marketplacesPath = join(pluginsBase, 'known_marketplaces.json');
354
+ const marketplaces = readJsonConfig(marketplacesPath);
355
+ marketplaces['runwork'] = {
356
+ source: { source: 'directory', path: marketRoot },
357
+ installLocation: marketRoot,
358
+ lastUpdated: new Date().toISOString(),
359
+ };
360
+ writeJsonConfig(marketplacesPath, marketplaces);
361
+ // Enable the plugin in settings.json
362
+ const settingsPath = join(homedir(), '.claude', 'settings.json');
363
+ const settings = readJsonConfig(settingsPath);
364
+ if (!settings['enabledPlugins']) {
365
+ settings['enabledPlugins'] = {};
366
+ }
367
+ const enabled = settings['enabledPlugins'];
368
+ if (!enabled[`${PLUGIN_NAME}@runwork`]) {
369
+ enabled[`${PLUGIN_NAME}@runwork`] = true;
370
+ writeJsonConfig(settingsPath, settings);
48
371
  }
49
372
  }
50
373
  }
@@ -1,4 +1,4 @@
1
- import type { AgentAdapter, McpServerEntry, SkillFile } from './types.js';
1
+ import type { AgentAdapter, AgentConfigOverride, AgentUsageStats, McpServerEntry, SkillFile } from './types.js';
2
2
  export declare class ClaudeDesktopAdapter implements AgentAdapter {
3
3
  name: string;
4
4
  slug: string;
@@ -7,4 +7,13 @@ export declare class ClaudeDesktopAdapter implements AgentAdapter {
7
7
  supportsSkills(): boolean;
8
8
  writeMcpServers(servers: McpServerEntry[], _scope: 'project' | 'user'): Promise<void>;
9
9
  writeSkills(skills: SkillFile[], _scope: 'project' | 'user'): Promise<void>;
10
+ writeInstructionHint(_hint: string, _scope: 'project' | 'user'): Promise<void>;
11
+ writeTeamInstructions(instructions: string, _scope: 'project' | 'user'): Promise<void>;
12
+ writeAgentConfig(config: AgentConfigOverride, _scope: 'project' | 'user'): Promise<void>;
13
+ readUsageStats(lastSyncAt: string | null): Promise<AgentUsageStats | null>;
14
+ readVersion(): Promise<string | null>;
15
+ /**
16
+ * Walk the org/user/session directory tree and invoke callback for each session JSON.
17
+ */
18
+ private walkSessionDirs;
10
19
  }