@paulduvall/claude-dev-toolkit 0.0.1-alpha.1 → 0.0.1-alpha.11

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 (141) hide show
  1. package/README.md +74 -23
  2. package/bin/claude-commands +263 -64
  3. package/commands/active/xarchitecture.md +393 -0
  4. package/commands/active/xconfig.md +127 -0
  5. package/commands/active/xdebug.md +130 -0
  6. package/commands/active/xdocs.md +178 -0
  7. package/commands/active/xgit.md +149 -0
  8. package/commands/active/xpipeline.md +152 -0
  9. package/commands/active/xquality.md +96 -0
  10. package/commands/active/xrefactor.md +198 -0
  11. package/commands/active/xrelease.md +142 -0
  12. package/commands/active/xsecurity.md +92 -0
  13. package/commands/active/xspec.md +174 -0
  14. package/commands/active/xtdd.md +151 -0
  15. package/commands/active/xtest.md +89 -0
  16. package/commands/experiments/xact.md +742 -0
  17. package/commands/experiments/xanalytics.md +113 -0
  18. package/commands/experiments/xanalyze.md +70 -0
  19. package/commands/experiments/xapi.md +161 -0
  20. package/commands/experiments/xatomic.md +112 -0
  21. package/commands/experiments/xaws.md +85 -0
  22. package/commands/experiments/xcicd.md +337 -0
  23. package/commands/experiments/xcommit.md +122 -0
  24. package/commands/experiments/xcompliance.md +182 -0
  25. package/commands/experiments/xconstraints.md +89 -0
  26. package/commands/experiments/xcoverage.md +90 -0
  27. package/commands/experiments/xdb.md +102 -0
  28. package/commands/experiments/xdesign.md +121 -0
  29. package/commands/experiments/xevaluate.md +111 -0
  30. package/commands/experiments/xfootnote.md +12 -0
  31. package/commands/experiments/xgenerate.md +117 -0
  32. package/commands/experiments/xgovernance.md +149 -0
  33. package/commands/experiments/xgreen.md +66 -0
  34. package/commands/experiments/xiac.md +118 -0
  35. package/commands/experiments/xincident.md +137 -0
  36. package/commands/experiments/xinfra.md +115 -0
  37. package/commands/experiments/xknowledge.md +115 -0
  38. package/commands/experiments/xmaturity.md +120 -0
  39. package/commands/experiments/xmetrics.md +118 -0
  40. package/commands/experiments/xmonitoring.md +128 -0
  41. package/commands/experiments/xnew.md +898 -0
  42. package/commands/experiments/xobservable.md +114 -0
  43. package/commands/experiments/xoidc.md +165 -0
  44. package/commands/experiments/xoptimize.md +115 -0
  45. package/commands/experiments/xperformance.md +112 -0
  46. package/commands/experiments/xplanning.md +131 -0
  47. package/commands/experiments/xpolicy.md +115 -0
  48. package/commands/experiments/xproduct.md +98 -0
  49. package/commands/experiments/xreadiness.md +75 -0
  50. package/commands/experiments/xred.md +55 -0
  51. package/commands/experiments/xrisk.md +128 -0
  52. package/commands/experiments/xrules.md +124 -0
  53. package/commands/experiments/xsandbox.md +120 -0
  54. package/commands/experiments/xscan.md +102 -0
  55. package/commands/experiments/xsetup.md +123 -0
  56. package/commands/experiments/xtemplate.md +116 -0
  57. package/commands/experiments/xtrace.md +212 -0
  58. package/commands/experiments/xux.md +171 -0
  59. package/commands/experiments/xvalidate.md +104 -0
  60. package/commands/experiments/xworkflow.md +113 -0
  61. package/hooks/README.md +231 -0
  62. package/hooks/file-logger.sh +98 -0
  63. package/hooks/lib/argument-parser.sh +422 -0
  64. package/hooks/lib/config-constants.sh +230 -0
  65. package/hooks/lib/context-manager.sh +549 -0
  66. package/hooks/lib/error-handler.sh +412 -0
  67. package/hooks/lib/execution-engine.sh +627 -0
  68. package/hooks/lib/file-utils.sh +375 -0
  69. package/hooks/lib/subagent-discovery.sh +465 -0
  70. package/hooks/lib/subagent-validator.sh +597 -0
  71. package/hooks/on-error-debug.sh +221 -0
  72. package/hooks/pre-commit-quality.sh +204 -0
  73. package/hooks/pre-write-security.sh +107 -0
  74. package/hooks/prevent-credential-exposure.sh +265 -0
  75. package/hooks/subagent-trigger-simple.sh +193 -0
  76. package/hooks/subagent-trigger.sh +253 -0
  77. package/lib/backup-restore-command.js +140 -0
  78. package/lib/base/base-command.js +252 -0
  79. package/lib/base/command-result.js +184 -0
  80. package/lib/config/constants.js +255 -0
  81. package/lib/config.js +228 -3
  82. package/lib/configure-command.js +428 -0
  83. package/lib/dependency-validator.js +64 -5
  84. package/lib/hook-installer-core.js +2 -2
  85. package/lib/installation-instruction-generator-backup.js +579 -0
  86. package/lib/installation-instruction-generator.js +213 -495
  87. package/lib/installer.js +134 -56
  88. package/lib/oidc-command.js +363 -0
  89. package/lib/result.js +138 -0
  90. package/lib/services/backup-list-service.js +226 -0
  91. package/lib/services/backup-service.js +230 -0
  92. package/lib/services/command-installer-service.js +217 -0
  93. package/lib/services/logger-service.js +201 -0
  94. package/lib/services/package-manager-service.js +319 -0
  95. package/lib/services/platform-instruction-service.js +294 -0
  96. package/lib/services/recovery-instruction-service.js +348 -0
  97. package/lib/services/restore-service.js +221 -0
  98. package/lib/setup-command.js +309 -0
  99. package/lib/subagent-formatter.js +278 -0
  100. package/lib/subagents-core.js +237 -0
  101. package/lib/subagents.js +508 -0
  102. package/lib/types.d.ts +183 -0
  103. package/lib/utils/claude-path-config.js +184 -0
  104. package/lib/utils/file-system-utils.js +152 -0
  105. package/lib/utils.js +8 -4
  106. package/lib/verify-command.js +430 -0
  107. package/package.json +17 -4
  108. package/scripts/postinstall.js +28 -10
  109. package/subagents/api-guardian.md +29 -0
  110. package/subagents/audit-trail-verifier.md +24 -0
  111. package/subagents/change-scoper.md +23 -0
  112. package/subagents/ci-pipeline-curator.md +24 -0
  113. package/subagents/code-review-assistant.md +258 -0
  114. package/subagents/continuous-release-orchestrator.md +29 -0
  115. package/subagents/contract-tester.md +24 -0
  116. package/subagents/data-steward.md +29 -0
  117. package/subagents/debug-context.md +197 -0
  118. package/subagents/debug-specialist.md +138 -0
  119. package/subagents/dependency-steward.md +24 -0
  120. package/subagents/deployment-strategist.md +29 -0
  121. package/subagents/documentation-curator.md +29 -0
  122. package/subagents/environment-guardian.md +29 -0
  123. package/subagents/license-compliance-guardian.md +29 -0
  124. package/subagents/observability-engineer.md +25 -0
  125. package/subagents/performance-guardian.md +29 -0
  126. package/subagents/product-owner-proxy.md +28 -0
  127. package/subagents/requirements-reviewer.md +26 -0
  128. package/subagents/rollback-first-responder.md +24 -0
  129. package/subagents/sbom-provenance.md +25 -0
  130. package/subagents/security-auditor.md +29 -0
  131. package/subagents/style-enforcer.md +23 -0
  132. package/subagents/test-writer.md +24 -0
  133. package/subagents/trunk-guardian.md +29 -0
  134. package/subagents/workflow-coordinator.md +26 -0
  135. package/templates/README.md +100 -0
  136. package/templates/basic-settings.json +30 -0
  137. package/templates/comprehensive-settings.json +206 -0
  138. package/templates/hybrid-hook-config.yaml +133 -0
  139. package/templates/security-focused-settings.json +62 -0
  140. package/templates/subagent-hooks.yaml +188 -0
  141. package/tsconfig.json +37 -0
