diff --git a/packages/cli/src/install/hooks.ts b/packages/cli/src/install/hooks.ts index 3988dd5..f669fdb 100644 --- a/packages/cli/src/install/hooks.ts +++ b/packages/cli/src/install/hooks.ts @@ -10,7 +10,7 @@ import { buildHookCommand, } from '../adapters/index.js'; import { configureOpencodePermissions } from './adapters.js'; -import { getDirName, getConfigDirFromHome, verifyInstalled } from './shared.js'; +import { getDirName, getConfigDirFromHome, verifyInstalled, removeBuiltInSkills } from './shared.js'; import type { InstallResult } from './shared.js'; import * as path from 'node:path'; import ora from 'ora'; @@ -24,6 +24,15 @@ export function cleanupOrphanedFiles(configDir: string): void { 'hooks/statusline.js', ]; + // Clean up legacy agents/skills/ directory (skills moved to skills/) + const legacySkillsDir = path.join(configDir, 'agents', 'skills'); + if (fs.existsSync(legacySkillsDir)) { + const removed = removeBuiltInSkills(legacySkillsDir); + if (removed > 0) { + console.log(` ${chalk.green('\u2713')} Removed ${removed} legacy skills from agents/skills/`); + } + } + for (const relPath of orphanedFiles) { const fullPath = path.join(configDir, relPath); if (fs.existsSync(fullPath)) { diff --git a/packages/cli/src/install/index.ts b/packages/cli/src/install/index.ts index f8dc579..26465fe 100644 --- a/packages/cli/src/install/index.ts +++ b/packages/cli/src/install/index.ts @@ -25,6 +25,7 @@ import { copyDirRecursive, verifyInstalled, verifyFileInstalled, + removeBuiltInSkills, } from './shared.js'; import type { InstallResult } from './shared.js'; import { getCommitAttribution } from './adapters.js'; @@ -262,21 +263,15 @@ async function install( } } - // Copy skills to agents/skills/ directory + // Copy skills to skills/ directory const skillsSrc = path.join(src, 'skills'); if (fs.existsSync(skillsSrc)) { spinner = ora({ text: 'Installing skills...', color: 'cyan' }).start(); - const skillsDest = path.join(targetDir, 'agents', 'skills'); + const skillsDest = path.join(targetDir, 'skills'); // Remove old MAXSIM built-in skills before copying new ones (preserve user custom skills) if (fs.existsSync(skillsDest)) { - const builtInSkills = ['tdd', 'systematic-debugging', 'verification-before-completion']; - for (const skill of builtInSkills) { - const skillDir = path.join(skillsDest, skill); - if (fs.existsSync(skillDir)) { - fs.rmSync(skillDir, { recursive: true }); - } - } + removeBuiltInSkills(skillsDest); } // Copy skills directory recursively @@ -300,10 +295,10 @@ async function install( const installedSkillDirs = fs.readdirSync(skillsDest, { withFileTypes: true }) .filter(e => e.isDirectory()).length; if (installedSkillDirs > 0) { - spinner.succeed(chalk.green('\u2713') + ` Installed ${installedSkillDirs} skills to agents/skills/`); + spinner.succeed(chalk.green('\u2713') + ` Installed ${installedSkillDirs} skills to skills/`); } else { spinner.fail('Failed to install skills'); - failures.push('agents/skills'); + failures.push('skills'); } } diff --git a/packages/cli/src/install/manifest.ts b/packages/cli/src/install/manifest.ts index c5e6fa5..6bf2b54 100644 --- a/packages/cli/src/install/manifest.ts +++ b/packages/cli/src/install/manifest.ts @@ -102,12 +102,12 @@ export function writeManifest( } } } - // Include skills in manifest (agents/skills//*) - const skillsManifestDir = path.join(agentsDir, 'skills'); + // Include skills in manifest (skills//*) + const skillsManifestDir = path.join(configDir, 'skills'); if (fs.existsSync(skillsManifestDir)) { const skillHashes = generateManifest(skillsManifestDir); for (const [rel, hash] of Object.entries(skillHashes)) { - manifest.files['agents/skills/' + rel] = hash; + manifest.files['skills/' + rel] = hash; } } diff --git a/packages/cli/src/install/shared.ts b/packages/cli/src/install/shared.ts index 0f05dd9..553d02d 100644 --- a/packages/cli/src/install/shared.ts +++ b/packages/cli/src/install/shared.ts @@ -118,6 +118,39 @@ export function verifyFileInstalled(filePath: string, description: string): bool return true; } +/** + * Built-in MAXSIM skill names — used during install, uninstall, and orphan cleanup + * to identify MAXSIM-owned skill directories (preserving user custom skills). + */ +export const BUILT_IN_SKILLS = [ + 'tdd', + 'systematic-debugging', + 'verification-before-completion', + 'code-review', + 'simplify', + 'memory-management', + 'using-maxsim', + 'batch-execution', + 'subagent-driven-development', + 'writing-plans', +] as const; + +/** + * Remove MAXSIM built-in skill directories from a given parent directory. + * Returns the number of skill directories removed. + */ +export function removeBuiltInSkills(skillsParentDir: string): number { + let count = 0; + for (const skill of BUILT_IN_SKILLS) { + const skillDir = path.join(skillsParentDir, skill); + if (fs.existsSync(skillDir)) { + fs.rmSync(skillDir, { recursive: true }); + count++; + } + } + return count; +} + export interface InstallResult { settingsPath: string | null; settings: Record | null; diff --git a/packages/cli/src/install/uninstall.ts b/packages/cli/src/install/uninstall.ts index dad9d4a..3f602d1 100644 --- a/packages/cli/src/install/uninstall.ts +++ b/packages/cli/src/install/uninstall.ts @@ -6,7 +6,7 @@ import chalk from 'chalk'; import type { RuntimeName } from '../adapters/index.js'; import { readSettings, writeSettings } from '../adapters/index.js'; -import { getDirName, getGlobalDir, getOpencodeGlobalDir } from './shared.js'; +import { getDirName, getGlobalDir, getOpencodeGlobalDir, removeBuiltInSkills } from './shared.js'; /** * Uninstall MAXSIM from the specified directory for a specific runtime @@ -93,7 +93,31 @@ export function uninstall(isGlobal: boolean, runtime: RuntimeName = 'claude', ex console.log(` ${chalk.green('\u2713')} Removed maxsim/`); } - // 3. Remove MAXSIM agents + // 3. Remove MAXSIM skills from skills/ directory + const skillsDir = path.join(targetDir, 'skills'); + if (fs.existsSync(skillsDir)) { + const skillCount = removeBuiltInSkills(skillsDir); + if (skillCount > 0) { + removedCount++; + console.log( + ` ${chalk.green('\u2713')} Removed ${skillCount} MAXSIM skills from skills/`, + ); + } + } + + // 3b. Remove legacy MAXSIM skills from agents/skills/ directory + const legacySkillsDir = path.join(targetDir, 'agents', 'skills'); + if (fs.existsSync(legacySkillsDir)) { + const legacySkillCount = removeBuiltInSkills(legacySkillsDir); + if (legacySkillCount > 0) { + removedCount++; + console.log( + ` ${chalk.green('\u2713')} Removed ${legacySkillCount} legacy MAXSIM skills from agents/skills/`, + ); + } + } + + // 4. Remove MAXSIM agents const agentsDir = path.join(targetDir, 'agents'); if (fs.existsSync(agentsDir)) { const files = fs.readdirSync(agentsDir); @@ -112,7 +136,7 @@ export function uninstall(isGlobal: boolean, runtime: RuntimeName = 'claude', ex } } - // 4. Remove MAXSIM hooks + // 5. Remove MAXSIM hooks const hooksDir = path.join(targetDir, 'hooks'); if (fs.existsSync(hooksDir)) { const maxsimHooks = [ @@ -137,7 +161,7 @@ export function uninstall(isGlobal: boolean, runtime: RuntimeName = 'claude', ex } } - // 5. Remove MAXSIM package.json (CommonJS mode marker) + // 6. Remove MAXSIM package.json (CommonJS mode marker) const pkgJsonPath = path.join(targetDir, 'package.json'); if (fs.existsSync(pkgJsonPath)) { try { @@ -154,7 +178,7 @@ export function uninstall(isGlobal: boolean, runtime: RuntimeName = 'claude', ex } } - // 6. Clean up settings.json + // 7. Clean up settings.json const settingsPath = path.join(targetDir, 'settings.json'); if (fs.existsSync(settingsPath)) { const settings = readSettings(settingsPath); @@ -248,7 +272,7 @@ export function uninstall(isGlobal: boolean, runtime: RuntimeName = 'claude', ex } } - // 7. For OpenCode, clean up permissions from opencode.json + // 8. For OpenCode, clean up permissions from opencode.json if (isOpencode) { const opencodeConfigDir = isGlobal ? getOpencodeGlobalDir() diff --git a/templates/agents/maxsim-debugger.md b/templates/agents/maxsim-debugger.md index ed588e6..59fe6e1 100644 --- a/templates/agents/maxsim-debugger.md +++ b/templates/agents/maxsim-debugger.md @@ -1273,8 +1273,8 @@ When any trigger condition below applies, read the full skill file via the Read | Skill | Read | Trigger | |-------|------|---------| -| Systematic Debugging | `.agents/skills/systematic-debugging/SKILL.md` | Always — you are a debugger, this is your primary skill | -| Verification Before Completion | `.agents/skills/verification-before-completion/SKILL.md` | Before claiming a bug is fixed or a debug session is complete | +| Systematic Debugging | `skills/systematic-debugging/SKILL.md` | Always — you are a debugger, this is your primary skill | +| Verification Before Completion | `skills/verification-before-completion/SKILL.md` | Before claiming a bug is fixed or a debug session is complete | **Project skills override built-in skills.** diff --git a/templates/agents/maxsim-executor.md b/templates/agents/maxsim-executor.md index 0663e14..be3cc2e 100644 --- a/templates/agents/maxsim-executor.md +++ b/templates/agents/maxsim-executor.md @@ -23,7 +23,7 @@ Before executing, discover project context: **Self-improvement lessons:** Read `.planning/LESSONS.md` if it exists — accumulated lessons from past executions on this codebase. Apply them proactively to avoid known mistakes before they become deviations. -**Project skills:** Check `.agents/skills/` directory if it exists: +**Project skills:** Check `skills/` directory if it exists: 1. List available skills (subdirectories) 2. Read `SKILL.md` for each skill (lightweight index ~130 lines) 3. Load specific `rules/*.md` files as needed during implementation @@ -612,11 +612,11 @@ Do not rely on memory of the skill content — always read the file fresh. | Skill | Read | Trigger | |-------|------|---------| -| TDD Enforcement | `.agents/skills/tdd/SKILL.md` | Before writing implementation code for a new feature, bug fix, or when plan type is `tdd` | -| Systematic Debugging | `.agents/skills/systematic-debugging/SKILL.md` | When encountering any bug, test failure, or unexpected behavior during execution | -| Verification Before Completion | `.agents/skills/verification-before-completion/SKILL.md` | Before claiming any task is done, fixed, or passing | +| TDD Enforcement | `skills/tdd/SKILL.md` | Before writing implementation code for a new feature, bug fix, or when plan type is `tdd` | +| Systematic Debugging | `skills/systematic-debugging/SKILL.md` | When encountering any bug, test failure, or unexpected behavior during execution | +| Verification Before Completion | `skills/verification-before-completion/SKILL.md` | Before claiming any task is done, fixed, or passing | -**Project skills override built-in skills.** If a skill with the same name exists in `.agents/skills/` in the project, load that one instead. +**Project skills override built-in skills.** If a skill with the same name exists in `skills/` in the project, load that one instead. diff --git a/templates/agents/maxsim-phase-researcher.md b/templates/agents/maxsim-phase-researcher.md index 0a170d4..c5269c6 100644 --- a/templates/agents/maxsim-phase-researcher.md +++ b/templates/agents/maxsim-phase-researcher.md @@ -26,7 +26,7 @@ Before researching, discover project context: **Project instructions:** Read `./CLAUDE.md` if it exists in the working directory. Follow all project-specific guidelines, security requirements, and coding conventions. -**Project skills:** Check `.agents/skills/` directory if it exists: +**Project skills:** Check `skills/` directory if it exists: 1. List available skills (subdirectories) 2. Read `SKILL.md` for each skill (lightweight index ~130 lines) 3. Load specific `rules/*.md` files as needed during research @@ -559,7 +559,7 @@ When any trigger condition below applies, read the full skill file via the Read | Skill | Read | Trigger | |-------|------|---------| -| Verification Before Completion | `.agents/skills/verification-before-completion/SKILL.md` | Before concluding research with confidence ratings | +| Verification Before Completion | `skills/verification-before-completion/SKILL.md` | Before concluding research with confidence ratings | **Project skills override built-in skills.** diff --git a/templates/agents/maxsim-plan-checker.md b/templates/agents/maxsim-plan-checker.md index 470771d..5aa3e48 100644 --- a/templates/agents/maxsim-plan-checker.md +++ b/templates/agents/maxsim-plan-checker.md @@ -33,7 +33,7 @@ Before verifying, discover project context: **Self-improvement lessons:** Read `.planning/LESSONS.md` if it exists — accumulated lessons from past executions. Use planning insights as an additional verification dimension: flag plans that repeat known gap patterns or ignore documented codebase conventions. -**Project skills:** Check `.agents/skills/` directory if it exists: +**Project skills:** Check `skills/` directory if it exists: 1. List available skills (subdirectories) 2. Read `SKILL.md` for each skill (lightweight index ~130 lines) 3. Load specific `rules/*.md` files as needed during verification @@ -707,7 +707,7 @@ When any trigger condition below applies, read the full skill file via the Read | Skill | Read | Trigger | |-------|------|---------| -| Verification Before Completion | `.agents/skills/verification-before-completion/SKILL.md` | Before issuing final PASS/FAIL verdict on a plan | +| Verification Before Completion | `skills/verification-before-completion/SKILL.md` | Before issuing final PASS/FAIL verdict on a plan | **Project skills override built-in skills.** diff --git a/templates/agents/maxsim-planner.md b/templates/agents/maxsim-planner.md index 9a8e752..21958fe 100644 --- a/templates/agents/maxsim-planner.md +++ b/templates/agents/maxsim-planner.md @@ -35,7 +35,7 @@ Before planning, discover project context: **Self-improvement lessons:** Read `.planning/LESSONS.md` if it exists — accumulated lessons from past executions on this codebase. Apply planning insights proactively: avoid known gaps, include wiring tasks for patterns that historically broke, reference codebase-specific conventions in task actions. -**Project skills:** Check `.agents/skills/` directory if it exists: +**Project skills:** Check `skills/` directory if it exists: 1. List available skills (subdirectories) 2. Read `SKILL.md` for each skill (lightweight index ~130 lines) 3. Load specific `rules/*.md` files as needed during planning @@ -1199,8 +1199,8 @@ When any trigger condition below applies, read the full skill file via the Read | Skill | Read | Trigger | |-------|------|---------| -| TDD Enforcement | `.agents/skills/tdd/SKILL.md` | When identifying TDD candidates during task breakdown | -| Verification Before Completion | `.agents/skills/verification-before-completion/SKILL.md` | When writing sections for tasks | +| TDD Enforcement | `skills/tdd/SKILL.md` | When identifying TDD candidates during task breakdown | +| Verification Before Completion | `skills/verification-before-completion/SKILL.md` | When writing sections for tasks | **Project skills override built-in skills.** diff --git a/templates/workflows/execute-phase.md b/templates/workflows/execute-phase.md index b9e29cf..186cce6 100644 --- a/templates/workflows/execute-phase.md +++ b/templates/workflows/execute-phase.md @@ -152,7 +152,7 @@ Execute each wave in sequence. Within a wave: parallel if `PARALLELIZATION=true` - .planning/STATE.md (State) - .planning/config.json (Config, if exists) - ./CLAUDE.md (Project instructions, if exists — follow project-specific guidelines and coding conventions) - - .agents/skills/ (Project skills, if exists — list skills, read SKILL.md for each, follow relevant rules during implementation) + - skills/ (Project skills, if exists — list skills, read SKILL.md for each, follow relevant rules during implementation) diff --git a/templates/workflows/plan-phase.md b/templates/workflows/plan-phase.md index dcce5d0..eff3c62 100644 --- a/templates/workflows/plan-phase.md +++ b/templates/workflows/plan-phase.md @@ -112,7 +112,7 @@ Answer: "What do I need to know to PLAN this phase well?" **Phase requirement IDs (MUST address):** {phase_req_ids} **Project instructions:** Read ./CLAUDE.md if exists — follow project-specific guidelines -**Project skills:** Check .agents/skills/ directory (if exists) — read SKILL.md files, research should account for project skill patterns +**Project skills:** Check skills/ directory (if exists) — read SKILL.md files, research should account for project skill patterns @@ -212,7 +212,7 @@ Planner prompt: **Phase requirement IDs (every ID MUST appear in a plan's `requirements` field):** {phase_req_ids} **Project instructions:** Read ./CLAUDE.md if exists — follow project-specific guidelines -**Project skills:** Check .agents/skills/ directory (if exists) — read SKILL.md files, plans should account for project skill rules +**Project skills:** Check skills/ directory (if exists) — read SKILL.md files, plans should account for project skill rules @@ -277,7 +277,7 @@ Checker prompt: **Phase requirement IDs (MUST ALL be covered):** {phase_req_ids} **Project instructions:** Read ./CLAUDE.md if exists — verify plans honor project guidelines -**Project skills:** Check .agents/skills/ directory (if exists) — verify plans account for project skill rules +**Project skills:** Check skills/ directory (if exists) — verify plans account for project skill rules diff --git a/templates/workflows/quick.md b/templates/workflows/quick.md index 5f40e0f..b24a777 100644 --- a/templates/workflows/quick.md +++ b/templates/workflows/quick.md @@ -108,7 +108,7 @@ Task( - ./CLAUDE.md (if exists — follow project-specific guidelines) -**Project skills:** Check .agents/skills/ directory (if exists) — read SKILL.md files, plans should account for project skill rules +**Project skills:** Check skills/ directory (if exists) — read SKILL.md files, plans should account for project skill rules @@ -259,7 +259,7 @@ Execute quick task ${next_num}. - ${QUICK_DIR}/${next_num}-PLAN.md (Plan) - .planning/STATE.md (Project state) - ./CLAUDE.md (Project instructions, if exists) -- .agents/skills/ (Project skills, if exists — list skills, read SKILL.md for each, follow relevant rules during implementation) +- skills/ (Project skills, if exists — list skills, read SKILL.md for each, follow relevant rules during implementation)