@jwdobeutechsolutions/dobeutech-claude-code-custom 1.0.0

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 (59) hide show
  1. package/CLAUDE.md +174 -0
  2. package/CONTRIBUTING.md +191 -0
  3. package/README.md +345 -0
  4. package/agents/accessibility-auditor.md +315 -0
  5. package/agents/api-designer.md +265 -0
  6. package/agents/architect.md +211 -0
  7. package/agents/build-error-resolver.md +532 -0
  8. package/agents/ci-cd-generator.md +318 -0
  9. package/agents/code-reviewer.md +104 -0
  10. package/agents/database-migrator.md +258 -0
  11. package/agents/deployment-manager.md +296 -0
  12. package/agents/doc-updater.md +452 -0
  13. package/agents/docker-specialist.md +293 -0
  14. package/agents/e2e-runner.md +708 -0
  15. package/agents/fullstack-architect.md +293 -0
  16. package/agents/infrastructure-engineer.md +297 -0
  17. package/agents/integration-tester.md +320 -0
  18. package/agents/performance-tester.md +243 -0
  19. package/agents/planner.md +119 -0
  20. package/agents/refactor-cleaner.md +306 -0
  21. package/agents/security-reviewer.md +545 -0
  22. package/agents/tdd-guide.md +280 -0
  23. package/agents/unit-test-generator.md +290 -0
  24. package/bin/claude-config.js +290 -0
  25. package/commands/api-design.md +55 -0
  26. package/commands/audit-accessibility.md +37 -0
  27. package/commands/audit-performance.md +38 -0
  28. package/commands/audit-security.md +43 -0
  29. package/commands/build-fix.md +29 -0
  30. package/commands/changelog.md +31 -0
  31. package/commands/code-review.md +40 -0
  32. package/commands/deploy.md +51 -0
  33. package/commands/docs-api.md +41 -0
  34. package/commands/e2e.md +363 -0
  35. package/commands/plan.md +113 -0
  36. package/commands/refactor-clean.md +28 -0
  37. package/commands/tdd.md +326 -0
  38. package/commands/test-coverage.md +27 -0
  39. package/commands/update-codemaps.md +17 -0
  40. package/commands/update-docs.md +31 -0
  41. package/hooks/hooks.json +121 -0
  42. package/mcp-configs/mcp-servers.json +163 -0
  43. package/package.json +53 -0
  44. package/rules/agents.md +49 -0
  45. package/rules/coding-style.md +70 -0
  46. package/rules/git-workflow.md +45 -0
  47. package/rules/hooks.md +46 -0
  48. package/rules/patterns.md +55 -0
  49. package/rules/performance.md +47 -0
  50. package/rules/security.md +36 -0
  51. package/rules/testing.md +30 -0
  52. package/scripts/install.js +254 -0
  53. package/skills/backend-patterns.md +582 -0
  54. package/skills/clickhouse-io.md +429 -0
  55. package/skills/coding-standards.md +520 -0
  56. package/skills/frontend-patterns.md +631 -0
  57. package/skills/project-guidelines-example.md +345 -0
  58. package/skills/security-review/SKILL.md +494 -0
  59. package/skills/tdd-workflow/SKILL.md +409 -0
