mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-05-20 11:19:58 +08:00
Completes the install-target matrix for Claude Code. Until now, ECC's Claude support was home-scope only (~/.claude/) via the `claude` target. This adds a project-scope counterpart (./.claude/) via a new `claude-project` target so teams can install ECC per-repo without contaminating ~/.claude/ — matching the existing project-scope adapters for Cursor, Antigravity, Gemini, CodeBuddy, Joycode, and Zed. Symmetric with `claude`: - Same namespace under rules/ecc and skills/ecc - Same docs/<locale> handling for --locale - Same hooks placeholder substitution for hooks.json - Reuses claude-home's destination-mapping logic 1:1 Use cases: - Monorepos with multiple Flow-managed projects - Teams that want ECC scoped per-project without touching ~/.claude/ - Per-project skill/rule isolation when global install isn't desirable No breaking change: existing --target claude continues to route to claude-home (user-scope) unchanged. New target is opt-in. Tests ----- - 4 new tests in tests/lib/install-targets.test.js (root resolution, lookup-by-id, plan parity with claude, foreign-path filtering) - All install-target regression guards (schema enum / SUPPORTED_INSTALL_TARGETS) still pass - End-to-end smoke: `--target claude-project --profile minimal --dry-run` emits 359 ops with destinations rooted at <projectRoot>/.claude/ (parity with --target claude which emits 359 ops rooted at ~/.claude/)
79 lines
2.2 KiB
JavaScript
79 lines
2.2 KiB
JavaScript
const antigravityProject = require('./antigravity-project');
|
|
const claudeHome = require('./claude-home');
|
|
const claudeProject = require('./claude-project');
|
|
const codebuddyProject = require('./codebuddy-project');
|
|
const codexHome = require('./codex-home');
|
|
const cursorProject = require('./cursor-project');
|
|
const geminiProject = require('./gemini-project');
|
|
const joycodeProject = require('./joycode-project');
|
|
const opencodeHome = require('./opencode-home');
|
|
const qwenHome = require('./qwen-home');
|
|
const zedProject = require('./zed-project');
|
|
|
|
const ADAPTERS = Object.freeze([
|
|
claudeHome,
|
|
claudeProject,
|
|
cursorProject,
|
|
antigravityProject,
|
|
codexHome,
|
|
geminiProject,
|
|
opencodeHome,
|
|
codebuddyProject,
|
|
joycodeProject,
|
|
qwenHome,
|
|
zedProject,
|
|
]);
|
|
|
|
function listInstallTargetAdapters() {
|
|
return ADAPTERS.slice();
|
|
}
|
|
|
|
function getInstallTargetAdapter(targetOrAdapterId) {
|
|
const adapter = ADAPTERS.find(candidate => candidate.supports(targetOrAdapterId));
|
|
|
|
if (!adapter) {
|
|
throw new Error(`Unknown install target adapter: ${targetOrAdapterId}`);
|
|
}
|
|
|
|
return adapter;
|
|
}
|
|
|
|
function planInstallTargetScaffold(options = {}) {
|
|
const adapter = getInstallTargetAdapter(options.target);
|
|
const modules = Array.isArray(options.modules) ? options.modules : [];
|
|
const planningInput = {
|
|
repoRoot: options.repoRoot,
|
|
projectRoot: options.projectRoot || options.repoRoot,
|
|
homeDir: options.homeDir,
|
|
};
|
|
const validationIssues = adapter.validate(planningInput);
|
|
const blockingIssues = validationIssues.filter(issue => issue.severity === 'error');
|
|
if (blockingIssues.length > 0) {
|
|
throw new Error(blockingIssues.map(issue => issue.message).join('; '));
|
|
}
|
|
const targetRoot = adapter.resolveRoot(planningInput);
|
|
const installStatePath = adapter.getInstallStatePath(planningInput);
|
|
const operations = adapter.planOperations({
|
|
...planningInput,
|
|
modules,
|
|
});
|
|
|
|
return {
|
|
adapter: {
|
|
id: adapter.id,
|
|
target: adapter.target,
|
|
kind: adapter.kind,
|
|
},
|
|
targetRoot,
|
|
installStatePath,
|
|
validationIssues,
|
|
operations,
|
|
};
|
|
}
|
|
|
|
module.exports = {
|
|
getInstallTargetAdapter,
|
|
listInstallTargetAdapters,
|
|
planInstallTargetScaffold,
|
|
};
|