@@ -0,0 +1,348 @@
1
+ /**
2
+ * Recovery Instruction Service
3
+ * Generates recovery and troubleshooting instructions for failed installations
4
+ */
5
+
6
+ const { ERROR_MESSAGES } = require('../config/constants');
7
+
8
+ class RecoveryInstructionService {
9
+ constructor() {
10
+ this.errorMessages = ERROR_MESSAGES;
11
+ this.commonRecoverySteps = this._initializeCommonRecoverySteps();
12
+ }
13
+
14
+ /**
15
+ * Generate recovery suggestions for failed dependency
16
+ * @param {Object} failedDependency - Dependency that failed validation
17
+ * @returns {Object} Recovery suggestions
18
+ */
19
+ generateRecoverySuggestions(failedDependency) {
20
+ const suggestions = {
21
+ immediate: [],
22
+ alternative: [],
23
+ troubleshooting: [],
24
+ additionalResources: []
25
+ };
26
+
27
+ if (!failedDependency || !failedDependency.error) {
28
+ return this._getGenericRecoverySuggestions(failedDependency);
29
+ }
30
+
31
+ // Generate error-specific suggestions
32
+ this._addErrorSpecificSuggestions(suggestions, failedDependency);
33
+
34
+ // Add dependency-specific suggestions
35
+ this._addDependencySpecificSuggestions(suggestions, failedDependency);
36
+
37
+ // Add platform-specific suggestions
38
+ this._addPlatformSpecificSuggestions(suggestions, failedDependency);
39
+
40
+ // Add general troubleshooting steps
41
+ this._addGeneralTroubleshootingSteps(suggestions);
42
+
43
+ return suggestions;
44
+ }
45
+
46
+ /**
47
+ * Initialize common recovery steps
48
+ * @returns {Object} Common recovery steps by category
49
+ * @private
50
+ */
51
+ _initializeCommonRecoverySteps() {
52
+ return {
53
+ permissions: [
54
+ 'Run command prompt or terminal as administrator/sudo',
55
+ 'Check file and directory permissions',
56
+ 'Ensure user has installation privileges'
57
+ ],
58
+ network: [
59
+ 'Check internet connection',
60
+ 'Try using a different network or VPN',
61
+ 'Configure proxy settings if behind corporate firewall',
62
+ 'Clear DNS cache: ipconfig /flushdns (Windows) or sudo dscacheutil -flushcache (macOS)'
63
+ ],
64
+ cache: [
65
+ 'Clear package manager cache',
66
+ 'Remove temporary installation files',
67
+ 'Reset package manager configuration'
68
+ ],
69
+ environment: [
70
+ 'Check system PATH environment variable',
71
+ 'Verify required environment variables are set',
72
+ 'Restart terminal/command prompt after installation',
73
+ 'Reboot system if necessary'
74
+ ]
75
+ };
76
+ }
77
+
78
+ /**
79
+ * Add error-specific recovery suggestions
80
+ * @param {Object} suggestions - Suggestions object to modify
81
+ * @param {Object} failedDependency - Failed dependency information
82
+ * @private
83
+ */
84
+ _addErrorSpecificSuggestions(suggestions, failedDependency) {
85
+ const errorCode = failedDependency.error.code || 'UNKNOWN';
86
+
87
+ switch (errorCode) {
88
+ case 'NOT_FOUND':
89
+ suggestions.immediate.push(`Install ${failedDependency.name} using your system package manager`);
90
+ suggestions.immediate.push(`Add ${failedDependency.name} to your system PATH`);
91
+ suggestions.alternative.push(`Download and install ${failedDependency.name} manually`);
92
+ suggestions.alternative.push(`Use portable version of ${failedDependency.name}`);
93
+ suggestions.troubleshooting.push(`Verify ${failedDependency.name} installation directory`);
94
+ suggestions.troubleshooting.push(`Check if ${failedDependency.name} was installed with different name`);
95
+ break;
96
+
97
+ case 'VERSION_MISMATCH':
98
+ suggestions.immediate.push(`Update ${failedDependency.name} to version ${failedDependency.requiredVersion || 'latest'}`);
99
+ suggestions.immediate.push(`Use version manager to install specific version`);
100
+ suggestions.alternative.push(`Install required version manually`);
101
+ suggestions.alternative.push(`Use Docker container with required version`);
102
+ suggestions.troubleshooting.push(`Check if multiple versions are installed`);
103
+ suggestions.troubleshooting.push(`Verify which version is in PATH`);
104
+ break;
105
+
106
+ case 'PERMISSION_DENIED':
107
+ suggestions.immediate.push(...this.commonRecoverySteps.permissions);
108
+ suggestions.alternative.push(`Install to user directory instead of system-wide`);
109
+ suggestions.alternative.push(`Use package manager that doesn't require admin rights`);
110
+ break;
111
+
112
+ case 'NETWORK_ERROR':
113
+ suggestions.immediate.push(...this.commonRecoverySteps.network);
114
+ suggestions.alternative.push(`Download installation files manually`);
115
+ suggestions.alternative.push(`Use offline installer if available`);
116
+ break;
117
+
118
+ case 'DISK_SPACE':
119
+ suggestions.immediate.push('Free up disk space by removing unnecessary files');
120
+ suggestions.immediate.push('Clean temporary files and caches');
121
+ suggestions.alternative.push('Install to different drive with more space');
122
+ suggestions.alternative.push('Use symbolic links to move installation');
123
+ break;
124
+
125
+ case 'CORRUPTED_DOWNLOAD':
126
+ suggestions.immediate.push('Clear download cache and retry');
127
+ suggestions.immediate.push('Download from different mirror or source');
128
+ suggestions.alternative.push('Verify download integrity with checksums');
129
+ suggestions.alternative.push('Use different download method');
130
+ break;
131
+
132
+ default:
133
+ suggestions.immediate.push(`Reinstall ${failedDependency.name} from scratch`);
134
+ suggestions.immediate.push('Check system logs for more details');
135
+ suggestions.troubleshooting.push('Run installation in verbose mode');
136
+ suggestions.troubleshooting.push('Check for conflicting software');
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Add dependency-specific recovery suggestions
142
+ * @param {Object} suggestions - Suggestions object to modify
143
+ * @param {Object} failedDependency - Failed dependency information
144
+ * @private
145
+ */
146
+ _addDependencySpecificSuggestions(suggestions, failedDependency) {
147
+ const dependencyName = failedDependency.name.toLowerCase();
148
+
149
+ switch (dependencyName) {
150
+ case 'node':
151
+ case 'nodejs':
152
+ suggestions.immediate.push('Install Node.js from official website: https://nodejs.org');
153
+ suggestions.alternative.push('Use Node Version Manager (nvm) for easier management');
154
+ suggestions.alternative.push('Install via package manager: brew install node (macOS)');
155
+ suggestions.troubleshooting.push('Check if Node.js is installed as "nodejs" instead of "node"');
156
+ suggestions.additionalResources.push('https://nodejs.org/en/download/package-manager/');
157
+ break;
158
+
159
+ case 'npm':
160
+ suggestions.immediate.push('npm comes with Node.js - install Node.js first');
161
+ suggestions.alternative.push('Install npm separately: npm install -g npm@latest');
162
+ suggestions.troubleshooting.push('Check npm configuration: npm config list');
163
+ suggestions.troubleshooting.push('Reset npm to defaults: npm config delete prefix');
164
+ break;
165
+
166
+ case 'git':
167
+ suggestions.immediate.push('Install Git from official website: https://git-scm.com');
168
+ suggestions.alternative.push('Install via package manager based on your OS');
169
+ suggestions.troubleshooting.push('Configure Git after installation with user name and email');
170
+ suggestions.additionalResources.push('https://git-scm.com/book/en/v2/Getting-Started-Installing-Git');
171
+ break;
172
+
173
+ case 'python':
174
+ case 'python3':
175
+ suggestions.immediate.push('Install Python from official website: https://python.org');
176
+ suggestions.alternative.push('Use Python version manager like pyenv');
177
+ suggestions.alternative.push('Install Anaconda for scientific computing');
178
+ suggestions.troubleshooting.push('Check if python3 command is available instead of python');
179
+ suggestions.troubleshooting.push('Verify pip is installed: python -m ensurepip');
180
+ suggestions.additionalResources.push('https://docs.python.org/3/using/index.html');
181
+ break;
182
+
183
+ case 'docker':
184
+ suggestions.immediate.push('Install Docker Desktop from official website');
185
+ suggestions.alternative.push('Use Docker CE for server installations');
186
+ suggestions.troubleshooting.push('Enable virtualization in BIOS settings');
187
+ suggestions.troubleshooting.push('Restart Docker service after installation');
188
+ suggestions.additionalResources.push('https://docs.docker.com/get-docker/');
189
+ break;
190
+ }
191
+ }
192
+
193
+ /**
194
+ * Add platform-specific recovery suggestions
195
+ * @param {Object} suggestions - Suggestions object to modify
196
+ * @param {Object} failedDependency - Failed dependency information
197
+ * @private
198
+ */
199
+ _addPlatformSpecificSuggestions(suggestions, failedDependency) {
200
+ const platform = process.platform;
201
+
202
+ switch (platform) {
203
+ case 'win32':
204
+ suggestions.troubleshooting.push('Try Windows Subsystem for Linux (WSL) for better compatibility');
205
+ suggestions.troubleshooting.push('Use PowerShell instead of Command Prompt');
206
+ suggestions.troubleshooting.push('Temporarily disable Windows Defender during installation');
207
+ suggestions.alternative.push('Use Chocolatey package manager: https://chocolatey.org');
208
+ suggestions.alternative.push('Use winget package manager if available');
209
+ break;
210
+
211
+ case 'darwin':
212
+ suggestions.alternative.push('Use Homebrew package manager: https://brew.sh');
213
+ suggestions.troubleshooting.push('Install Xcode Command Line Tools: xcode-select --install');
214
+ suggestions.troubleshooting.push('Check for conflicting installations in /usr/local');
215
+ break;
216
+
217
+ case 'linux':
218
+ suggestions.alternative.push('Use distribution package manager (apt, yum, pacman, etc.)');
219
+ suggestions.troubleshooting.push('Update package lists before installation');
220
+ suggestions.troubleshooting.push('Check if package is available in distribution repositories');
221
+ suggestions.troubleshooting.push('Consider using Snap or Flatpak for universal packages');
222
+ break;
223
+ }
224
+ }
225
+
226
+ /**
227
+ * Add general troubleshooting steps
228
+ * @param {Object} suggestions - Suggestions object to modify
229
+ * @private
230
+ */
231
+ _addGeneralTroubleshootingSteps(suggestions) {
232
+ suggestions.troubleshooting.push(...this.commonRecoverySteps.environment);
233
+ suggestions.troubleshooting.push('Check system logs for error details');
234
+ suggestions.troubleshooting.push('Try installation in safe mode or clean environment');
235
+ suggestions.troubleshooting.push('Verify system meets minimum requirements');
236
+ }
237
+
238
+ /**
239
+ * Get generic recovery suggestions when error details are not available
240
+ * @param {Object} failedDependency - Failed dependency information
241
+ * @returns {Object} Generic recovery suggestions
242
+ * @private
243
+ */
244
+ _getGenericRecoverySuggestions(failedDependency) {
245
+ const name = failedDependency?.name || 'dependency';
246
+
247
+ return {
248
+ immediate: [
249
+ `Try reinstalling ${name}`,
250
+ `Check if ${name} is in your system PATH`,
251
+ 'Restart your terminal or command prompt'
252
+ ],
253
+ alternative: [
254
+ `Install ${name} using different package manager`,
255
+ `Download ${name} manually from official website`,
256
+ `Use portable version of ${name}`
257
+ ],
258
+ troubleshooting: [
259
+ 'Check system requirements',
260
+ 'Verify internet connection',
261
+ 'Run installation as administrator if needed',
262
+ 'Check for system updates'
263
+ ],
264
+ additionalResources: []
265
+ };
266
+ }
267
+
268
+ /**
269
+ * Generate step-by-step recovery guide
270
+ * @param {Object} failedDependency - Failed dependency information
271
+ * @returns {Array} Step-by-step recovery instructions
272
+ */
273
+ generateStepByStepGuide(failedDependency) {
274
+ const guide = [];
275
+ const suggestions = this.generateRecoverySuggestions(failedDependency);
276
+
277
+ // Step 1: Immediate actions
278
+ if (suggestions.immediate.length > 0) {
279
+ guide.push({
280
+ step: 1,
281
+ title: 'Try these immediate solutions first:',
282
+ actions: suggestions.immediate.slice(0, 3) // Top 3 immediate suggestions
283
+ });
284
+ }
285
+
286
+ // Step 2: Alternative approaches
287
+ if (suggestions.alternative.length > 0) {
288
+ guide.push({
289
+ step: 2,
290
+ title: 'If immediate solutions don\'t work, try these alternatives:',
291
+ actions: suggestions.alternative.slice(0, 3) // Top 3 alternatives
292
+ });
293
+ }
294
+
295
+ // Step 3: Troubleshooting
296
+ if (suggestions.troubleshooting.length > 0) {
297
+ guide.push({
298
+ step: 3,
299
+ title: 'For advanced troubleshooting:',
300
+ actions: suggestions.troubleshooting.slice(0, 3) // Top 3 troubleshooting steps
301
+ });
302
+ }
303
+
304
+ // Step 4: Additional resources
305
+ if (suggestions.additionalResources.length > 0) {
306
+ guide.push({
307
+ step: 4,
308
+ title: 'Additional resources:',
309
+ actions: suggestions.additionalResources
310
+ });
311
+ }
312
+
313
+ return guide;
314
+ }
315
+
316
+ /**
317
+ * Generate recovery instructions for multiple failed dependencies
318
+ * @param {Array} failedDependencies - Array of failed dependencies
319
+ * @returns {Object} Consolidated recovery instructions
320
+ */
321
+ generateBulkRecoveryInstructions(failedDependencies) {
322
+ const consolidated = {
323
+ immediate: new Set(),
324
+ alternative: new Set(),
325
+ troubleshooting: new Set(),
326
+ additionalResources: new Set()
327
+ };
328
+
329
+ failedDependencies.forEach(dependency => {
330
+ const suggestions = this.generateRecoverySuggestions(dependency);
331
+
332
+ suggestions.immediate.forEach(item => consolidated.immediate.add(item));
333
+ suggestions.alternative.forEach(item => consolidated.alternative.add(item));
334
+ suggestions.troubleshooting.forEach(item => consolidated.troubleshooting.add(item));
335
+ suggestions.additionalResources.forEach(item => consolidated.additionalResources.add(item));
336
+ });
337
+
338
+ return {
339
+ immediate: Array.from(consolidated.immediate),
340
+ alternative: Array.from(consolidated.alternative),
341
+ troubleshooting: Array.from(consolidated.troubleshooting),
342
+ additionalResources: Array.from(consolidated.additionalResources),
343
+ affectedDependencies: failedDependencies.map(dep => dep.name)
344
+ };
345
+ }
346
+ }
347
+
348
+ module.exports = RecoveryInstructionService;
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Restore Service
3
+ * Focused service for restoring Claude Code configuration from backups
4
+ */
5
+
6
+ const path = require('path');
7
+ const fs = require('fs');
8
+ const FileSystemUtils = require('../utils/file-system-utils');
9
+ const ClaudePathConfig = require('../utils/claude-path-config');
10
+
11
+ class RestoreService {
12
+ constructor(config = null) {
13
+ this.config = config || new ClaudePathConfig();
14
+ this.restoredCount = 0;
15
+ }
16
+
17
+ /**
18
+ * Restore from a backup
19
+ */
20
+ async restore(backupName) {
21
+ // Find backup path
22
+ const backupPath = this.findBackupPath(backupName);
23
+ if (!backupPath) {
24
+ throw new Error(`Backup '${backupName}' not found`);
25
+ }
26
+
27
+ // Read metadata if available
28
+ const metadata = await this.readMetadata(backupPath);
29
+ if (metadata) {
30
+ console.log(`📋 Backup created: ${new Date(metadata.timestamp).toLocaleString()}`);
31
+ }
32
+
33
+ // Reset counter
34
+ this.restoredCount = 0;
35
+
36
+ // Restore components
37
+ const results = {};
38
+
39
+ // Restore settings
40
+ results.settings = await this.restoreSettings(backupPath);
41
+
42
+ // Restore commands
43
+ results.commands = await this.restoreCommands(backupPath);
44
+
45
+ // Restore hooks
46
+ results.hooks = await this.restoreHooks(backupPath);
47
+
48
+ return {
49
+ backupName,
50
+ backupPath,
51
+ restoredCount: this.restoredCount,
52
+ results,
53
+ metadata
54
+ };
55
+ }
56
+
57
+ /**
58
+ * Find backup path (compressed or directory)
59
+ */
60
+ findBackupPath(backupName) {
61
+ // Try compressed backup first
62
+ const compressedPath = path.join(this.config.backupsDir, `${backupName}.tar.gz`);
63
+ if (fs.existsSync(compressedPath)) {
64
+ // Would need to extract here in a real implementation
65
+ // For now, look for directory version
66
+ }
67
+
68
+ // Try directory backup
69
+ const directoryPath = path.join(this.config.backupsDir, backupName);
70
+ if (fs.existsSync(directoryPath)) {
71
+ return directoryPath;
72
+ }
73
+
74
+ return null;
75
+ }
76
+
77
+ /**
78
+ * Read backup metadata
79
+ */
80
+ async readMetadata(backupPath) {
81
+ const metadataPath = path.join(backupPath, 'backup-metadata.json');
82
+
83
+ if (!FileSystemUtils.isReadable(metadataPath)) {
84
+ return null;
85
+ }
86
+
87
+ try {
88
+ const content = FileSystemUtils.readFile(metadataPath);
89
+ return JSON.parse(content);
90
+ } catch (error) {
91
+ console.warn(`⚠️ Warning: Could not read backup metadata - ${error.message}`);
92
+ return null;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Restore settings.json
98
+ */
99
+ async restoreSettings(backupPath) {
100
+ const backupSettingsPath = path.join(backupPath, 'settings.json');
101
+
102
+ if (!FileSystemUtils.isReadable(backupSettingsPath)) {
103
+ return { restored: false, reason: 'No settings file in backup' };
104
+ }
105
+
106
+ // Ensure directory exists
107
+ FileSystemUtils.ensureDirectory(this.config.claudeDir);
108
+
109
+ // Copy settings file
110
+ const success = FileSystemUtils.copyFile(backupSettingsPath, this.config.settingsPath);
111
+
112
+ if (success) {
113
+ this.restoredCount++;
114
+ console.log('✅ Restored settings.json');
115
+ return { restored: true };
116
+ } else {
117
+ return { restored: false, reason: 'Failed to copy settings file' };
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Restore commands directory
123
+ */
124
+ async restoreCommands(backupPath) {
125
+ const backupCommandsDir = path.join(backupPath, 'commands');
126
+
127
+ if (!fs.existsSync(backupCommandsDir)) {
128
+ return { restored: false, reason: 'No commands in backup', count: 0 };
129
+ }
130
+
131
+ // Ensure commands directory exists
132
+ FileSystemUtils.ensureDirectory(this.config.commandsDir);
133
+
134
+ // Clear existing commands (backup should be created by caller)
135
+ try {
136
+ const existingCommands = fs.readdirSync(this.config.commandsDir);
137
+ existingCommands.forEach(file => {
138
+ if (file.endsWith('.md')) {
139
+ const filePath = path.join(this.config.commandsDir, file);
140
+ FileSystemUtils.remove(filePath);
141
+ }
142
+ });
143
+ } catch (error) {
144
+ console.warn(`⚠️ Warning: Could not clear existing commands - ${error.message}`);
145
+ }
146
+
147
+ // Restore commands
148
+ let restoredCount = 0;
149
+
150
+ try {
151
+ const commandFiles = fs.readdirSync(backupCommandsDir);
152
+
153
+ for (const file of commandFiles) {
154
+ if (file.endsWith('.md')) {
155
+ const sourcePath = path.join(backupCommandsDir, file);
156
+ const destPath = path.join(this.config.commandsDir, file);
157
+
158
+ if (FileSystemUtils.copyFile(sourcePath, destPath)) {
159
+ restoredCount++;
160
+ this.restoredCount++;
161
+ }
162
+ }
163
+ }
164
+
165
+ if (restoredCount > 0) {
166
+ console.log(`✅ Restored ${restoredCount} commands`);
167
+ }
168
+
169
+ return { restored: true, count: restoredCount };
170
+ } catch (error) {
171
+ return { restored: false, reason: error.message, count: 0 };
172
+ }
173
+ }
174
+
175
+ /**
176
+ * Restore hooks directory
177
+ */
178
+ async restoreHooks(backupPath) {
179
+ const backupHooksDir = path.join(backupPath, 'hooks');
180
+
181
+ if (!fs.existsSync(backupHooksDir)) {
182
+ return { restored: false, reason: 'No hooks in backup', count: 0 };
183
+ }
184
+
185
+ // Ensure hooks directory exists
186
+ FileSystemUtils.ensureDirectory(this.config.hooksDir);
187
+
188
+ let restoredCount = 0;
189
+
190
+ try {
191
+ const hookFiles = fs.readdirSync(backupHooksDir);
192
+
193
+ for (const file of hookFiles) {
194
+ const sourcePath = path.join(backupHooksDir, file);
195
+ const destPath = path.join(this.config.hooksDir, file);
196
+
197
+ // Set appropriate permissions for hooks
198
+ let mode = 0o644;
199
+ if (file.endsWith('.sh')) {
200
+ mode = 0o755; // Executable for shell scripts
201
+ }
202
+
203
+ if (FileSystemUtils.copyFile(sourcePath, destPath)) {
204
+ fs.chmodSync(destPath, mode);
205
+ restoredCount++;
206
+ this.restoredCount++;
207
+ }
208
+ }
209
+
210
+ if (restoredCount > 0) {
211
+ console.log(`✅ Restored ${restoredCount} hooks`);
212
+ }
213
+
214
+ return { restored: true, count: restoredCount };
215
+ } catch (error) {
216
+ return { restored: false, reason: error.message, count: 0 };
217
+ }
218
+ }
219
+ }
220
+
221
+ module.exports = RestoreService;