@compilr-dev/cli 0.8.9 → 0.9.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 (31) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/agent.d.ts +9 -0
  3. package/dist/agent.js +1 -0
  4. package/dist/commands-v2/handlers/project.js +88 -229
  5. package/dist/commands-v2/handlers/skill.js +10 -6
  6. package/dist/commands-v2/handlers/team.d.ts +19 -1
  7. package/dist/commands-v2/handlers/team.js +178 -3
  8. package/dist/compilr-diff-companion.vsix +0 -0
  9. package/dist/index.js +55 -3
  10. package/dist/multi-agent/agent-edit.d.ts +75 -0
  11. package/dist/multi-agent/agent-edit.js +84 -0
  12. package/dist/multi-agent/capability-loader.d.ts +15 -5
  13. package/dist/multi-agent/capability-loader.js +18 -8
  14. package/dist/multi-agent/custom-agents.d.ts +12 -0
  15. package/dist/multi-agent/custom-agents.js +22 -1
  16. package/dist/repl-helpers.d.ts +6 -1
  17. package/dist/repl-helpers.js +24 -10
  18. package/dist/repl-v2.d.ts +10 -0
  19. package/dist/repl-v2.js +43 -2
  20. package/dist/ui/overlay/impl/agent-edit-overlay-v2.d.ts +105 -0
  21. package/dist/ui/overlay/impl/agent-edit-overlay-v2.js +364 -0
  22. package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.d.ts +1 -8
  23. package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.js +16 -120
  24. package/dist/ui/overlay/impl/project-edit-overlay-v2.d.ts +2 -1
  25. package/dist/ui/overlay/impl/project-edit-overlay-v2.js +26 -19
  26. package/dist/ui/overlay/impl/skills-overlay-v2.d.ts +42 -2
  27. package/dist/ui/overlay/impl/skills-overlay-v2.js +238 -185
  28. package/dist/ui/overlay/impl/team-overlay-v2.d.ts +1 -2
  29. package/dist/ui/overlay/impl/team-overlay-v2.js +6 -9
  30. package/dist/ui/terminal-types.d.ts +8 -0
  31. package/package.json +7 -3
@@ -4,7 +4,6 @@
4
4
  * Multi-step wizard for creating custom agents.
5
5
  * Step 1: Basic Info (Agent ID, Display Name, Specialty, Personality)
6
6
  * Step 2: Tool Profile (select profile or customize tool groups)
7
- * Step 3: Skills (select which skills to enable)
8
7
  * Step 4: Model Tier (select fast/balanced/powerful)
9
8
  */
10
9
  import { BaseOverlayV2 } from '../../base/index.js';
@@ -20,7 +19,7 @@ interface FormField {
20
19
  value: string;
21
20
  error?: string;
22
21
  }