@@ -0,0 +1,254 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
6
+
7
+ // Colors for console output
8
+ const colors = {
9
+ reset: '\x1b[0m',
10
+ bright: '\x1b[1m',
11
+ green: '\x1b[32m',
12
+ yellow: '\x1b[33m',
13
+ blue: '\x1b[34m',
14
+ red: '\x1b[31m',
15
+ };
16
+
17
+ function log(message, color = 'reset') {
18
+ console.log(`${colors[color]}${message}${colors.reset}`);
19
+ }
20
+
21
+ // Detect installation scope
22
+ function isGlobalInstall() {
23
+ // Check npm_config_global environment variable
24
+ if (process.env.npm_config_global === 'true') {
25
+ return true;
26
+ }
27
+
28
+ // Check if we're in a global node_modules location
29
+ const installPath = __dirname;
30
+ const globalPaths = [
31
+ path.join(os.homedir(), '.npm'),
32
+ path.join(os.homedir(), 'AppData', 'Roaming', 'npm'),
33
+ '/usr/local/lib/node_modules',
34
+ '/usr/lib/node_modules',
35
+ ];
36
+
37
+ return globalPaths.some(globalPath => installPath.includes(globalPath));
38
+ }
39
+
40
+ // Get target directory
41
+ function getTargetDir() {
42
+ if (isGlobalInstall()) {
43
+ // Global installation: ~/.claude/
44
+ return path.join(os.homedir(), '.claude');
45
+ } else {
46
+ // Local installation: ./.claude/ in project root
47
+ // Find project root by looking for package.json or .git
48
+ let currentDir = process.cwd();
49
+ let projectRoot = currentDir;
50
+
51
+ while (currentDir !== path.dirname(currentDir)) {
52
+ if (fs.existsSync(path.join(currentDir, 'package.json')) ||
53
+ fs.existsSync(path.join(currentDir, '.git'))) {
54
+ projectRoot = currentDir;
55
+ break;
56
+ }
57
+ currentDir = path.dirname(currentDir);
58
+ }
59
+
60
+ return path.join(projectRoot, '.claude');
61
+ }
62
+ }
63
+
64
+ // Get source directory (where package files are)
65
+ function getSourceDir() {
66
+ // When installed via npm, files are in node_modules/@jwdobeutechsolutions/dobeutech-claude-code-custom
67
+ // When running from source, files are in the repo root
68
+ const possiblePaths = [
69
+ path.join(__dirname, '..'), // From scripts/install.js -> repo root
70
+ path.join(process.cwd(), 'node_modules', '@jwdobeutechsolutions', 'dobeutech-claude-code-custom'),
71
+ path.join(process.cwd(), 'node_modules', 'dobeutech-claude-code-custom'),
72
+ ];
73
+
74
+ for (const possiblePath of possiblePaths) {
75
+ if (fs.existsSync(path.join(possiblePath, 'agents'))) {
76
+ return possiblePath;
77
+ }
78
+ }
79
+
80
+ // Fallback to __dirname/..
81
+ return path.join(__dirname, '..');
82
+ }
83
+
84
+ // Ensure directory exists
85
+ function ensureDir(dirPath) {
86
+ if (!fs.existsSync(dirPath)) {
87
+ fs.mkdirSync(dirPath, { recursive: true });
88
+ }
89
+ }
90
+
91
+ // Copy directory recursively
92
+ function copyDir(src, dest) {
93
+ ensureDir(dest);
94
+ const entries = fs.readdirSync(src, { withFileTypes: true });
95
+
96
+ for (const entry of entries) {
97
+ const srcPath = path.join(src, entry.name);
98
+ const destPath = path.join(dest, entry.name);
99
+
100
+ if (entry.isDirectory()) {
101
+ copyDir(srcPath, destPath);
102
+ } else {
103
+ fs.copyFileSync(srcPath, destPath);
104
+ }
105
+ }
106
+ }
107
+
108
+ // Copy file
109
+ function copyFile(src, dest) {
110
+ ensureDir(path.dirname(dest));
111
+ fs.copyFileSync(src, dest);
112
+ }
113
+
114
+ // Merge JSON files
115
+ function mergeJson(targetPath, sourceData, mergeKey) {
116
+ let targetData = {};
117
+
118
+ if (fs.existsSync(targetPath)) {
119
+ try {
120
+ const content = fs.readFileSync(targetPath, 'utf8');
121
+ targetData = JSON.parse(content);
122
+ } catch (err) {
123
+ log(`Warning: Could not parse existing ${path.basename(targetPath)}: ${err.message}`, 'yellow');
124
+ }
125
+ }
126
+
127
+ // Merge based on structure
128
+ if (mergeKey === 'hooks') {
129
+ // For hooks.json, merge into settings.json
130
+ if (!targetData.hooks) {
131
+ targetData.hooks = {};
132
+ }
133
+ if (sourceData.hooks) {
134
+ // Merge each hook category
135
+ for (const [category, hooks] of Object.entries(sourceData.hooks)) {
136
+ if (!targetData.hooks[category]) {
137
+ targetData.hooks[category] = [];
138
+ }
139
+ // Add new hooks that don't already exist (by matcher)
140
+ const existingMatchers = new Set(
141
+ targetData.hooks[category].map(h => h.matcher).filter(Boolean)
142
+ );
143
+ for (const hook of hooks) {
144
+ if (!hook.matcher || !existingMatchers.has(hook.matcher)) {
145
+ targetData.hooks[category].push(hook);
146
+ }
147
+ }
148
+ }
149
+ }
150
+ } else if (mergeKey === 'mcpServers') {
151
+ // For mcp-servers.json, merge into .claude.json
152
+ if (!targetData.mcpServers) {
153
+ targetData.mcpServers = {};
154
+ }
155
+ if (sourceData.mcpServers) {
156
+ // Merge MCP servers, preserving existing API keys
157
+ for (const [serverName, serverConfig] of Object.entries(sourceData.mcpServers)) {
158
+ if (!targetData.mcpServers[serverName]) {
159
+ targetData.mcpServers[serverName] = serverConfig;
160
+ } else {
161
+ // Preserve existing env vars (API keys)
162
+ if (targetData.mcpServers[serverName].env) {
163
+ serverConfig.env = {
164
+ ...serverConfig.env,
165
+ ...targetData.mcpServers[serverName].env,
166
+ };
167
+ }
168
+ targetData.mcpServers[serverName] = {
169
+ ...serverConfig,
170
+ ...targetData.mcpServers[serverName],
171
+ env: serverConfig.env || targetData.mcpServers[serverName].env,
172
+ };
173
+ }
174
+ }
175
+ }
176
+ }
177
+
178
+ return targetData;
179
+ }
180
+
181
+ // Main installation function
182
+ function install() {
183
+ try {
184
+ const sourceDir = getSourceDir();
185
+ const targetDir = getTargetDir();
186
+ const isGlobal = isGlobalInstall();
187
+
188
+ log(`\n${colors.bright}Installing Claude Code Configurations${colors.reset}`, 'bright');
189
+ log(`Source: ${sourceDir}`, 'blue');
190
+ log(`Target: ${targetDir}`, 'blue');
191
+ log(`Scope: ${isGlobal ? 'Global' : 'Local'}\n`, 'blue');
192
+
193
+ // Verify source directory has required files
194
+ if (!fs.existsSync(path.join(sourceDir, 'agents'))) {
195
+ log(`Error: Source directory does not contain 'agents' folder`, 'red');
196
+ log(`Expected: ${path.join(sourceDir, 'agents')}`, 'red');
197
+ process.exit(1);
198
+ }
199
+
200
+ // Create target directory structure
201
+ ensureDir(targetDir);
202
+
203
+ // Copy directories
204
+ const dirsToCopy = ['agents', 'skills', 'commands', 'rules', 'templates', 'docs'];
205
+ for (const dir of dirsToCopy) {
206
+ const srcPath = path.join(sourceDir, dir);
207
+ const destPath = path.join(targetDir, dir);
208
+
209
+ if (fs.existsSync(srcPath)) {
210
+ log(`Copying ${dir}/...`, 'green');
211
+ copyDir(srcPath, destPath);
212
+ }
213
+ }
214
+
215
+ // Handle hooks.json -> settings.json merge
216
+ const hooksSrc = path.join(sourceDir, 'hooks', 'hooks.json');
217
+ if (fs.existsSync(hooksSrc)) {
218
+ log(`Merging hooks into settings.json...`, 'green');
219
+ const hooksData = JSON.parse(fs.readFileSync(hooksSrc, 'utf8'));
220
+ const settingsPath = path.join(targetDir, 'settings.json');
221
+ const mergedSettings = mergeJson(settingsPath, hooksData, 'hooks');
222
+ fs.writeFileSync(settingsPath, JSON.stringify(mergedSettings, null, 2));
223
+ }
224
+
225
+ // Handle mcp-servers.json -> .claude.json merge
226
+ const mcpSrc = path.join(sourceDir, 'mcp-configs', 'mcp-servers.json');
227
+ if (fs.existsSync(mcpSrc)) {
228
+ log(`Merging MCP servers into .claude.json...`, 'green');
229
+ const mcpData = JSON.parse(fs.readFileSync(mcpSrc, 'utf8'));
230
+ const claudeJsonPath = path.join(targetDir, '.claude.json');
231
+ const mergedMcp = mergeJson(claudeJsonPath, mcpData, 'mcpServers');
232
+ fs.writeFileSync(claudeJsonPath, JSON.stringify(mergedMcp, null, 2));
233
+ }
234
+
235
+ log(`\n${colors.bright}✓ Installation complete!${colors.reset}`, 'green');
236
+ log(`\nConfiguration files installed to: ${targetDir}`, 'blue');
237
+ log(`\nNext steps:`, 'bright');
238
+ log(`1. Review and configure API keys in ${path.join(targetDir, '.claude.json')}`, 'yellow');
239
+ log(`2. Customize settings in ${path.join(targetDir, 'settings.json')} if needed`, 'yellow');
240
+ log(`3. Run 'claude-config update' to sync latest changes`, 'yellow');
241
+ log(``, 'reset');
242
+
243
+ } catch (error) {
244
+ log(`\n${colors.red}Error during installation:${colors.reset}`, 'red');
245
+ log(error.message, 'red');
246
+ if (error.stack) {
247
+ log(error.stack, 'red');
248
+ }
249
+ process.exit(1);
250
+ }
251
+ }
252
+
253
+ // Run installation
254
+ install();