diff --git a/README.md b/README.md index d1d3b778..0d4f6df1 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,34 @@ Most Claude Code users should use exactly one install path: If you already layered multiple installs and things look duplicated, skip straight to [Reset / Uninstall ECC](#reset--uninstall-ecc). +### Low-context / no-hooks path + +If hooks feel too global or you only want ECC's rules, agents, commands, and core workflow skills, skip the plugin and use the minimal manual profile: + +```bash +./install.sh --profile minimal --target claude +``` + +```powershell +.\install.ps1 --profile minimal --target claude +# or +npx ecc-install --profile minimal --target claude +``` + +This profile intentionally excludes `hooks-runtime`. + +If you want the normal core profile but need hooks off, use: + +```bash +./install.sh --profile core --without baseline:hooks --target claude +``` + +Add hooks later only if you want runtime enforcement: + +```bash +./install.sh --target claude --modules hooks-runtime +``` + ### Step 1: Install the Plugin (Recommended) > NOTE: The plugin is convenient, but the OSS installer below is still the most reliable path if your Claude Code build has trouble resolving self-hosted marketplace entries. diff --git a/manifests/install-profiles.json b/manifests/install-profiles.json index c35bb0db..d82cf4ed 100644 --- a/manifests/install-profiles.json +++ b/manifests/install-profiles.json @@ -1,6 +1,16 @@ { "version": 1, "profiles": { + "minimal": { + "description": "Low-context Claude Code setup with rules, agents, commands, platform configs, and quality workflow support, but no hook runtime.", + "modules": [ + "rules-core", + "agents-core", + "commands-core", + "platform-configs", + "workflow-quality" + ] + }, "core": { "description": "Minimal harness baseline with commands, hooks, platform configs, and quality workflow support.", "modules": [ diff --git a/tests/lib/install-manifests.test.js b/tests/lib/install-manifests.test.js index 10c97ad1..b987ab1c 100644 --- a/tests/lib/install-manifests.test.js +++ b/tests/lib/install-manifests.test.js @@ -79,6 +79,7 @@ function runTests() { if (test('lists install profiles from the real project', () => { const profiles = listInstallProfiles(); + assert.ok(profiles.some(profile => profile.id === 'minimal'), 'Should include minimal profile'); assert.ok(profiles.some(profile => profile.id === 'core'), 'Should include core profile'); assert.ok(profiles.some(profile => profile.id === 'full'), 'Should include full profile'); })) passed++; else failed++; @@ -212,6 +213,22 @@ function runTests() { assert.strictEqual(plan.targetRoot, path.join(projectRoot, '.agent')); })) passed++; else failed++; + if (test('resolves minimal profile without the hook runtime', () => { + const plan = resolveInstallPlan({ + profileId: 'minimal', + target: 'claude', + projectRoot: '/workspace/app', + }); + + assert.deepStrictEqual( + plan.selectedModuleIds, + ['rules-core', 'agents-core', 'commands-core', 'platform-configs', 'workflow-quality'] + ); + assert.ok(!plan.selectedModuleIds.includes('hooks-runtime'), + 'minimal profile should not install hooks-runtime'); + assert.ok(plan.operations.length > 0, 'Should include install operations'); + })) passed++; else failed++; + if (test('resolves explicit modules with dependency expansion', () => { const plan = resolveInstallPlan({ moduleIds: ['security'] }); assert.ok(plan.selectedModuleIds.includes('security'), 'Should include requested module'); diff --git a/tests/scripts/install-apply.test.js b/tests/scripts/install-apply.test.js index 3c2a7fda..63fde637 100644 --- a/tests/scripts/install-apply.test.js +++ b/tests/scripts/install-apply.test.js @@ -271,6 +271,24 @@ function runTests() { } })) passed++; else failed++; + if (test('supports minimal profile dry-runs without hooks through the installer', () => { + const homeDir = createTempDir('install-apply-home-'); + const projectDir = createTempDir('install-apply-project-'); + + try { + const result = run(['--profile', 'minimal', '--dry-run'], { cwd: projectDir, homeDir }); + assert.strictEqual(result.code, 0, result.stderr); + assert.ok(result.stdout.includes('Mode: manifest')); + assert.ok(result.stdout.includes('Profile: minimal')); + assert.ok(result.stdout.includes('Selected modules: rules-core, agents-core, commands-core, platform-configs, workflow-quality')); + assert.ok(!result.stdout.includes('hooks-runtime')); + assert.ok(!fs.existsSync(path.join(homeDir, '.claude', 'ecc', 'install-state.json'))); + } finally { + cleanup(homeDir); + cleanup(projectDir); + } + })) passed++; else failed++; + if (test('installs manifest profiles and writes non-legacy install-state', () => { const homeDir = createTempDir('install-apply-home-'); const projectDir = createTempDir('install-apply-project-'); diff --git a/tests/scripts/install-readme-clarity.test.js b/tests/scripts/install-readme-clarity.test.js index a6029eda..a1946ef0 100644 --- a/tests/scripts/install-readme-clarity.test.js +++ b/tests/scripts/install-readme-clarity.test.js @@ -70,6 +70,29 @@ function runTests() { ); })) passed++; else failed++; + if (test('README documents low-context no-hooks install path', () => { + assert.ok( + readme.includes('### Low-context / no-hooks path'), + 'README should surface a low-context no-hooks install option near Quick Start' + ); + assert.ok( + readme.includes('./install.sh --profile minimal --target claude'), + 'README should document the shell minimal profile command' + ); + assert.ok( + readme.includes('npx ecc-install --profile minimal --target claude'), + 'README should document the npx minimal profile command' + ); + assert.ok( + readme.includes('--profile core --without baseline:hooks --target claude'), + 'README should document the hook opt-out path for the core profile' + ); + assert.ok( + readme.includes('This profile intentionally excludes `hooks-runtime`.'), + 'README should state that the minimal profile excludes hooks' + ); + })) passed++; else failed++; + if (test('README explains plugin-path cleanup and rules scoping', () => { assert.ok( readme.includes('remove the plugin from Claude Code'),