fix: add no-hooks minimal install path

This commit is contained in:
Affaan Mustafa 2026-04-30 01:48:31 -04:00 committed by Affaan Mustafa
parent d26d66fd3b
commit 5881554a1c
5 changed files with 96 additions and 0 deletions

View File

@ -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.

View File

@ -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": [

View File

@ -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');

View File

@ -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-');

View File

@ -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'),