@forwardimpact/pathway 0.24.0 → 0.25.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.
package/README.md CHANGED
@@ -14,8 +14,8 @@ web experience and command line.
14
14
 
15
15
  - **Web application** — Interactive browser for jobs, skills, and career paths
16
16
  - **CLI tools** — Command-line access to all functionality
17
- - **Agent teams** — Generate VS Code Custom Agent teams (`.agent.md`) and skills
18
- (`SKILL.md`)
17
+ - **Agent teams** — Generate Claude Code agent teams (`.claude/agents/`) and
18
+ skills (`.claude/skills/`)
19
19
  - **Interview prep** — Build interview question sets by role
20
20
  - **Static site** — Export everything as a static site
21
21
 
@@ -30,7 +30,7 @@ npx fit-pathway skill --list
30
30
  npx fit-pathway job software_engineering senior --track=platform
31
31
 
32
32
  # Generate agent teams and skills
33
- npx fit-pathway agent software_engineering --track=platform --output=./.github/agents
33
+ npx fit-pathway agent software_engineering --track=platform --output=.
34
34
  ```
35
35
 
36
36
  ## CLI Commands
@@ -30,11 +30,13 @@
30
30
  */
31
31
 
32
32
  import { join, resolve, dirname } from "path";
33
- import { existsSync } from "fs";
34
- import { homedir } from "os";
35
33
  import { fileURLToPath } from "url";
34
+ import fs from "fs/promises";
35
+ import { homedir } from "os";
36
36
  import { createDataLoader } from "@forwardimpact/map/loader";
37
37
  import { validateAllData } from "@forwardimpact/map/validation";
38
+ import { Finder } from "@forwardimpact/libutil";
39
+ import { createLogger } from "@forwardimpact/libtelemetry";
38
40
  import { formatError } from "../src/lib/cli-output.js";
39
41
  import { createTemplateLoader } from "@forwardimpact/libtemplate";
40
42
 
@@ -336,50 +338,6 @@ function printHelp() {
336
338
  console.log(HELP_TEXT);
337
339
  }
338
340
 
339
- /**
340
- * Resolve the data directory path.
341
- * @param {Object} options - Parsed command options
342
- * @returns {string} Resolved absolute path to data directory
343
- */
344
- function resolveDataPath(options) {
345
- if (options.data) {
346
- return resolve(options.data);
347
- }
348
-
349
- if (process.env.PATHWAY_DATA) {
350
- return resolve(process.env.PATHWAY_DATA);
351
- }
352
-
353
- const homeData = join(homedir(), ".fit", "pathway", "data");
354
- if (existsSync(homeData)) {
355
- return homeData;
356
- }
357
-
358
- const cwdDataPathway = join(process.cwd(), "data/pathway");
359
- if (existsSync(cwdDataPathway)) {
360
- return cwdDataPathway;
361
- }
362
-
363
- const cwdExamplesPathway = join(process.cwd(), "examples/pathway");
364
- if (existsSync(cwdExamplesPathway)) {
365
- return cwdExamplesPathway;
366
- }
367
-
368
- const cwdData = join(process.cwd(), "data");
369
- if (existsSync(cwdData)) {
370
- return cwdData;
371
- }
372
-
373
- const cwdExamples = join(process.cwd(), "examples");
374
- if (existsSync(cwdExamples)) {
375
- return cwdExamples;
376
- }
377
-
378
- throw new Error(
379
- "No data directory found. Create ./data/pathway/ or use --data=<path>",
380
- );
381
- }
382
-
383
341
  /**
384
342
  * Main CLI entry point
385
343
  */
@@ -404,7 +362,20 @@ async function main() {
404
362
  process.exit(0);
405
363
  }
406
364
 
407
- const dataDir = resolveDataPath(options);
365
+ let dataDir;
366
+ if (options.data) {
367
+ dataDir = resolve(options.data);
368
+ } else {
369
+ const logger = createLogger("pathway");
370
+ const finder = new Finder(fs, logger, process);
371
+ try {
372
+ dataDir = join(finder.findData("data", homedir()), "pathway");
373
+ } catch {
374
+ throw new Error(
375
+ "No data directory found. Use --data=<path> to specify location.",
376
+ );
377
+ }
378
+ }
408
379
 
409
380
  if (command === "dev") {
410
381
  await runDevCommand({ dataDir, options });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forwardimpact/pathway",
3
- "version": "0.24.0",
3
+ "version": "0.25.1",
4
4
  "description": "Career progression web app and CLI for exploring roles and generating agent teams",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -41,12 +41,12 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@forwardimpact/map": "^0.14.0",
44
- "@forwardimpact/libskill": "^3.0.0",
44
+ "@forwardimpact/libskill": "^4.0.0",
45
45
  "@forwardimpact/libtemplate": "^0.2.0",
46
46
  "@forwardimpact/libui": "^1.0.0",
47
47
  "mustache": "^4.2.0",
48
- "simple-icons": "^16.7.0",
49
- "yaml": "^2.3.4"
48
+ "simple-icons": "^16.13.0",
49
+ "yaml": "^2.8.3"
50
50
  },
51
51
  "engines": {
52
52
  "node": ">=18.0.0"
@@ -2,7 +2,8 @@
2
2
  * Agent Command
3
3
  *
4
4
  * CLI command for generating AI coding agent configurations
5
- * from Engineering Pathway data.
5
+ * from Engineering Pathway data. Outputs follow the Claude Code
6
+ * agent specification.
6
7
  *
7
8
  * All agents are stage-specific. Use --stage for a single stage
8
9
  * or --all-stages (default) for all stages.
@@ -26,7 +27,6 @@
26
27
  import { writeFile, mkdir, readFile } from "fs/promises";
27
28
  import { join, dirname } from "path";
28
29
  import { existsSync } from "fs";
29
- import { stringify as stringifyYaml } from "yaml";
30
30
  import { createDataLoader } from "@forwardimpact/map/loader";
31
31
  import {
32
32
  generateStageAgentProfile,
@@ -36,7 +36,6 @@ import {
36
36
  deriveAgentSkills,
37
37
  generateSkillMarkdown,
38
38
  deriveToolkit,
39
- buildAgentIndex,
40
39
  getDisciplineAbbreviation,
41
40
  toKebabCase,
42
41
  } from "@forwardimpact/libskill";
@@ -58,13 +57,13 @@ async function ensureDir(filePath) {
58
57
  }
59
58
 
60
59
  /**
61
- * Generate VS Code settings file with required settings
60
+ * Generate Claude Code settings file
62
61
  * Merges with existing settings if file exists
63
62
  * @param {string} baseDir - Base output directory
64
- * @param {Object} vscodeSettings - Settings loaded from data
63
+ * @param {Object} claudeCodeSettings - Settings loaded from data
65
64
  */
66
- async function generateVSCodeSettings(baseDir, vscodeSettings) {
67
- const settingsPath = join(baseDir, ".vscode", "settings.json");
65
+ async function generateClaudeCodeSettings(baseDir, claudeCodeSettings) {
66
+ const settingsPath = join(baseDir, ".claude", "settings.json");
68
67
 
69
68
  let settings = {};
70
69
  if (existsSync(settingsPath)) {
@@ -72,7 +71,7 @@ async function generateVSCodeSettings(baseDir, vscodeSettings) {
72
71
  settings = JSON.parse(content);
73
72
  }
74
73
 
75
- const merged = { ...settings, ...vscodeSettings };
74
+ const merged = { ...settings, ...claudeCodeSettings };
76
75
 
77
76
  await ensureDir(settingsPath);
78
77
  await writeFile(
@@ -83,64 +82,6 @@ async function generateVSCodeSettings(baseDir, vscodeSettings) {
83
82
  console.log(formatSuccess(`Updated: ${settingsPath}`));
84
83
  }
85
84
 
86
- /**
87
- * Generate devcontainer.json from template with VS Code settings embedded
88
- * @param {string} baseDir - Base output directory
89
- * @param {Object} devcontainerConfig - Devcontainer config loaded from data
90
- * @param {Object} vscodeSettings - VS Code settings to embed in customizations
91
- */
92
- async function generateDevcontainer(
93
- baseDir,
94
- devcontainerConfig,
95
- vscodeSettings,
96
- ) {
97
- if (!devcontainerConfig || Object.keys(devcontainerConfig).length === 0) {
98
- return;
99
- }
100
-
101
- const devcontainerPath = join(baseDir, ".devcontainer", "devcontainer.json");
102
-
103
- // Build devcontainer.json with VS Code settings embedded
104
- const devcontainer = {
105
- ...devcontainerConfig,
106
- customizations: {
107
- vscode: {
108
- settings: vscodeSettings,
109
- },
110
- },
111
- };
112
-
113
- await ensureDir(devcontainerPath);
114
- await writeFile(
115
- devcontainerPath,
116
- JSON.stringify(devcontainer, null, 2) + "\n",
117
- "utf-8",
118
- );
119
- console.log(formatSuccess(`Created: ${devcontainerPath}`));
120
- }
121
-
122
- /**
123
- * Generate GitHub Actions workflow for Copilot Coding Agent setup steps
124
- * @param {string} baseDir - Base output directory
125
- * @param {Object|null} copilotSetupSteps - Workflow config loaded from data
126
- */
127
- async function generateCopilotSetupSteps(baseDir, copilotSetupSteps) {
128
- if (!copilotSetupSteps) {
129
- return;
130
- }
131
-
132
- const workflowPath = join(
133
- baseDir,
134
- ".github",
135
- "workflows",
136
- "copilot-setup-steps.yml",
137
- );
138
-
139
- await ensureDir(workflowPath);
140
- await writeFile(workflowPath, stringifyYaml(copilotSetupSteps), "utf-8");
141
- console.log(formatSuccess(`Created: ${workflowPath}`));
142
- }
143
-
144
85
  /**
145
86
  * Show agent summary with stats
146
87
  * @param {Object} data - Pathway data
@@ -258,7 +199,7 @@ function listAgentCombinations(data, agentData, verbose = false) {
258
199
  * @param {string} template - Mustache template for agent profile
259
200
  */
260
201
  async function writeProfile(profile, baseDir, template) {
261
- const profilePath = join(baseDir, ".github", "agents", profile.filename);
202
+ const profilePath = join(baseDir, ".claude", "agents", profile.filename);
262
203
  const profileContent = formatAgentProfile(profile, template);
263
204
  await ensureDir(profilePath);
264
205
  await writeFile(profilePath, profileContent, "utf-8");
@@ -451,15 +392,6 @@ export async function runAgentCommand({
451
392
 
452
393
  const baseDir = options.output || ".";
453
394
 
454
- // Build agent index for all valid combinations
455
- const agentIndex = buildAgentIndex({
456
- disciplines: data.disciplines,
457
- tracks: data.tracks,
458
- stages: data.stages,
459
- agentDisciplines: agentData.disciplines,
460
- agentTracks: agentData.tracks,
461
- });
462
-
463
395
  // Common params for stage-based generation
464
396
  const stageParams = {
465
397
  discipline: humanDiscipline,
@@ -471,7 +403,6 @@ export async function runAgentCommand({
471
403
  agentDiscipline,
472
404
  agentTrack,
473
405
  stages: data.stages,
474
- agentIndex,
475
406
  };
476
407
 
477
408
  // Handle --stage flag for single stage agent
@@ -508,13 +439,7 @@ export async function runAgentCommand({
508
439
  }
509
440
 
510
441
  await writeProfile(profile, baseDir, agentTemplate);
511
- await generateVSCodeSettings(baseDir, agentData.vscodeSettings);
512
- await generateDevcontainer(
513
- baseDir,
514
- agentData.devcontainer,
515
- agentData.vscodeSettings,
516
- );
517
- await generateCopilotSetupSteps(baseDir, agentData.copilotSetupSteps);
442
+ await generateClaudeCodeSettings(baseDir, agentData.claudeCodeSettings);
518
443
  console.log("");
519
444
  console.log(
520
445
  formatSuccess(`Generated stage agent: ${profile.frontmatter.name}`),
@@ -522,8 +447,7 @@ export async function runAgentCommand({
522
447
  return;
523
448
  }
524
449
 
525
- // Default behavior: generate all stage agents (or single stage if --stage specified)
526
- // No generic agents - all agents are stage-specific
450
+ // Default behavior: generate all stage agents
527
451
  const profiles = [];
528
452
 
529
453
  // Generate all stage agents
@@ -603,13 +527,7 @@ export async function runAgentCommand({
603
527
  await writeProfile(profile, baseDir, agentTemplate);
604
528
  }
605
529
  const fileCount = await writeSkills(skillFiles, baseDir, skillTemplates);
606
- await generateVSCodeSettings(baseDir, agentData.vscodeSettings);
607
- await generateDevcontainer(
608
- baseDir,
609
- agentData.devcontainer,
610
- agentData.vscodeSettings,
611
- );
612
- await generateCopilotSetupSteps(baseDir, agentData.copilotSetupSteps);
530
+ await generateClaudeCodeSettings(baseDir, agentData.claudeCodeSettings);
613
531
 
614
532
  console.log("");
615
533
  console.log(formatSuccess(`Generated ${profiles.length} agents:`));
@@ -160,6 +160,24 @@ ${framework.emojiIcon} Generating ${framework.title} static site...
160
160
  });
161
161
  console.log(` ✓ ui/lib + ui/css`);
162
162
 
163
+ // Copy vendor dependencies for offline usage
164
+ console.log("📦 Copying vendor dependencies...");
165
+ const vendorDir = join(outputDir, "vendor");
166
+ await mkdir(vendorDir, { recursive: true });
167
+
168
+ // mustache (ESM module)
169
+ const mustacheSrc = fileURLToPath(import.meta.resolve("mustache"));
170
+ const mustacheMjs = join(dirname(mustacheSrc), "mustache.mjs");
171
+ await cp(mustacheMjs, join(vendorDir, "mustache.mjs"));
172
+ console.log(" ✓ vendor/mustache.mjs");
173
+
174
+ // yaml (browser ESM build — not in package exports, resolve via filesystem)
175
+ // import.meta.resolve("yaml") → .../yaml/dist/index.js, go up two levels
176
+ const yamlPkg = dirname(dirname(fileURLToPath(import.meta.resolve("yaml"))));
177
+ const yamlBrowserDist = join(yamlPkg, "browser", "dist");
178
+ await cp(yamlBrowserDist, join(vendorDir, "yaml"), { recursive: true });
179
+ console.log(" ✓ vendor/yaml/");
180
+
163
181
  // Copy data directory (dereference symlinks to copy actual content)
164
182
  console.log("📁 Copying data files...");
165
183
  const dataOutputDir = join(outputDir, "data");
@@ -34,10 +34,19 @@ const mapLibDir = resolvePackageLib("@forwardimpact/map");
34
34
  const modelLibDir = resolvePackageLib("@forwardimpact/libskill");
35
35
  const uiLibDir = resolvePackageLib("@forwardimpact/libui");
36
36
 
37
+ // Vendor dependencies — mirror the paths that build.js copies to vendor/
38
+ const mustacheDir = dirname(fileURLToPath(import.meta.resolve("mustache")));
39
+ const yamlBrowserDir = join(
40
+ dirname(dirname(fileURLToPath(import.meta.resolve("yaml")))),
41
+ "browser",
42
+ "dist",
43
+ );
44
+
37
45
  const MIME_TYPES = {
38
46
  ".html": "text/html; charset=utf-8",
39
47
  ".css": "text/css; charset=utf-8",
40
48
  ".js": "application/javascript; charset=utf-8",
49
+ ".mjs": "application/javascript; charset=utf-8",
41
50
  ".yaml": "text/yaml; charset=utf-8",
42
51
  ".yml": "text/yaml; charset=utf-8",
43
52
  ".json": "application/json; charset=utf-8",
@@ -149,6 +158,12 @@ export async function runDevCommand({ dataDir, options }) {
149
158
  } else if (pathname.startsWith("/ui/css/")) {
150
159
  // Serve @forwardimpact/libui package CSS files
151
160
  filePath = join(uiLibDir, "css", pathname.slice(8));
161
+ } else if (pathname === "/vendor/mustache.mjs") {
162
+ // Serve vendored mustache ESM module
163
+ filePath = join(mustacheDir, "mustache.mjs");
164
+ } else if (pathname.startsWith("/vendor/yaml/")) {
165
+ // Serve vendored yaml browser ESM build
166
+ filePath = join(yamlBrowserDir, pathname.slice(13));
152
167
  } else if (pathname === "/" || pathname === "") {
153
168
  // Serve index.html for root
154
169
  filePath = join(publicDir, "index.html");
@@ -9,7 +9,7 @@
9
9
  import { cp, mkdir, rm, readFile, writeFile, access } from "fs/promises";
10
10
  import { join } from "path";
11
11
  import { homedir } from "os";
12
- import { execFileSync, execSync } from "child_process";
12
+ import { execFileSync } from "child_process";
13
13
  import { createDataLoader } from "@forwardimpact/map/loader";
14
14
 
15
15
  const INSTALL_DIR = join(homedir(), ".fit", "pathway");
@@ -112,9 +112,13 @@ export async function runUpdateCommand({ dataDir: _dataDir, options }) {
112
112
  // 6. Update global pathway package if version changed
113
113
  if (oldVersion !== newVersion) {
114
114
  console.log(` Updating pathway ${oldVersion} → ${newVersion}...`);
115
- execSync(`npm install -g @forwardimpact/pathway@${newVersion}`, {
116
- stdio: "ignore",
117
- });
115
+ execFileSync(
116
+ "npm",
117
+ ["install", "-g", `@forwardimpact/pathway@${newVersion}`],
118
+ {
119
+ stdio: "ignore",
120
+ },
121
+ );
118
122
  console.log(" ✓ Global package updated");
119
123
  }
120
124
 
@@ -22,17 +22,24 @@ import { SKILL_PROFICIENCY_ORDER } from "@forwardimpact/map/levels";
22
22
  import { truncate } from "../formatters/shared.js";
23
23
 
24
24
  /**
25
- * Sort skills by level descending (expert first), then alphabetically
25
+ * Sort skills by capability group order, then by level descending within each group
26
26
  * @param {SkillMatrixItem[]} skills
27
+ * @param {string[]} capabilityOrder - Ordered capability IDs
27
28
  * @returns {SkillMatrixItem[]}
28
29
  */
29
- function sortByLevelDescending(skills) {
30
+ function sortByCapabilityThenLevel(skills, capabilityOrder) {
31
+ const orderMap = new Map(capabilityOrder.map((id, i) => [id, i]));
30
32
  return [...skills].sort((a, b) => {
31
- const levelA = SKILL_PROFICIENCY_ORDER.indexOf(a.level);
32
- const levelB = SKILL_PROFICIENCY_ORDER.indexOf(b.level);
33
- if (levelB !== levelA) {
34
- return levelB - levelA;
35
- }
33
+ const capA = orderMap.has(a.capability)
34
+ ? orderMap.get(a.capability)
35
+ : capabilityOrder.length;
36
+ const capB = orderMap.has(b.capability)
37
+ ? orderMap.get(b.capability)
38
+ : capabilityOrder.length;
39
+ if (capA !== capB) return capA - capB;
40
+ const levelA = SKILL_PROFICIENCY_ORDER.indexOf(a.proficiency);
41
+ const levelB = SKILL_PROFICIENCY_ORDER.indexOf(b.proficiency);
42
+ if (levelB !== levelA) return levelB - levelA;
36
43
  return a.skillName.localeCompare(b.skillName);
37
44
  });
38
45
  }
@@ -40,14 +47,19 @@ function sortByLevelDescending(skills) {
40
47
  /**
41
48
  * Create a skill matrix table
42
49
  * @param {SkillMatrixItem[]} skillMatrix - Skill matrix entries
50
+ * @param {Object} [options]
51
+ * @param {string[]} [options.capabilityOrder] - Capability IDs in desired display order
43
52
  * @returns {HTMLElement}
44
53
  */
45
- export function createSkillMatrix(skillMatrix) {
54
+ export function createSkillMatrix(skillMatrix, options = {}) {
46
55
  if (!skillMatrix || skillMatrix.length === 0) {
47
56
  return div({ className: "empty-state" }, "No skills in matrix");
48
57
  }
49
58
 
50
- const sortedSkills = sortByLevelDescending(skillMatrix);
59
+ const { capabilityOrder } = options;
60
+ const sortedSkills = capabilityOrder
61
+ ? sortByCapabilityThenLevel(skillMatrix, capabilityOrder)
62
+ : [...skillMatrix];
51
63
 
52
64
  const rows = sortedSkills.map((skill) => {
53
65
  const levelIndex = getSkillProficiencyIndex(skill.proficiency);
@@ -17,14 +17,14 @@ import { getStageEmoji } from "../stage/shared.js";
17
17
  * @param {Object} deployment.profile - Agent profile
18
18
  * @param {Array} deployment.skills - Agent skills
19
19
  * @param {Array} [deployment.roleAgents] - Role variant agents (plan, review)
20
- * @param {Object} [deployment.vscodeSettings] - VS Code settings to include in download
20
+ * @param {Object} [deployment.claudeCodeSettings] - Claude Code settings to include in download
21
21
  * @returns {HTMLElement}
22
22
  */
23
23
  export function agentDeploymentToDOM({
24
24
  profile,
25
25
  skills,
26
26
  roleAgents = [],
27
- vscodeSettings = {},
27
+ claudeCodeSettings = {},
28
28
  }) {
29
29
  const profileContent = formatAgentProfile(profile);
30
30
  const agentName = profile.frontmatter.name;
@@ -37,7 +37,7 @@ export function agentDeploymentToDOM({
37
37
  profile,
38
38
  skills,
39
39
  roleAgents,
40
- vscodeSettings,
40
+ claudeCodeSettings,
41
41
  agentName,
42
42
  ),
43
43
 
@@ -90,7 +90,7 @@ export function agentDeploymentToDOM({
90
90
  * @param {Object} profile - Agent profile
91
91
  * @param {Array} skills - Agent skills
92
92
  * @param {Array} roleAgents - Role variant agents
93
- * @param {Object} vscodeSettings - VS Code settings to include
93
+ * @param {Object} claudeCodeSettings - Claude Code settings to include
94
94
  * @param {string} agentName - Agent name for zip filename
95
95
  * @returns {HTMLElement}
96
96
  */
@@ -98,7 +98,7 @@ function createDownloadButton(
98
98
  profile,
99
99
  skills,
100
100
  roleAgents,
101
- vscodeSettings,
101
+ claudeCodeSettings,
102
102
  agentName,
103
103
  ) {
104
104
  const btn = button(
@@ -115,7 +115,7 @@ function createDownloadButton(
115
115
  profile,
116
116
  skills,
117
117
  roleAgents,
118
- vscodeSettings,
118
+ claudeCodeSettings,
119
119
  agentName,
120
120
  );
121
121
  } finally {
@@ -167,28 +167,28 @@ function createRoleAgentCard(agent) {
167
167
  * @param {Object} profile - Agent profile
168
168
  * @param {Array} skills - Agent skills
169
169
  * @param {Array} roleAgents - Role variant agents
170
- * @param {Object} vscodeSettings - VS Code settings to include
170
+ * @param {Object} claudeCodeSettings - Claude Code settings to include
171
171
  * @param {string} agentName - Agent name for zip filename
172
172
  */
173
173
  async function downloadAllAsZip(
174
174
  profile,
175
175
  skills,
176
176
  roleAgents,
177
- vscodeSettings,
177
+ claudeCodeSettings,
178
178
  agentName,
179
179
  ) {
180
180
  // Dynamically import JSZip
181
181
  const JSZip = await importJSZip();
182
182
  const zip = new JSZip();
183
183
 
184
- // Add main profile to .github/agents/ folder
184
+ // Add main profile to .claude/agents/ folder
185
185
  const profileContent = formatAgentProfile(profile);
186
- zip.file(`.github/agents/${profile.filename}`, profileContent);
186
+ zip.file(`.claude/agents/${profile.filename}`, profileContent);
187
187
 
188
- // Add role agent profiles to .github/agents/ folder
188
+ // Add role agent profiles to .claude/agents/ folder
189
189
  for (const roleAgent of roleAgents) {
190
190
  const roleContent = formatAgentProfile(roleAgent);
191
- zip.file(`.github/agents/${roleAgent.filename}`, roleContent);
191
+ zip.file(`.claude/agents/${roleAgent.filename}`, roleContent);
192
192
  }
193
193
 
194
194
  // Add skills to .claude/skills/ folder
@@ -197,11 +197,11 @@ async function downloadAllAsZip(
197
197
  zip.file(`.claude/skills/${skill.dirname}/SKILL.md`, skillContent);
198
198
  }
199
199
 
200
- // Add VS Code settings for multi-agent features
201
- if (Object.keys(vscodeSettings).length > 0) {
200
+ // Add Claude Code settings
201
+ if (Object.keys(claudeCodeSettings).length > 0) {
202
202
  zip.file(
203
- ".vscode/settings.json",
204
- JSON.stringify(vscodeSettings, null, 2) + "\n",
203
+ ".claude/settings.json",
204
+ JSON.stringify(claudeCodeSettings, null, 2) + "\n",
205
205
  );
206
206
  }
207
207
 
@@ -235,13 +235,12 @@ async function importJSZip() {
235
235
  * @param {Object} profile - Generated profile with frontmatter and body
236
236
  * @param {Object} options - Options
237
237
  * @param {Array} [options.stages] - All stages for emoji lookup
238
- * @param {Object} [options.vscodeSettings] - VS Code settings for download
238
+ * @param {Object} [options.claudeCodeSettings] - Claude Code settings for download
239
239
  * @returns {HTMLElement}
240
240
  */
241
241
  export function stageAgentToDOM(stageAgent, profile, options = {}) {
242
- const { vscodeSettings = {}, stages = [] } = options;
243
- const { stage, tools, handoffs, constraints, checklist, derivedSkills } =
244
- stageAgent;
242
+ const { claudeCodeSettings = {}, stages = [] } = options;
243
+ const { stage, tools, constraints, checklist, derivedSkills } = stageAgent;
245
244
  const stageEmoji = getStageEmoji(stages, stage.id);
246
245
  const profileContent = formatAgentProfile(profile);
247
246
 
@@ -287,25 +286,6 @@ export function stageAgentToDOM(stageAgent, profile, options = {}) {
287
286
  )
288
287
  : null,
289
288
 
290
- // Handoffs section
291
- handoffs.length > 0
292
- ? section(
293
- { className: "agent-section" },
294
- h3({}, "Handoffs"),
295
- div(
296
- { className: "handoff-buttons" },
297
- ...handoffs.map((h) => {
298
- const targetEmoji = getStageEmoji(stages, h.target);
299
- return div(
300
- { className: "handoff-button-preview" },
301
- span({ className: "handoff-icon" }, targetEmoji),
302
- span({ className: "handoff-label" }, h.label),
303
- );
304
- }),
305
- ),
306
- )
307
- : null,
308
-
309
289
  // Checklist section
310
290
  checklist.length > 0
311
291
  ? section(
@@ -353,7 +333,7 @@ export function stageAgentToDOM(stageAgent, profile, options = {}) {
353
333
  ),
354
334
 
355
335
  // Download button
356
- createStageAgentDownloadButton(profile, vscodeSettings),
336
+ createStageAgentDownloadButton(profile, claudeCodeSettings),
357
337
  );
358
338
  }
359
339
 
@@ -387,10 +367,10 @@ function createChecklistPreview(checklist) {
387
367
  /**
388
368
  * Create download button for stage agent
389
369
  * @param {Object} profile - Agent profile
390
- * @param {Object} vscodeSettings - VS Code settings
370
+ * @param {Object} claudeCodeSettings - Claude Code settings
391
371
  * @returns {HTMLElement}
392
372
  */
393
- function createStageAgentDownloadButton(profile, vscodeSettings) {
373
+ function createStageAgentDownloadButton(profile, claudeCodeSettings) {
394
374
  const btn = button(
395
375
  { className: "btn btn-primary download-all-btn" },
396
376
  "📥 Download Agent Profile",
@@ -406,13 +386,13 @@ function createStageAgentDownloadButton(profile, vscodeSettings) {
406
386
 
407
387
  // Add profile
408
388
  const profileContent = formatAgentProfile(profile);
409
- zip.file(`.github/agents/${profile.filename}`, profileContent);
389
+ zip.file(`.claude/agents/${profile.filename}`, profileContent);
410
390
 
411
- // Add VS Code settings
412
- if (Object.keys(vscodeSettings).length > 0) {
391
+ // Add Claude Code settings
392
+ if (Object.keys(claudeCodeSettings).length > 0) {
413
393
  zip.file(
414
- ".vscode/settings.json",
415
- JSON.stringify(vscodeSettings, null, 2) + "\n",
394
+ ".claude/settings.json",
395
+ JSON.stringify(claudeCodeSettings, null, 2) + "\n",
416
396
  );
417
397
  }
418
398