@claude-code-hooks/cli 0.1.2 → 0.1.4
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/package.json +4 -4
- package/src/cli.js +72 -40
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-code-hooks/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Wizard CLI to set up and manage @claude-code-hooks packages for Claude Code.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/beefiker/claude-code-hooks/tree/main/packages/cli",
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@clack/prompts": "^1.0.0",
|
|
30
30
|
"@claude-code-hooks/core": "0.1.2",
|
|
31
|
-
"@claude-code-hooks/security": "0.1.
|
|
32
|
-
"@claude-code-hooks/secrets": "0.1.
|
|
33
|
-
"@claude-code-hooks/sound": "0.2.
|
|
31
|
+
"@claude-code-hooks/security": "0.1.4",
|
|
32
|
+
"@claude-code-hooks/secrets": "0.1.5",
|
|
33
|
+
"@claude-code-hooks/sound": "0.2.8"
|
|
34
34
|
},
|
|
35
35
|
"keywords": [
|
|
36
36
|
"claude",
|
package/src/cli.js
CHANGED
|
@@ -83,48 +83,65 @@ async function main() {
|
|
|
83
83
|
|
|
84
84
|
intro('claude-code-hooks');
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
86
|
+
// ── Step 1–3: action, target, packages (with simple back navigation) ──
|
|
87
|
+
let action;
|
|
88
|
+
let target;
|
|
89
|
+
let selected;
|
|
90
|
+
|
|
91
|
+
while (true) {
|
|
92
|
+
action = await select({
|
|
93
|
+
message: `${pc.dim('Step 1/5')} Action`,
|
|
94
|
+
options: [
|
|
95
|
+
{ value: 'setup', label: 'Setup / enable packages' },
|
|
96
|
+
{ value: 'uninstall', label: 'Uninstall / remove managed hooks' },
|
|
97
|
+
{ value: 'exit', label: 'Exit' }
|
|
98
|
+
]
|
|
99
|
+
});
|
|
100
|
+
if (isCancel(action) || action === 'exit') dieCancelled('Bye');
|
|
101
|
+
|
|
102
|
+
target = await select({
|
|
103
|
+
message: `${pc.dim('Step 2/5')} Target`,
|
|
104
|
+
options: [
|
|
105
|
+
{ value: 'global', label: `Global (default): ${pc.dim('~/.claude/settings.json')}` },
|
|
106
|
+
{ value: 'projectOnly', label: `Project-only: write ${pc.bold(CONFIG_FILENAME)} + print snippet` },
|
|
107
|
+
{ value: '__back__', label: 'Back' }
|
|
108
|
+
]
|
|
109
|
+
});
|
|
110
|
+
if (isCancel(target)) dieCancelled();
|
|
111
|
+
if (target === '__back__') continue;
|
|
112
|
+
|
|
113
|
+
selected = await multiselect({
|
|
114
|
+
message: `${pc.dim('Step 3/5')} Packages`,
|
|
115
|
+
options: [
|
|
116
|
+
{ value: 'security', label: '@claude-code-hooks/security', hint: 'Warn/block risky commands' },
|
|
117
|
+
{ value: 'secrets', label: '@claude-code-hooks/secrets', hint: 'Detect secret-like tokens' },
|
|
118
|
+
{ value: 'sound', label: '@claude-code-hooks/sound', hint: 'Play sounds on events' }
|
|
119
|
+
],
|
|
120
|
+
required: true
|
|
121
|
+
});
|
|
122
|
+
if (isCancel(selected)) dieCancelled();
|
|
123
|
+
|
|
124
|
+
const proceed = await confirm({ message: 'Continue to configure selected packages?', initialValue: true });
|
|
125
|
+
if (isCancel(proceed)) dieCancelled();
|
|
126
|
+
if (!proceed) continue;
|
|
127
|
+
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
115
130
|
|
|
116
131
|
// Build per-package plan/config
|
|
117
|
-
const perPackage = {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
132
|
+
const perPackage = { security: null, secrets: null, sound: null };
|
|
133
|
+
|
|
134
|
+
// ── Step 4/5: configure ──
|
|
135
|
+
note(
|
|
136
|
+
selected.map((k) => `${pc.bold(k)}: ${pc.dim({ security: 'Warn/block risky commands', secrets: 'Detect secret-like tokens', sound: 'Play sounds on events' }[k] || '')}`).join('\n'),
|
|
137
|
+
`${pc.dim('Step 4/5')} Configure`
|
|
138
|
+
);
|
|
122
139
|
|
|
123
|
-
if (selected.includes('security')) perPackage.security = await planSecuritySetup({ action, projectDir });
|
|
124
|
-
if (selected.includes('secrets')) perPackage.secrets = await planSecretsSetup({ action, projectDir });
|
|
125
|
-
if (selected.includes('sound')) perPackage.sound = await planSoundSetup({ action, projectDir });
|
|
140
|
+
if (selected.includes('security')) perPackage.security = await planSecuritySetup({ action, projectDir, ui: 'umbrella' });
|
|
141
|
+
if (selected.includes('secrets')) perPackage.secrets = await planSecretsSetup({ action, projectDir, ui: 'umbrella' });
|
|
142
|
+
if (selected.includes('sound')) perPackage.sound = await planSoundSetup({ action, projectDir, ui: 'umbrella' });
|
|
126
143
|
|
|
127
|
-
//
|
|
144
|
+
// ── Step 5/5: review ──
|
|
128
145
|
const files = [];
|
|
129
146
|
if (target === 'global') files.push(configPathForScope('global', projectDir));
|
|
130
147
|
if (target === 'projectOnly') {
|
|
@@ -132,12 +149,27 @@ async function main() {
|
|
|
132
149
|
files.push(path.join(projectDir, 'claude-code-hooks.snippet.json (optional)'));
|
|
133
150
|
}
|
|
134
151
|
|
|
152
|
+
function summarizePlan(key, plan) {
|
|
153
|
+
if (!plan) return `${key}: (skipped)`;
|
|
154
|
+
if (action === 'uninstall') return `${key}: remove managed hooks`;
|
|
155
|
+
|
|
156
|
+
const events = plan.snippetHooks ? Object.keys(plan.snippetHooks) : [];
|
|
157
|
+
const list = events.slice(0, 5);
|
|
158
|
+
const tail = events.length > 5 ? ` +${events.length - 5} more` : '';
|
|
159
|
+
return `${key}: ${events.length} event(s)${events.length ? ` (${list.join(', ')}${tail})` : ''}`;
|
|
160
|
+
}
|
|
161
|
+
|
|
135
162
|
note(
|
|
136
163
|
[
|
|
164
|
+
`${pc.dim('Step 5/5')} Review`,
|
|
165
|
+
'',
|
|
137
166
|
`Action: ${pc.bold(action)}`,
|
|
138
167
|
`Target: ${pc.bold(target === 'global' ? 'global settings' : 'project-only')}`,
|
|
139
|
-
|
|
140
|
-
|
|
168
|
+
'',
|
|
169
|
+
`${pc.bold('Packages')}`,
|
|
170
|
+
...selected.map((k) => ` - ${summarizePlan(k, perPackage[k])}`),
|
|
171
|
+
'',
|
|
172
|
+
`${pc.bold('Files')}`,
|
|
141
173
|
...files.map((f) => ` - ${f}`)
|
|
142
174
|
].join('\n'),
|
|
143
175
|
'Review'
|