23
- type WizardStep = 'template-select' | 'basic' | 'tools' | 'skills' | 'tier' | 'prompt';
22
+ type WizardStep = 'template-select' | 'basic' | 'tools' | 'tier' | 'prompt';
24
23
  interface FormState {
25
24
  fields: FormField[];
26
25
  activeFieldIndex: number;
@@ -31,8 +30,6 @@ interface FormState {
31
30
  profileListIndex: number;
32
31
  groupListIndex: number;
33
32
  inGroupSelection: boolean;
34
- enabledSkills: Set<string>;
35
- skillListIndex: number;
36
33
  selectedModelTier: ModelTier;
37
34
  tierListIndex: number;
38
35
  systemPromptAddition: string;
@@ -67,7 +64,6 @@ export interface CustomAgentFormResult {
67
64
  personality?: string;
68
65
  systemPromptAddition?: string;
69
66
  toolConfig: ToolConfig;
70
- enabledSkills: string[];
71
67
  modelTier: ModelTier;
72
68
  };
73
69
  }
@@ -84,12 +80,9 @@ export declare class CustomAgentFormOverlayV2 extends BaseOverlayV2<FormState, C
84
80
  private renderBasicStep;
85
81
  private renderToolsStep;
86
82
  private renderGroupItem;
87
- private renderSkillsStep;
88
- private getAvailableTools;
89
83
  handleKey(key: KeyEvent): OverlayAction<CustomAgentFormResult>;
90
84
  private handleBasicStepKey;
91
85
  private handleToolsStepKey;
92
- private handleSkillsStepKey;
93
86
  private renderTierStep;
94
87
  private handleTierStepKey;
95
88
  private renderPromptStep;
@@ -4,11 +4,10 @@
4
4
  * Multi-step wizard for creating custom agents.
5
5
  * Step 1: Basic Info (Agent ID, Display Name, Specialty, Personality)
6
6
  * Step 2: Tool Profile (select profile or customize tool groups)
7
- * Step 3: Skills (select which skills to enable)
8
7
  * Step 4: Model Tier (select fast/balanced/powerful)
9
8
  */
10
9
  import { BaseOverlayV2, renderBorder, wrapText } from '../../base/index.js';
11
- import { validateAgentId, isAgentIdTaken, PREDEFINED_ROLE_IDS, TOOL_GROUPS, PROFILE_INFO, getGroupsByTier, createDefaultToolConfig, getToolsForProfile, getDefinedSkillNames, checkSkillCompatibility, getSkillsByCategory, } from '@compilr-dev/sdk';
10
+ import { validateAgentId, isAgentIdTaken, PREDEFINED_ROLE_IDS, TOOL_GROUPS, PROFILE_INFO, getGroupsByTier, createDefaultToolConfig, } from '@compilr-dev/sdk';
12
11
  import { MODEL_TIERS, TIER_INFO } from '../../../models/index.js';
13
12
  // Profile list for selection — derived from SDK's PROFILE_INFO
14
13
  const PROFILE_LIST = Object.keys(PROFILE_INFO);
@@ -67,8 +66,6 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
67
66
  profileListIndex: 0,
68
67
  groupListIndex: 0,
69
68
  inGroupSelection: false,
70
- enabledSkills: new Set(),
71
- skillListIndex: 0,
72
69
  selectedModelTier: 'balanced',
73
70
  tierListIndex: 1, // Default to balanced (index 1)
74
71
  templateListIndex: 0,
@@ -89,8 +86,6 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
89
86
  return this.renderBasicStep(context);
90
87
  case 'tools':
91
88
  return this.renderToolsStep(context);
92
- case 'skills':
93
- return this.renderSkillsStep(context);
94
89
  case 'tier':
95
90
  return this.renderTierStep(context);
96
91
  case 'prompt':
@@ -187,7 +182,7 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
187
182
  const border = renderBorder(context.width, s);
188
183
  // Header with step indicator
189
184
  lines.push(border);
190
- lines.push(` ${s.primaryBold('Create Custom Agent')} ${s.muted('- Step 1/5: Basic Info')}`);
185
+ lines.push(` ${s.primaryBold('Create Custom Agent')} ${s.muted('- Step 1/4: Basic Info')}`);
191
186
  lines.push(border);
192
187
  lines.push('');
193
188
  // Render each field
@@ -239,7 +234,7 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
239
234
  const border = renderBorder(context.width, s);
240
235
  // Header
241
236
  lines.push(border);
242
- lines.push(` ${s.primaryBold('Create Custom Agent')} ${s.muted('- Step 2/5: Tool Profile')}`);
237
+ lines.push(` ${s.primaryBold('Create Custom Agent')} ${s.muted('- Step 2/4: Tool Profile')}`);
243
238
  lines.push(border);
244
239
  lines.push('');
245
240
  if (!this.state.inGroupSelection) {
@@ -278,9 +273,15 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
278
273
  const groupId = direct[i];
279
274
  this.renderGroupItem(lines, groupId, i, s);
280
275
  }
281
- // Meta tools section
276
+ /*
277
+ The parenthetical used to read "(via use_tool)". That named an invocation mechanism
278
+ the person choosing tool groups cannot act on, and `use_tool` is not something they
279
+ will see in the agent's own tool list — the registry routes these transparently. The
280
+ section name already says which tier these belong to, so the mechanism is dropped
281
+ rather than restated.
282
+ */
282
283
  lines.push('');
283
- lines.push(` ${s.muted('─── Meta-Registry Tools (via use_tool) ───')}`);
284
+ lines.push(` ${s.muted('─── Meta-Registry Tools ───')}`);
284
285
  for (let i = 0; i < meta.length; i++) {
285
286
  const groupId = meta[i];
286
287
  this.renderGroupItem(lines, groupId, direct.length + i, s);
@@ -302,48 +303,6 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
302
303
  const readOnlyBadge = group.readOnly ? s.muted(' (read-only)') : '';
303
304
  lines.push(` ${marker} ${labelStyle(group.label)}${readOnlyBadge}`);
304
305
  }
305
- renderSkillsStep(context) {
306
- const s = context.styles;
307
- const lines = [];
308
- const border = renderBorder(context.width, s);
309
- // Header
310
- lines.push(border);
311
- lines.push(` ${s.primaryBold('Create Custom Agent')} ${s.muted('- Step 3/5: Skills')}`);
312
- lines.push(border);
313
- lines.push('');
314
- lines.push(` ${s.primary('Select skills to enable:')}`);
315
- lines.push(` ${s.muted('(Leave empty for all skills, or select specific skills)')}`);
316
- lines.push('');
317
- // Get available tools for compatibility check
318
- const availableTools = this.getAvailableTools();
319
- const categories = getSkillsByCategory();
320
- let globalIndex = 0;
321
- for (const [category, skills] of Object.entries(categories)) {
322
- lines.push(` ${s.muted(`─── ${category.charAt(0).toUpperCase() + category.slice(1)} ───`)}`);
323
- for (const skillName of skills) {
324
- const compatibility = checkSkillCompatibility(skillName, availableTools);
325
- const isSelected = globalIndex === this.state.skillListIndex;
326
- const isEnabled = this.state.enabledSkills.has(skillName);
327
- const isCompatible = compatibility.compatible;
328
- const marker = isEnabled ? s.success('[x]') : '[ ]';
329
- const labelStyle = isSelected ? s.primaryBold : s.secondary;
330
- // Soft warning for incompatible skills (not blocking)
331
- const warningBadge = !isCompatible
332
- ? s.warning(` ⚠ may need: ${compatibility.missingRequired.slice(0, 2).join(', ')}${compatibility.missingRequired.length > 2 ? '...' : ''}`)
333
- : '';
334
- lines.push(` ${marker} ${labelStyle(skillName)}${warningBadge}`);
335
- globalIndex++;
336
- }
337
- lines.push('');
338
- }
339
- lines.push(border);
340
- lines.push(s.muted(' ↑/↓ Navigate Space Toggle a Toggle All Enter Next ← Back Esc Cancel'));
341
- lines.push(border);
342
- return lines;
343
- }
344
- getAvailableTools() {
345
- return getToolsForProfile(this.state.selectedProfile, this.state.selectedProfile === 'custom' ? Array.from(this.state.customGroups) : undefined);
346
- }
347
306
  handleKey(key) {
348
307
  // Escape - cancel
349
308
  if (key.name === 'escape') {
@@ -360,8 +319,6 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
360
319
  return this.handleBasicStepKey(key);
361
320
  case 'tools':
362
321
  return this.handleToolsStepKey(key);
363
- case 'skills':
364
- return this.handleSkillsStepKey(key);
365
322
  case 'tier':
366
323
  return this.handleTierStepKey(key);
367
324
  case 'prompt':
@@ -495,8 +452,7 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
495
452
  this.state.groupListIndex = 0;
496
453
  }
497
454
  else {
498
- // Go to skills step
499
- this.state.currentStep = 'skills';
455
+ this.state.currentStep = 'tier';
500
456
  }
501
457
  return this.rerender();
502
458
  }
@@ -535,77 +491,19 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
535
491
  // Don't proceed without any groups
536
492
  return this.noAction();
537
493
  }
