@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.
- package/README.md +74 -23
- package/bin/claude-commands +263 -64
- package/commands/active/xarchitecture.md +393 -0
- package/commands/active/xconfig.md +127 -0
- package/commands/active/xdebug.md +130 -0
- package/commands/active/xdocs.md +178 -0
- package/commands/active/xgit.md +149 -0
- package/commands/active/xpipeline.md +152 -0
- package/commands/active/xquality.md +96 -0
- package/commands/active/xrefactor.md +198 -0
- package/commands/active/xrelease.md +142 -0
- package/commands/active/xsecurity.md +92 -0
- package/commands/active/xspec.md +174 -0
- package/commands/active/xtdd.md +151 -0
- package/commands/active/xtest.md +89 -0
- package/commands/experiments/xact.md +742 -0
- package/commands/experiments/xanalytics.md +113 -0
- package/commands/experiments/xanalyze.md +70 -0
- package/commands/experiments/xapi.md +161 -0
- package/commands/experiments/xatomic.md +112 -0
- package/commands/experiments/xaws.md +85 -0
- package/commands/experiments/xcicd.md +337 -0
- package/commands/experiments/xcommit.md +122 -0
- package/commands/experiments/xcompliance.md +182 -0
- package/commands/experiments/xconstraints.md +89 -0
- package/commands/experiments/xcoverage.md +90 -0
- package/commands/experiments/xdb.md +102 -0
- package/commands/experiments/xdesign.md +121 -0
- package/commands/experiments/xevaluate.md +111 -0
- package/commands/experiments/xfootnote.md +12 -0
- package/commands/experiments/xgenerate.md +117 -0
- package/commands/experiments/xgovernance.md +149 -0
- package/commands/experiments/xgreen.md +66 -0
- package/commands/experiments/xiac.md +118 -0
- package/commands/experiments/xincident.md +137 -0
- package/commands/experiments/xinfra.md +115 -0
- package/commands/experiments/xknowledge.md +115 -0
- package/commands/experiments/xmaturity.md +120 -0
- package/commands/experiments/xmetrics.md +118 -0
- package/commands/experiments/xmonitoring.md +128 -0
- package/commands/experiments/xnew.md +898 -0
- package/commands/experiments/xobservable.md +114 -0
- package/commands/experiments/xoidc.md +165 -0
- package/commands/experiments/xoptimize.md +115 -0
- package/commands/experiments/xperformance.md +112 -0
- package/commands/experiments/xplanning.md +131 -0
- package/commands/experiments/xpolicy.md +115 -0
- package/commands/experiments/xproduct.md +98 -0
- package/commands/experiments/xreadiness.md +75 -0
- package/commands/experiments/xred.md +55 -0
- package/commands/experiments/xrisk.md +128 -0
- package/commands/experiments/xrules.md +124 -0
- package/commands/experiments/xsandbox.md +120 -0
- package/commands/experiments/xscan.md +102 -0
- package/commands/experiments/xsetup.md +123 -0
- package/commands/experiments/xtemplate.md +116 -0
- package/commands/experiments/xtrace.md +212 -0
- package/commands/experiments/xux.md +171 -0
- package/commands/experiments/xvalidate.md +104 -0
- package/commands/experiments/xworkflow.md +113 -0
- package/hooks/README.md +231 -0
- package/hooks/file-logger.sh +98 -0
- package/hooks/lib/argument-parser.sh +422 -0
- package/hooks/lib/config-constants.sh +230 -0
- package/hooks/lib/context-manager.sh +549 -0
- package/hooks/lib/error-handler.sh +412 -0
- package/hooks/lib/execution-engine.sh +627 -0
- package/hooks/lib/file-utils.sh +375 -0
- package/hooks/lib/subagent-discovery.sh +465 -0
- package/hooks/lib/subagent-validator.sh +597 -0
- package/hooks/on-error-debug.sh +221 -0
- package/hooks/pre-commit-quality.sh +204 -0
- package/hooks/pre-write-security.sh +107 -0
- package/hooks/prevent-credential-exposure.sh +265 -0
- package/hooks/subagent-trigger-simple.sh +193 -0
- package/hooks/subagent-trigger.sh +253 -0
- package/lib/backup-restore-command.js +140 -0
- package/lib/base/base-command.js +252 -0
- package/lib/base/command-result.js +184 -0
- package/lib/config/constants.js +255 -0
- package/lib/config.js +228 -3
- package/lib/configure-command.js +428 -0
- package/lib/dependency-validator.js +64 -5
- package/lib/hook-installer-core.js +2 -2
- package/lib/installation-instruction-generator-backup.js +579 -0
- package/lib/installation-instruction-generator.js +213 -495
- package/lib/installer.js +134 -56
- package/lib/oidc-command.js +363 -0
- package/lib/result.js +138 -0
- package/lib/services/backup-list-service.js +226 -0
- package/lib/services/backup-service.js +230 -0
- package/lib/services/command-installer-service.js +217 -0
- package/lib/services/logger-service.js +201 -0
- package/lib/services/package-manager-service.js +319 -0
- package/lib/services/platform-instruction-service.js +294 -0
- package/lib/services/recovery-instruction-service.js +348 -0
- package/lib/services/restore-service.js +221 -0
- package/lib/setup-command.js +309 -0
- package/lib/subagent-formatter.js +278 -0
- package/lib/subagents-core.js +237 -0
- package/lib/subagents.js +508 -0
- package/lib/types.d.ts +183 -0
- package/lib/utils/claude-path-config.js +184 -0
- package/lib/utils/file-system-utils.js +152 -0
- package/lib/utils.js +8 -4
- package/lib/verify-command.js +430 -0
- package/package.json +17 -4
- package/scripts/postinstall.js +28 -10
- package/subagents/api-guardian.md +29 -0
- package/subagents/audit-trail-verifier.md +24 -0
- package/subagents/change-scoper.md +23 -0
- package/subagents/ci-pipeline-curator.md +24 -0
- package/subagents/code-review-assistant.md +258 -0
- package/subagents/continuous-release-orchestrator.md +29 -0
- package/subagents/contract-tester.md +24 -0
- package/subagents/data-steward.md +29 -0
- package/subagents/debug-context.md +197 -0
- package/subagents/debug-specialist.md +138 -0
- package/subagents/dependency-steward.md +24 -0
- package/subagents/deployment-strategist.md +29 -0
- package/subagents/documentation-curator.md +29 -0
- package/subagents/environment-guardian.md +29 -0
- package/subagents/license-compliance-guardian.md +29 -0
- package/subagents/observability-engineer.md +25 -0
- package/subagents/performance-guardian.md +29 -0
- package/subagents/product-owner-proxy.md +28 -0
- package/subagents/requirements-reviewer.md +26 -0
- package/subagents/rollback-first-responder.md +24 -0
- package/subagents/sbom-provenance.md +25 -0
- package/subagents/security-auditor.md +29 -0
- package/subagents/style-enforcer.md +23 -0
- package/subagents/test-writer.md +24 -0
- package/subagents/trunk-guardian.md +29 -0
- package/subagents/workflow-coordinator.md +26 -0
- package/templates/README.md +100 -0
- package/templates/basic-settings.json +30 -0
- package/templates/comprehensive-settings.json +206 -0
- package/templates/hybrid-hook-config.yaml +133 -0
- package/templates/security-focused-settings.json +62 -0
- package/templates/subagent-hooks.yaml +188 -0
- package/tsconfig.json +37 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Result Value Object
|
|
3
|
+
* Standardized result structure for all command operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class CommandResult {
|
|
7
|
+
constructor(success, data = {}) {
|
|
8
|
+
this.success = success;
|
|
9
|
+
this.timestamp = new Date().toISOString();
|
|
10
|
+
|
|
11
|
+
// Merge provided data
|
|
12
|
+
Object.assign(this, data);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Create successful result
|
|
17
|
+
*/
|
|
18
|
+
static success(data = {}) {
|
|
19
|
+
return new CommandResult(true, data);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Create failure result
|
|
24
|
+
*/
|
|
25
|
+
static failure(error, data = {}) {
|
|
26
|
+
return new CommandResult(false, {
|
|
27
|
+
error: typeof error === 'string' ? error : error.message,
|
|
28
|
+
originalError: typeof error === 'object' ? error : undefined,
|
|
29
|
+
...data
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Create result from boolean
|
|
35
|
+
*/
|
|
36
|
+
static fromBoolean(isSuccess, successData = {}, failureData = {}) {
|
|
37
|
+
return isSuccess
|
|
38
|
+
? CommandResult.success(successData)
|
|
39
|
+
: CommandResult.failure('Operation failed', failureData);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check if result indicates success
|
|
44
|
+
*/
|
|
45
|
+
isSuccess() {
|
|
46
|
+
return this.success === true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Check if result indicates failure
|
|
51
|
+
*/
|
|
52
|
+
isFailure() {
|
|
53
|
+
return this.success === false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Get error message if failure
|
|
58
|
+
*/
|
|
59
|
+
getError() {
|
|
60
|
+
return this.success ? null : (this.error || 'Unknown error');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get data payload
|
|
65
|
+
*/
|
|
66
|
+
getData(key = null) {
|
|
67
|
+
if (key) {
|
|
68
|
+
return this[key];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Return all data except control properties
|
|
72
|
+
const { success, timestamp, error, originalError, ...data } = this;
|
|
73
|
+
return data;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Transform result with a function
|
|
78
|
+
*/
|
|
79
|
+
map(transform) {
|
|
80
|
+
if (this.isFailure()) {
|
|
81
|
+
return this; // Return unchanged failure
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
const transformedData = transform(this.getData());
|
|
86
|
+
return CommandResult.success(transformedData);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
return CommandResult.failure(error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Chain operations that might fail
|
|
94
|
+
*/
|
|
95
|
+
flatMap(operation) {
|
|
96
|
+
if (this.isFailure()) {
|
|
97
|
+
return this; // Return unchanged failure
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
const result = operation(this.getData());
|
|
102
|
+
return result instanceof CommandResult ? result : CommandResult.success(result);
|
|
103
|
+
} catch (error) {
|
|
104
|
+
return CommandResult.failure(error);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Provide fallback value for failures
|
|
110
|
+
*/
|
|
111
|
+
orElse(fallback) {
|
|
112
|
+
return this.isSuccess() ? this.getData() : fallback;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Convert to JSON for serialization
|
|
117
|
+
*/
|
|
118
|
+
toJSON() {
|
|
119
|
+
return {
|
|
120
|
+
success: this.success,
|
|
121
|
+
timestamp: this.timestamp,
|
|
122
|
+
...(this.success ? this.getData() : { error: this.getError() })
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Convert to human-readable string
|
|
128
|
+
*/
|
|
129
|
+
toString() {
|
|
130
|
+
if (this.success) {
|
|
131
|
+
const data = this.getData();
|
|
132
|
+
const keys = Object.keys(data);
|
|
133
|
+
|
|
134
|
+
if (keys.length === 0) {
|
|
135
|
+
return '✅ Success';
|
|
136
|
+
} else if (keys.length === 1) {
|
|
137
|
+
return `✅ Success: ${keys[0]} = ${data[keys[0]]}`;
|
|
138
|
+
} else {
|
|
139
|
+
return `✅ Success (${keys.length} properties)`;
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
return `❌ Failure: ${this.getError()}`;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Merge with another result (for combining operations)
|
|
148
|
+
*/
|
|
149
|
+
merge(otherResult) {
|
|
150
|
+
if (this.isFailure()) return this;
|
|
151
|
+
if (otherResult.isFailure()) return otherResult;
|
|
152
|
+
|
|
153
|
+
return CommandResult.success({
|
|
154
|
+
...this.getData(),
|
|
155
|
+
...otherResult.getData()
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Add metrics to the result
|
|
161
|
+
*/
|
|
162
|
+
withMetrics(metrics) {
|
|
163
|
+
this.metrics = metrics;
|
|
164
|
+
return this;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Add duration to the result
|
|
169
|
+
*/
|
|
170
|
+
withDuration(duration) {
|
|
171
|
+
this.duration = typeof duration === 'number' ? `${duration.toFixed(2)}s` : duration;
|
|
172
|
+
return this;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Add context information
|
|
177
|
+
*/
|
|
178
|
+
withContext(context) {
|
|
179
|
+
this.context = context;
|
|
180
|
+
return this;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
module.exports = CommandResult;
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Constants
|
|
3
|
+
* Centralized configuration constants used throughout the application
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// System Requirements
|
|
7
|
+
const SYSTEM_REQUIREMENTS = {
|
|
8
|
+
MIN_NODE_VERSION: '16.0.0',
|
|
9
|
+
MIN_NPM_VERSION: '7.0.0',
|
|
10
|
+
MIN_MEMORY_GB: 2,
|
|
11
|
+
MIN_DISK_SPACE_MB: 100,
|
|
12
|
+
SUPPORTED_PLATFORMS: ['linux', 'darwin', 'win32'],
|
|
13
|
+
SUPPORTED_ARCHITECTURES: ['x64', 'arm64']
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// Download Links for Dependencies
|
|
17
|
+
const DOWNLOAD_LINKS = {
|
|
18
|
+
git: {
|
|
19
|
+
linux: 'https://git-scm.com/download/linux',
|
|
20
|
+
darwin: 'https://git-scm.com/download/mac',
|
|
21
|
+
win32: 'https://git-scm.com/download/win',
|
|
22
|
+
all: 'https://git-scm.com/downloads'
|
|
23
|
+
},
|
|
24
|
+
node: {
|
|
25
|
+
all: 'https://nodejs.org/en/download/',
|
|
26
|
+
lts: 'https://nodejs.org/en/download/package-manager/',
|
|
27
|
+
docker: 'https://hub.docker.com/_/node'
|
|
28
|
+
},
|
|
29
|
+
python: {
|
|
30
|
+
all: 'https://www.python.org/downloads/',
|
|
31
|
+
anaconda: 'https://www.anaconda.com/products/distribution',
|
|
32
|
+
pyenv: 'https://github.com/pyenv/pyenv'
|
|
33
|
+
},
|
|
34
|
+
docker: {
|
|
35
|
+
linux: 'https://docs.docker.com/engine/install/',
|
|
36
|
+
darwin: 'https://docs.docker.com/desktop/install/mac-install/',
|
|
37
|
+
win32: 'https://docs.docker.com/desktop/install/windows-install/'
|
|
38
|
+
},
|
|
39
|
+
claudeCode: {
|
|
40
|
+
npm: 'https://www.npmjs.com/package/@anthropic-ai/claude-code',
|
|
41
|
+
github: 'https://github.com/anthropics/claude-code'
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Package Manager Commands
|
|
46
|
+
const PACKAGE_MANAGERS = {
|
|
47
|
+
npm: {
|
|
48
|
+
name: 'npm',
|
|
49
|
+
install: 'npm install',
|
|
50
|
+
globalInstall: 'npm install -g',
|
|
51
|
+
update: 'npm update',
|
|
52
|
+
checkCommand: 'npm --version',
|
|
53
|
+
installUrl: 'https://docs.npmjs.com/downloading-and-installing-node-js-and-npm'
|
|
54
|
+
},
|
|
55
|
+
yarn: {
|
|
56
|
+
name: 'yarn',
|
|
57
|
+
install: 'yarn add',
|
|
58
|
+
globalInstall: 'yarn global add',
|
|
59
|
+
update: 'yarn upgrade',
|
|
60
|
+
checkCommand: 'yarn --version',
|
|
61
|
+
installUrl: 'https://classic.yarnpkg.com/lang/en/docs/install/'
|
|
62
|
+
},
|
|
63
|
+
pnpm: {
|
|
64
|
+
name: 'pnpm',
|
|
65
|
+
install: 'pnpm add',
|
|
66
|
+
globalInstall: 'pnpm add -g',
|
|
67
|
+
update: 'pnpm update',
|
|
68
|
+
checkCommand: 'pnpm --version',
|
|
69
|
+
installUrl: 'https://pnpm.io/installation'
|
|
70
|
+
},
|
|
71
|
+
brew: {
|
|
72
|
+
name: 'Homebrew',
|
|
73
|
+
install: 'brew install',
|
|
74
|
+
update: 'brew upgrade',
|
|
75
|
+
checkCommand: 'brew --version',
|
|
76
|
+
installUrl: 'https://brew.sh/',
|
|
77
|
+
platforms: ['darwin']
|
|
78
|
+
},
|
|
79
|
+
apt: {
|
|
80
|
+
name: 'apt',
|
|
81
|
+
install: 'sudo apt install',
|
|
82
|
+
update: 'sudo apt update && sudo apt upgrade',
|
|
83
|
+
checkCommand: 'apt --version',
|
|
84
|
+
platforms: ['linux']
|
|
85
|
+
},
|
|
86
|
+
yum: {
|
|
87
|
+
name: 'yum',
|
|
88
|
+
install: 'sudo yum install',
|
|
89
|
+
update: 'sudo yum update',
|
|
90
|
+
checkCommand: 'yum --version',
|
|
91
|
+
platforms: ['linux']
|
|
92
|
+
},
|
|
93
|
+
chocolatey: {
|
|
94
|
+
name: 'Chocolatey',
|
|
95
|
+
install: 'choco install',
|
|
96
|
+
update: 'choco upgrade',
|
|
97
|
+
checkCommand: 'choco --version',
|
|
98
|
+
installUrl: 'https://chocolatey.org/install',
|
|
99
|
+
platforms: ['win32']
|
|
100
|
+
},
|
|
101
|
+
winget: {
|
|
102
|
+
name: 'winget',
|
|
103
|
+
install: 'winget install',
|
|
104
|
+
update: 'winget upgrade',
|
|
105
|
+
checkCommand: 'winget --version',
|
|
106
|
+
platforms: ['win32']
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
// File and Directory Constants
|
|
111
|
+
const PATHS = {
|
|
112
|
+
CLAUDE_DIR: '.claude',
|
|
113
|
+
COMMANDS_DIR: 'commands',
|
|
114
|
+
HOOKS_DIR: 'hooks',
|
|
115
|
+
BACKUPS_DIR: 'backups',
|
|
116
|
+
SUBAGENTS_DIR: 'subagents',
|
|
117
|
+
SETTINGS_FILE: 'settings.json',
|
|
118
|
+
LOG_FILE: 'claude-commands.log',
|
|
119
|
+
TEMP_DIR: '.temp',
|
|
120
|
+
ACTIVE_COMMANDS: 'active',
|
|
121
|
+
EXPERIMENTAL_COMMANDS: 'experiments'
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// Command Configuration
|
|
125
|
+
const COMMANDS = {
|
|
126
|
+
MAX_COMMANDS: 100,
|
|
127
|
+
DEFAULT_COMMAND_TYPE: 'active',
|
|
128
|
+
SUPPORTED_EXTENSIONS: ['.md', '.txt'],
|
|
129
|
+
FRONTMATTER_DELIMITER: '---',
|
|
130
|
+
REQUIRED_SECTIONS: ['description', 'usage', 'implementation'],
|
|
131
|
+
MAX_FILE_SIZE_MB: 5,
|
|
132
|
+
ENCODING: 'utf8'
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Backup Configuration
|
|
136
|
+
const BACKUP = {
|
|
137
|
+
MAX_BACKUPS: 10,
|
|
138
|
+
COMPRESSION_ENABLED: true,
|
|
139
|
+
COMPRESSION_LEVEL: 6,
|
|
140
|
+
RETENTION_DAYS: 30,
|
|
141
|
+
AUTO_CLEANUP: true,
|
|
142
|
+
BACKUP_FORMAT: 'tar.gz',
|
|
143
|
+
NAMING_PATTERN: 'backup-YYYYMMDD-HHMMSS'
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// Installation Configuration
|
|
147
|
+
const INSTALLATION = {
|
|
148
|
+
MAX_CONCURRENT_OPERATIONS: 5,
|
|
149
|
+
TIMEOUT_MS: 30000,
|
|
150
|
+
RETRY_ATTEMPTS: 3,
|
|
151
|
+
RETRY_DELAY_MS: 1000,
|
|
152
|
+
PROGRESS_UPDATE_INTERVAL: 500,
|
|
153
|
+
VALIDATION_ENABLED: true,
|
|
154
|
+
AUTO_BACKUP: false,
|
|
155
|
+
FORCE_OVERWRITE: false
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// Logging Configuration
|
|
159
|
+
const LOGGING = {
|
|
160
|
+
DEFAULT_LEVEL: 'info',
|
|
161
|
+
LEVELS: ['debug', 'info', 'warn', 'error'],
|
|
162
|
+
MAX_LOG_SIZE_MB: 10,
|
|
163
|
+
MAX_LOG_FILES: 5,
|
|
164
|
+
TIMESTAMP_FORMAT: 'YYYY-MM-DD HH:mm:ss',
|
|
165
|
+
ENABLE_COLORS: true,
|
|
166
|
+
ENABLE_CONTEXT: true
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Security Configuration
|
|
170
|
+
const SECURITY = {
|
|
171
|
+
ALLOWED_PROTOCOLS: ['http:', 'https:', 'file:'],
|
|
172
|
+
MAX_DOWNLOAD_SIZE_MB: 50,
|
|
173
|
+
ALLOWED_FILE_TYPES: ['.md', '.txt', '.json', '.js', '.sh', '.py'],
|
|
174
|
+
DANGEROUS_COMMANDS: ['rm -rf', 'format', 'del /f', 'sudo rm'],
|
|
175
|
+
CREDENTIAL_PATTERNS: [
|
|
176
|
+
/api[_-]?key\s*[:=]\s*['"][^'"]+['"]/i,
|
|
177
|
+
/secret[_-]?key\s*[:=]\s*['"][^'"]+['"]/i,
|
|
178
|
+
/password\s*[:=]\s*['"][^'"]+['"]/i,
|
|
179
|
+
/token\s*[:=]\s*['"][^'"]+['"]/i
|
|
180
|
+
],
|
|
181
|
+
HOOK_TIMEOUT_MS: 5000
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// Error Messages
|
|
185
|
+
const ERROR_MESSAGES = {
|
|
186
|
+
INSTALLATION_FAILED: 'Installation failed. Please check your setup and try again.',
|
|
187
|
+
PERMISSION_DENIED: 'Permission denied. Please check file permissions and try again.',
|
|
188
|
+
NETWORK_ERROR: 'Network error. Please check your internet connection.',
|
|
189
|
+
FILE_NOT_FOUND: 'Required file not found. Please ensure all dependencies are installed.',
|
|
190
|
+
INVALID_CONFIGURATION: 'Invalid configuration. Please check your settings.',
|
|
191
|
+
COMMAND_NOT_FOUND: 'Command not found. Please install required dependencies.',
|
|
192
|
+
VALIDATION_FAILED: 'Validation failed. Please check the input and try again.',
|
|
193
|
+
BACKUP_FAILED: 'Backup operation failed. Please check disk space and permissions.',
|
|
194
|
+
RESTORE_FAILED: 'Restore operation failed. Please check backup integrity.',
|
|
195
|
+
DEPENDENCY_MISSING: 'Required dependency is missing. Please install and try again.'
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// Success Messages
|
|
199
|
+
const SUCCESS_MESSAGES = {
|
|
200
|
+
INSTALLATION_COMPLETE: 'Installation completed successfully!',
|
|
201
|
+
BACKUP_CREATED: 'Backup created successfully.',
|
|
202
|
+
RESTORE_COMPLETE: 'Restore completed successfully.',
|
|
203
|
+
CONFIGURATION_UPDATED: 'Configuration updated successfully.',
|
|
204
|
+
VALIDATION_PASSED: 'All validations passed.',
|
|
205
|
+
CLEANUP_COMPLETE: 'Cleanup completed successfully.'
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// CLI Configuration
|
|
209
|
+
const CLI = {
|
|
210
|
+
PROGRAM_NAME: 'claude-commands',
|
|
211
|
+
VERSION: '1.0.0',
|
|
212
|
+
DESCRIPTION: 'Claude Code Custom Commands CLI',
|
|
213
|
+
DEFAULT_COMMAND: 'help',
|
|
214
|
+
EXIT_CODES: {
|
|
215
|
+
SUCCESS: 0,
|
|
216
|
+
GENERAL_ERROR: 1,
|
|
217
|
+
INVALID_USAGE: 2,
|
|
218
|
+
PERMISSION_DENIED: 3,
|
|
219
|
+
NOT_FOUND: 4,
|
|
220
|
+
NETWORK_ERROR: 5,
|
|
221
|
+
VALIDATION_ERROR: 6
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
// Export all constants
|
|
226
|
+
module.exports = {
|
|
227
|
+
SYSTEM_REQUIREMENTS,
|
|
228
|
+
DOWNLOAD_LINKS,
|
|
229
|
+
PACKAGE_MANAGERS,
|
|
230
|
+
PATHS,
|
|
231
|
+
COMMANDS,
|
|
232
|
+
BACKUP,
|
|
233
|
+
INSTALLATION,
|
|
234
|
+
LOGGING,
|
|
235
|
+
SECURITY,
|
|
236
|
+
ERROR_MESSAGES,
|
|
237
|
+
SUCCESS_MESSAGES,
|
|
238
|
+
CLI
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
// Export individual constants for convenience
|
|
242
|
+
module.exports.constants = {
|
|
243
|
+
SYSTEM_REQUIREMENTS,
|
|
244
|
+
DOWNLOAD_LINKS,
|
|
245
|
+
PACKAGE_MANAGERS,
|
|
246
|
+
PATHS,
|
|
247
|
+
COMMANDS,
|
|
248
|
+
BACKUP,
|
|
249
|
+
INSTALLATION,
|
|
250
|
+
LOGGING,
|
|
251
|
+
SECURITY,
|
|
252
|
+
ERROR_MESSAGES,
|
|
253
|
+
SUCCESS_MESSAGES,
|
|
254
|
+
CLI
|
|
255
|
+
};
|
package/lib/config.js
CHANGED
|
@@ -145,7 +145,7 @@ function getAvailableTemplates(templatesDir) {
|
|
|
145
145
|
id: path.basename(file, '.json'),
|
|
146
146
|
name: file,
|
|
147
147
|
path: templatePath,
|
|
148
|
-
description:
|
|
148
|
+
description: getTemplateDescription(file, data),
|
|
149
149
|
features: Object.keys(data).filter(key => !key.startsWith('//')).length
|
|
150
150
|
});
|
|
151
151
|
} catch (error) {
|
|
@@ -161,6 +161,226 @@ function getAvailableTemplates(templatesDir) {
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Get human-readable description for a template
|
|
166
|
+
* @param {string} filename - Template filename
|
|
167
|
+
* @param {Object} data - Parsed template data
|
|
168
|
+
* @returns {string} - Human-readable description
|
|
169
|
+
*/
|
|
170
|
+
function getTemplateDescription(filename, data) {
|
|
171
|
+
// Check for explicit description in template
|
|
172
|
+
if (data['// Description']) {
|
|
173
|
+
return data['// Description'];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Generate description based on filename
|
|
177
|
+
const basename = path.basename(filename, '.json');
|
|
178
|
+
switch (basename) {
|
|
179
|
+
case 'basic-settings':
|
|
180
|
+
return 'Minimal configuration for getting started with Claude Code';
|
|
181
|
+
case 'comprehensive-settings':
|
|
182
|
+
return 'Full-featured configuration with all available options';
|
|
183
|
+
case 'security-focused-settings':
|
|
184
|
+
return 'Security-enhanced configuration with additional protections';
|
|
185
|
+
default:
|
|
186
|
+
return `Configuration template: ${basename}`;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* GREEN PHASE: Config Command CLI Handler
|
|
192
|
+
* Implements claude-commands config feature requirements
|
|
193
|
+
*/
|
|
194
|
+
class ConfigManager {
|
|
195
|
+
constructor() {
|
|
196
|
+
this.templatesDir = path.join(__dirname, '..', 'templates');
|
|
197
|
+
this.claudeDir = path.join(os.homedir(), '.claude');
|
|
198
|
+
this.settingsPath = path.join(this.claudeDir, 'settings.json');
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// REQ-CONFIG-001: List Templates
|
|
202
|
+
listTemplates() {
|
|
203
|
+
console.log('📋 Available Configuration Templates:\n');
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
if (!fs.existsSync(this.templatesDir)) {
|
|
207
|
+
console.log('❌ Templates directory not found');
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const templates = getAvailableTemplates(this.templatesDir);
|
|
212
|
+
|
|
213
|
+
if (templates.length === 0) {
|
|
214
|
+
console.log('No configuration templates found');
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
templates.forEach(template => {
|
|
219
|
+
console.log(` 📄 ${template.name}`);
|
|
220
|
+
console.log(` ${template.description}`);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
console.log(`\n💡 Usage: claude-commands config --template <name>`);
|
|
224
|
+
} catch (error) {
|
|
225
|
+
console.error('❌ Error listing templates:', error.message);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// REQ-CONFIG-002: Apply Template
|
|
230
|
+
applyTemplate(templateName) {
|
|
231
|
+
try {
|
|
232
|
+
// Resolve template name to full filename
|
|
233
|
+
const resolvedTemplate = this.resolveTemplateName(templateName);
|
|
234
|
+
if (!resolvedTemplate) {
|
|
235
|
+
this.handleTemplateNotFound(templateName);
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const templatePath = path.join(this.templatesDir, resolvedTemplate);
|
|
240
|
+
if (!fs.existsSync(templatePath)) {
|
|
241
|
+
this.handleTemplateNotFound(templateName);
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Ensure Claude directory exists
|
|
246
|
+
this.ensureClaudeDirectory();
|
|
247
|
+
|
|
248
|
+
// Backup existing settings if present
|
|
249
|
+
this.backupExistingSettings();
|
|
250
|
+
|
|
251
|
+
// Apply template using existing function
|
|
252
|
+
const success = applyConfigurationTemplate(templatePath, this.settingsPath);
|
|
253
|
+
|
|
254
|
+
if (success) {
|
|
255
|
+
console.log(`✅ Successfully applied template '${templateName}' (${resolvedTemplate})`);
|
|
256
|
+
console.log(`📝 Configuration saved to: ${this.settingsPath}`);
|
|
257
|
+
return true;
|
|
258
|
+
} else {
|
|
259
|
+
console.error(`❌ Failed to apply template '${templateName}'`);
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
} catch (error) {
|
|
263
|
+
console.error('❌ Error applying template:', error.message);
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Helper method to resolve template names (supports short names)
|
|
269
|
+
resolveTemplateName(templateName) {
|
|
270
|
+
// Return as-is if it already has .json extension
|
|
271
|
+
if (templateName.endsWith('.json')) {
|
|
272
|
+
return templateName;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Map short names to full filenames
|
|
276
|
+
const templateMap = {
|
|
277
|
+
'basic': 'basic-settings.json',
|
|
278
|
+
'comprehensive': 'comprehensive-settings.json',
|
|
279
|
+
'security-focused': 'security-focused-settings.json',
|
|
280
|
+
'security': 'security-focused-settings.json'
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
// Check if it's a known short name
|
|
284
|
+
if (templateMap[templateName]) {
|
|
285
|
+
return templateMap[templateName];
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Try adding .json extension
|
|
289
|
+
const withExtension = `${templateName}.json`;
|
|
290
|
+
if (fs.existsSync(path.join(this.templatesDir, withExtension))) {
|
|
291
|
+
return withExtension;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Try adding -settings.json extension
|
|
295
|
+
const withSettingsExtension = `${templateName}-settings.json`;
|
|
296
|
+
if (fs.existsSync(path.join(this.templatesDir, withSettingsExtension))) {
|
|
297
|
+
return withSettingsExtension;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
// Helper method for template not found error
|
|
304
|
+
handleTemplateNotFound(templateName) {
|
|
305
|
+
console.error(`❌ Template '${templateName}' not found.`);
|
|
306
|
+
this.listTemplates();
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Helper method to ensure Claude directory exists
|
|
310
|
+
ensureClaudeDirectory() {
|
|
311
|
+
if (!fs.existsSync(this.claudeDir)) {
|
|
312
|
+
fs.mkdirSync(this.claudeDir, { recursive: true });
|
|
313
|
+
console.log(`📁 Created directory: ${this.claudeDir}`);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Helper method to backup existing settings
|
|
318
|
+
backupExistingSettings() {
|
|
319
|
+
if (fs.existsSync(this.settingsPath)) {
|
|
320
|
+
const backupPath = this.createBackup();
|
|
321
|
+
console.log(`💾 Backed up existing settings to: ${backupPath}`);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// REQ-CONFIG-002: Backup functionality
|
|
326
|
+
createBackup() {
|
|
327
|
+
const timestamp = new Date().toISOString()
|
|
328
|
+
.replace(/[:.]/g, '-')
|
|
329
|
+
.replace('T', '-')
|
|
330
|
+
.split('.')[0]; // YYYY-MM-DD-HHMMSS format
|
|
331
|
+
|
|
332
|
+
const backupPath = `${this.settingsPath}.backup.${timestamp}`;
|
|
333
|
+
fs.copyFileSync(this.settingsPath, backupPath);
|
|
334
|
+
return backupPath;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// REQ-CONFIG-003: Show Help
|
|
338
|
+
showHelp() {
|
|
339
|
+
console.log('🔧 Claude Commands Config Tool\n');
|
|
340
|
+
console.log('Usage:');
|
|
341
|
+
console.log(' claude-commands config [options]\n');
|
|
342
|
+
console.log('Options:');
|
|
343
|
+
console.log(' -l, --list List available configuration templates');
|
|
344
|
+
console.log(' -t, --template <name> Apply configuration template');
|
|
345
|
+
console.log(' -h, --help Show this help message\n');
|
|
346
|
+
console.log('Examples:');
|
|
347
|
+
console.log(' claude-commands config --list # Show available templates');
|
|
348
|
+
console.log(' claude-commands config --template comprehensive # Apply comprehensive template');
|
|
349
|
+
console.log(' claude-commands config --template basic # Apply basic template');
|
|
350
|
+
console.log(' claude-commands config --help # Show this help\n');
|
|
351
|
+
console.log('Description:');
|
|
352
|
+
console.log(' Manage Claude Code configuration templates. Templates are applied');
|
|
353
|
+
console.log(' to ~/.claude/settings.json with automatic backup of existing settings.');
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Main command handler
|
|
357
|
+
handleCommand(options) {
|
|
358
|
+
// REQ-CONFIG-003: Show help when no options or explicit help
|
|
359
|
+
if (!options.list && !options.template) {
|
|
360
|
+
this.showHelp();
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// REQ-CONFIG-001: List templates
|
|
365
|
+
if (options.list) {
|
|
366
|
+
this.listTemplates();
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// REQ-CONFIG-002: Apply template
|
|
371
|
+
if (options.template) {
|
|
372
|
+
const success = this.applyTemplate(options.template);
|
|
373
|
+
if (!success) {
|
|
374
|
+
process.exit(1);
|
|
375
|
+
}
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Create config manager instance
|
|
382
|
+
const configManager = new ConfigManager();
|
|
383
|
+
|
|
164
384
|
module.exports = {
|
|
165
385
|
getConfigPath: () => {
|
|
166
386
|
return path.join(os.homedir(), '.claude', 'commands');
|
|
@@ -172,11 +392,16 @@ module.exports = {
|
|
|
172
392
|
colorOutput: true
|
|
173
393
|
},
|
|
174
394
|
|
|
175
|
-
// REQ-009 Implementation
|
|
395
|
+
// REQ-009 Implementation (existing)
|
|
176
396
|
applyConfigurationTemplate,
|
|
177
397
|
getAvailableTemplates,
|
|
178
398
|
|
|
179
399
|
// Utility functions (exposed for testing)
|
|
180
400
|
parseJSONC,
|
|
181
|
-
deepMerge
|
|
401
|
+
deepMerge,
|
|
402
|
+
getTemplateDescription,
|
|
403
|
+
|
|
404
|
+
// CLI command handler (new)
|
|
405
|
+
handleCommand: (options) => configManager.handleCommand(options),
|
|
406
|
+
ConfigManager
|
|
182
407
|
};
|