claude-dev-env 1.8.0 → 1.8.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.
Files changed (2) hide show
  1. package/bin/install.mjs +46 -7
  2. package/package.json +1 -1
package/bin/install.mjs CHANGED
@@ -28,6 +28,13 @@ const INSTALL_GROUPS = {
28
28
  prompts: {
29
29
  description: 'Prompt engineering tools',
30
30
  skills: ['prompt-generator', 'agent-prompt'],
31
+ includeHookFiles: [
32
+ 'blocking/agent-execution-intent-gate.py',
33
+ 'blocking/prompt_workflow_gate_core.py',
34
+ 'blocking/prompt-workflow-stop-guard.py',
35
+ 'HOOK_SPECS_PROMPT_WORKFLOW.md',
36
+ ],
37
+ includeRules: ['prompt-workflow-context-controls.md'],
31
38
  },
32
39
  journal: {
33
40
  description: 'Session logging and memory',
@@ -162,20 +169,45 @@ function install(selectedGroups) {
162
169
  const allowedDirectories = selectedGroups
163
170
  ? new Set(selectedGroups.flatMap(groupName => INSTALL_GROUPS[groupName].includeDirectories || []))
164
171
  : null;
165
- const shouldInstallHooks = selectedGroups
172
+ const shouldInstallAllHooks = selectedGroups
166
173
  ? selectedGroups.some(groupName => INSTALL_GROUPS[groupName].includeAllHooks)
167
174
  : true;
175
+ const allowedHookFiles = selectedGroups
176
+ ? new Set(selectedGroups.flatMap(groupName => INSTALL_GROUPS[groupName].includeHookFiles || []))
177
+ : null;
178
+ const allowedRules = selectedGroups
179
+ ? new Set(selectedGroups.flatMap(groupName => INSTALL_GROUPS[groupName].includeRules || []))
180
+ : null;
168
181
 
169
182
  const allInstalledFiles = [];
170
183
  const summary = {};
171
184
  for (const directory of CONTENT_DIRECTORIES) {
172
- if (allowedDirectories && !allowedDirectories.has(directory)) continue;
185
+ const hasFullAccess = !allowedDirectories || allowedDirectories.has(directory);
186
+ const hasPartialRules = directory === 'rules' && allowedRules && allowedRules.size > 0;
187
+ if (!hasFullAccess && !hasPartialRules) continue;
173
188
  const sourceDir = join(PACKAGE_ROOT, directory);
174
189
  if (!existsSync(sourceDir)) continue;
175
190
  const destDir = join(CLAUDE_HOME, directory);
176
- const stats = copyTree(sourceDir, destDir);
177
- summary[directory] = stats;
178
- allInstalledFiles.push(...stats.paths);
191
+ if (hasFullAccess) {
192
+ const stats = copyTree(sourceDir, destDir);
193
+ summary[directory] = stats;
194
+ allInstalledFiles.push(...stats.paths);
195
+ } else if (hasPartialRules) {
196
+ let rulesCreated = 0;
197
+ let rulesUpdated = 0;
198
+ for (const ruleFile of allowedRules) {
199
+ const sourcePath = join(sourceDir, ruleFile);
200
+ if (!existsSync(sourcePath)) continue;
201
+ const destPath = join(destDir, ruleFile);
202
+ mkdirSync(dirname(destPath), { recursive: true });
203
+ const existed = existsSync(destPath);
204
+ copyFileSync(sourcePath, destPath);
205
+ allInstalledFiles.push(destPath);
206
+ if (existed) { rulesUpdated++; } else { rulesCreated++; }
207
+ console.log(` ${existed ? '\u21bb' : '\u2713'} ${join(directory, ruleFile)} (${existed ? 'updated' : 'new'})`);
208
+ }
209
+ summary[directory] = { created: rulesCreated, updated: rulesUpdated, paths: [] };
210
+ }
179
211
  }
180
212
  const skillsSource = join(PACKAGE_ROOT, 'skills');
181
213
  if (existsSync(skillsSource)) {
@@ -193,11 +225,18 @@ function install(selectedGroups) {
193
225
  summary.skills = { created: skillsCreated, updated: skillsUpdated, paths: skillPaths };
194
226
  allInstalledFiles.push(...skillPaths);
195
227
  }
196
- if (shouldInstallHooks) {
228
+ const shouldInstallAnyHooks = shouldInstallAllHooks || (allowedHookFiles && allowedHookFiles.size > 0);
229
+ if (shouldInstallAnyHooks) {
197
230
  const hooksSource = join(PACKAGE_ROOT, 'hooks');
198
231
  if (existsSync(hooksSource)) {
199
232
  const hooksDestination = join(CLAUDE_HOME, 'hooks');
200
- const filesToCopy = collectFiles(hooksSource).filter(file => !file.endsWith('hooks.json'));
233
+ const filesToCopy = collectFiles(hooksSource)
234
+ .filter(file => !file.endsWith('hooks.json'))
235
+ .filter(file => {
236
+ if (shouldInstallAllHooks) return true;
237
+ const relativePath = relative(hooksSource, file).replace(/\\/g, '/');
238
+ return allowedHookFiles.has(relativePath);
239
+ });
201
240
  let hooksCreated = 0;
202
241
  let hooksUpdated = 0;
203
242
  for (const sourceFile of filesToCopy) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-dev-env",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "description": "Claude Code development standards — rules, hooks, agents, commands, and skills",
5
5
  "type": "module",
6
6
  "bin": {