538
- // Go to skills step
539
- this.state.currentStep = 'skills';
494
+ this.state.currentStep = 'tier';
540
495
  return this.rerender();
541
496
  }
542
497
  }
543
498
  return this.noAction();
544
499
  }
545
- handleSkillsStepKey(key) {
546
- const skillNames = getDefinedSkillNames();
547
- const totalSkills = skillNames.length;
548
- // Left arrow - go back to tools step
549
- if (key.name === 'left') {
550
- this.state.currentStep = 'tools';
551
- return this.rerender();
552
- }
553
- // Up/Down - navigate skills
554
- if (key.name === 'up') {
555
- if (this.state.skillListIndex > 0) {
556
- this.state.skillListIndex--;
557
- }
558
- return this.rerender();
559
- }
560
- if (key.name === 'down') {
561
- if (this.state.skillListIndex < totalSkills - 1) {
562
- this.state.skillListIndex++;
563
- }
564
- return this.rerender();
565
- }
566
- // Space - toggle skill
567
- if (key.name === 'space') {
568
- const flatSkills = Object.values(getSkillsByCategory()).flat();
569
- const skillName = flatSkills[this.state.skillListIndex];
570
- // Allow toggling regardless of compatibility (soft warning only)
571
- if (this.state.enabledSkills.has(skillName)) {
572
- this.state.enabledSkills.delete(skillName);
573
- }
574
- else {
575
- this.state.enabledSkills.add(skillName);
576
- }
577
- return this.rerender();
578
- }
579
- // 'a' - toggle all skills
580
- if (key.char === 'a') {
581
- const flatSkills = Object.values(getSkillsByCategory()).flat();
582
- const allEnabled = flatSkills.every(skillName => this.state.enabledSkills.has(skillName));
583
- if (allEnabled) {
584
- // Clear all
585
- this.state.enabledSkills.clear();
586
- }
587
- else {
588
- // Enable all
589
- for (const skillName of flatSkills) {
590
- this.state.enabledSkills.add(skillName);
591
- }
592
- }
593
- return this.rerender();
594
- }
595
- // Enter - go to tier step
596
- if (key.name === 'return') {
597
- this.state.currentStep = 'tier';
598
- return this.rerender();
599
- }
600
- return this.noAction();
601
- }
602
500
  renderTierStep(context) {
603
501
  const s = context.styles;
604
502
  const lines = [];
605
503
  const border = renderBorder(context.width, s);
606
504
  // Header
607
505
  lines.push(border);
608
- lines.push(` ${s.primaryBold('Create Custom Agent')} ${s.muted('- Step 4/5: Model Tier')}`);
506
+ lines.push(` ${s.primaryBold('Create Custom Agent')} ${s.muted('- Step 3/4: Model Tier')}`);
609
507
  lines.push(border);
610
508
  lines.push('');
611
509
  lines.push(` ${s.primary('Select the default model tier for this agent:')}`);
@@ -634,9 +532,9 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
634
532
  return lines;
635
533
  }
636
534
  handleTierStepKey(key) {
637
- // Left arrow - go back to skills step
535
+ // Left arrow - go back to the tools step
638
536
  if (key.name === 'left') {
639
- this.state.currentStep = 'skills';
537
+ this.state.currentStep = 'tools';
640
538
  return this.rerender();
641
539
  }
642
540
  // Up/Down - navigate tiers
@@ -818,7 +716,6 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
818
716
  personality: getFieldValue('personality') || undefined,
819
717
  systemPromptAddition: this.state.systemPromptAddition.trim() || undefined,
820
718
  toolConfig: createDefaultToolConfig(),
821
- enabledSkills: [],
822
719
  modelTier: 'balanced', // Default tier
823
720
  },
824
721
  });
@@ -844,7 +741,6 @@ export class CustomAgentFormOverlayV2 extends BaseOverlayV2 {
844
741
  personality: getFieldValue('personality') || undefined,
845
742
  systemPromptAddition: this.state.systemPromptAddition.trim() || undefined,
846
743
  toolConfig,
847
- enabledSkills: Array.from(this.state.enabledSkills),
848
744
  modelTier: this.state.selectedModelTier,
849
745
  },
850
746
  });
@@ -7,8 +7,9 @@
7
7
  import { BaseOverlayV2 } from '../../base/index.js';
8
8
  import type { RenderContext, OverlayAction, KeyEvent } from '../types.js';
9
9
  import { type Project } from '../../../db/repositories/index.js';
10
+ import { type ProjectPatch } from '@compilr-dev/sdk';
10
11
  interface EditableField {
11
- key: 'displayName' | 'description' | 'gitRemote' | 'gitBranch' | 'path';
12
+ key: keyof ProjectPatch;
12
13
  label: string;
13
14
  value: string;
14
15
  placeholder?: string;
@@ -7,6 +7,7 @@
7
7
  import { BaseOverlayV2, renderBorder } from '../../base/index.js';
8
8
  import { projectRepository } from '../../../db/repositories/index.js';
9
9
  import * as terminal from '../../terminal.js';
10
+ import { buildProjectUpdate } from '@compilr-dev/sdk';
10
11
  // =============================================================================
11
12
  // Status Labels
12
13
  // =============================================================================
@@ -25,10 +26,21 @@ export class ProjectEditOverlayV2 extends BaseOverlayV2 {
25
26
  constructor(project) {
26
27
  super({
27
28
  project,
29
+ /*
30
+ ⚠️ THE SAME FIELDS DESKTOP EDITS (Phase 5 parity). This carried five; Desktop's document
31
+ carried eleven, so a project edited in the app showed a language and a framework the
32
+ terminal could neither see nor change. Parity is on the DATA MODEL — the presentation stays
33
+ a field list, because a terminal has no document.
34
+ */
28
35
  fields: [
29
36
  { key: 'displayName', label: 'Display Name', value: project.displayName, placeholder: 'Project display name' },
30
37
  { key: 'description', label: 'Description', value: project.description || '', placeholder: 'Brief description' },
31
38
  { key: 'path', label: 'Path', value: project.path || '', placeholder: '/path/to/project' },
39
+ { key: 'docsPath', label: 'Docs Path', value: project.docsPath || '', placeholder: 'defaults to the project folder' },
40
+ { key: 'language', label: 'Language', value: project.language || '', placeholder: 'TypeScript' },
41
+ { key: 'framework', label: 'Framework', value: project.framework || '', placeholder: 'React' },
42
+ { key: 'packageManager', label: 'Package Manager', value: project.packageManager || '', placeholder: 'npm' },
43
+ { key: 'runtimeVersion', label: 'Runtime', value: project.runtimeVersion || '', placeholder: '22' },
32
44
  { key: 'gitRemote', label: 'Git Remote', value: project.gitRemote || '', placeholder: 'https://github.com/...' },
33
45
  { key: 'gitBranch', label: 'Git Branch', value: project.gitBranch || '', placeholder: 'main' },
34
46
  ],
@@ -163,28 +175,23 @@ export class ProjectEditOverlayV2 extends BaseOverlayV2 {
163
175
  return this.noAction();
164
176
  }
165
177
  saveAndClose() {
166
- // Build update object from fields
167
- const updates = {};
178
+ /*
179
+ ⚠️ THE SDK'S MAPPING, NOT A SECOND ONE. This used to hand-write its own snake_case mapping,
180
+ and it had drifted from Desktop's: `field.value || undefined` turned an empty string into
181
+ "leave alone", so a git remote could be SET here but never CLEARED. An empty field now means
182
+ what it looks like it means.
183
+ */
184
+ const patch = {};
168
185
  for (const field of this.state.fields) {
169
- if (field.key === 'displayName') {
170
- updates.display_name = field.value || undefined;
171
- }
172
- else if (field.key === 'description') {
173
- updates.description = field.value || undefined;
174
- }
175
- else if (field.key === 'gitRemote') {
176
- updates.git_remote = field.value || undefined;
177
- }
178
- else if (field.key === 'gitBranch') {
179
- updates.git_branch = field.value || undefined;
180
- }
181
- else {
182
- // field.key === 'path'
183
- updates.path = field.value || undefined;
184
- }
186
+ patch[field.key] = field.value;
187
+ }
188
+ const built = buildProjectUpdate(patch);
189
+ if (!built.ok) {
190
+ this.state.error = built.error;
191
+ return this.rerender();
185
192
  }
186
193
  try {
187
- projectRepository.update(this.state.project.id, updates);
194
+ projectRepository.update(this.state.project.id, built.input);
188
195
  return this.close({ saved: true, projectId: this.state.project.id });
189
196
  }
190
197
  catch (err) {
@@ -15,14 +15,21 @@
15
15
  * Spec: project-docs/00-requirements/compilr-dev-cli/skills-overlay-spec.md
16
16
  */
17
17
  import { TabbedListOverlayV2, BaseScreen } from '../../base/index.js';
18
- import { type CustomSkill } from '@compilr-dev/sdk';
18
+ import { type SkillReachability, type CustomSkill } from '@compilr-dev/sdk';
19
19
  import { type SkillScope } from '../../../utils/skill-paths.js';
20
20
  /** Unified item for the list — custom skills have full data, built-in have name+description only */
21
21
  interface SkillItem {
22
22
  name: string;
23
23
  description: string;
24
24
  scope: 'project' | 'user' | 'sdk' | 'binding';
25
- enabled: boolean;
25
+ /**
26
+ * ⚠️ THE TWO ANTHROPIC SWITCHES, NOT `enabled`. This used to be `skill.enabled !== false`, and
27
+ * `enabled` is not part of the format — zero of 50 Anthropic-authored skills carry it. A skill
28
+ * shelved in Desktop writes `user-invocable: false` and no `enabled` key at all, so the old
29
+ * expression read it back as ON: the CLI showed a shelved skill as live, and the resolver (which
30
+ * already uses skillReachability) disagreed with the list in front of the user.
31
+ */
32
+ reach: SkillReachability;
26
33
  /** Validation issues (empty = valid) */
27
34
  issues: string[];
28
35
  /** Full CustomSkill data (null for built-in) */
@@ -45,17 +52,38 @@ interface SkillItem {
45
52
  export interface SkillsOverlayV2Options {
46
53
  /** Project root path (for project-scoped skills) */
47
54
  projectPath?: string;
55
+ /**
56
+ * Extra prompt sources, supplied by the app layer because that is where they are configured.
57
+ * The same set passed to the resolver, so this tab and `getSkillPrompt` cannot disagree
58
+ * about what exists.
59
+ */
60
+ skillSources?: import('@compilr-dev/sdk').SkillSources;
48
61
  /** Callback to open the skill detail overlay (view/edit/diff). Returns true if modified. */
49
62
  onOpenDetail?: (filePath: string, skillName: string, scope: string, forkedFrom?: import('@compilr-dev/sdk').ForkedFromMarker, boundCommands?: string[]) => Promise<boolean>;
50
63
  }
51
64
  export interface SkillsOverlayV2Result {
52
65
  dismissed: boolean;
53
66
  }
67
+ /**
68
+ * The shipped macros this tab offers.
69
+ *
70
+ * ⚠️ IT USED TO OFFER EIGHT IT CANNOT RUN. This walked `platformMacros` directly and added every
71
+ * one, including the canvas family — which `getSkillPrompt` REFUSES, because a terminal cannot
72
+ * draw a canvas. So the Built-in tab listed `canvas`, `infographic`, `carousel`, `board`,
73
+ * `canvas-styles` and the three reference ones, and selecting any of them got nothing. That is
74
+ * the same "offered, then answers Unknown command" defect the CLI had already fixed for
75
+ * disabled skills, in a second place nobody checked.
76
+ *
77
+ * It now asks the SDK, declaring what this host can render. The resolver's refusal and this
78
+ * list are therefore two consequences of one rule rather than two rules that can disagree.
79
+ */
80
+ export declare function loadBuiltinMacros(projectPath?: string, sources?: import('@compilr-dev/sdk').SkillSources): SkillItem[];
54
81
  export declare class SkillsOverlayV2 extends TabbedListOverlayV2<SkillItem, SkillsOverlayV2Result> {
55
82
  readonly type: "inline";
56
83
  readonly id = "skills-overlay-v2";
57
84
  private allItems;
58
85
  private readonly projectPath?;
86
+ private readonly skillSources?;
59
87
  private readonly onOpenDetail?;
60
88
  constructor(options: SkillsOverlayV2Options);
61
89
  /**
@@ -73,6 +101,18 @@ export declare class SkillsOverlayV2 extends TabbedListOverlayV2<SkillItem, Skil
73
101
  pushScreen?: BaseScreen;
74
102
  };
75
103
  private createSkill;
104
+ /**
105
+ * Shelve a skill, or bring it back.
106
+ *
107
+ * ⚠️ WRITES THE TWO ANTHROPIC SWITCHES AND REMOVES THE LEGACY KEY (D-1), THROUGH THE SDK'S
108
+ * PATCHER RATHER THAN A REGEX (D-2). The old version rewrote frontmatter line by line, which
109
+ * destroys comments — measured on our own template: 17 lines to 7, all 9 comment lines to 0.
110
+ *
111
+ * One key for two switches is lossy by construction: a skill set to "agents only" in Desktop is
112
+ * shelved and then restored to BOTH. That is why the list renders the real state beside the name
113
+ * — the flattening is visible, not silent — and why the two-switch editor lives in the host that
114
+ * has a document to put it in.
115
+ */
76
116
  private toggleSkill;
77
117
  private deleteSkill;
78
118
  private renameSkill;