cc-safe-setup 11.5.0 → 11.6.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.
- package/README.md +1 -1
- package/index.mjs +51 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
**One command to make Claude Code safe for autonomous operation.** [日本語](docs/README.ja.md)
|
|
8
8
|
|
|
9
|
-
8 built-in + 104 examples = **118 hooks**.
|
|
9
|
+
8 built-in + 104 examples = **118 hooks**. 41 CLI commands. 561 tests. 5 languages. [**Hub**](https://yurukusa.github.io/cc-safe-setup/hub.html) · [Cheat Sheet](https://yurukusa.github.io/cc-safe-setup/hooks-cheatsheet.html) · [Builder](https://yurukusa.github.io/cc-safe-setup/builder.html) · [FAQ](https://yurukusa.github.io/cc-safe-setup/faq.html) · [Examples](https://yurukusa.github.io/cc-safe-setup/by-example.html) · [Matrix](https://yurukusa.github.io/cc-safe-setup/matrix.html) · [Playground](https://yurukusa.github.io/cc-hook-registry/playground.html)
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
npx cc-safe-setup
|
package/index.mjs
CHANGED
|
@@ -106,6 +106,8 @@ const PROFILE = PROFILE_IDX !== -1 ? process.argv[PROFILE_IDX + 1] : null;
|
|
|
106
106
|
const COMPARE_IDX = process.argv.findIndex(a => a === '--compare');
|
|
107
107
|
const COMPARE = COMPARE_IDX !== -1 ? { a: process.argv[COMPARE_IDX + 1], b: process.argv[COMPARE_IDX + 2] } : null;
|
|
108
108
|
const REPLAY = process.argv.includes('--replay');
|
|
109
|
+
const SAVE_PROFILE_IDX = process.argv.findIndex(a => a === '--save-profile');
|
|
110
|
+
const SAVE_PROFILE = SAVE_PROFILE_IDX !== -1 ? process.argv[SAVE_PROFILE_IDX + 1] : null;
|
|
109
111
|
const CREATE_IDX = process.argv.findIndex(a => a === '--create');
|
|
110
112
|
const CREATE_DESC = CREATE_IDX !== -1 ? process.argv.slice(CREATE_IDX + 1).join(' ') : null;
|
|
111
113
|
const SUGGEST = process.argv.includes('--suggest');
|
|
@@ -142,6 +144,7 @@ if (HELP) {
|
|
|
142
144
|
npx cc-safe-setup --doctor Diagnose why hooks aren't working
|
|
143
145
|
npx cc-safe-setup --watch Live dashboard of blocked commands
|
|
144
146
|
npx cc-safe-setup --create "<desc>" Generate a custom hook from description
|
|
147
|
+
npx cc-safe-setup --save-profile <name> Save current hooks as a named profile
|
|
145
148
|
npx cc-safe-setup --suggest Analyze project and predict risks → suggest hooks
|
|
146
149
|
npx cc-safe-setup --why <hook> Why this hook exists (real incident + issue link)
|
|
147
150
|
npx cc-safe-setup --replay Replay blocked commands timeline (demo/review)
|
|
@@ -928,6 +931,53 @@ async function fullSetup() {
|
|
|
928
931
|
console.log();
|
|
929
932
|
}
|
|
930
933
|
|
|
934
|
+
async function saveProfile(name) {
|
|
935
|
+
const { readdirSync } = await import('fs');
|
|
936
|
+
const profilesDir = join(HOME, '.claude', 'profiles');
|
|
937
|
+
mkdirSync(profilesDir, { recursive: true });
|
|
938
|
+
|
|
939
|
+
if (!name) {
|
|
940
|
+
// List saved profiles
|
|
941
|
+
console.log();
|
|
942
|
+
console.log(c.bold + ' Saved Profiles' + c.reset);
|
|
943
|
+
console.log();
|
|
944
|
+
const files = existsSync(profilesDir) ? readdirSync(profilesDir).filter(f => f.endsWith('.json')) : [];
|
|
945
|
+
if (files.length === 0) {
|
|
946
|
+
console.log(c.dim + ' No saved profiles yet.' + c.reset);
|
|
947
|
+
console.log(c.dim + ' Save: npx cc-safe-setup --save-profile my-setup' + c.reset);
|
|
948
|
+
} else {
|
|
949
|
+
for (const f of files) {
|
|
950
|
+
const pName = f.replace('.json', '');
|
|
951
|
+
const data = JSON.parse(readFileSync(join(profilesDir, f), 'utf-8'));
|
|
952
|
+
console.log(` ${c.bold}${pName}${c.reset} (${data.hooks?.length || 0} hooks, saved ${data.savedAt?.split('T')[0] || '?'})`);
|
|
953
|
+
console.log(c.dim + ` Load: npx cc-safe-setup --profile ${pName}` + c.reset);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
console.log();
|
|
957
|
+
return;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// Save current hook state
|
|
961
|
+
const hookDir = join(HOME, '.claude', 'hooks');
|
|
962
|
+
const hooks = existsSync(hookDir) ? readdirSync(hookDir).filter(f => f.endsWith('.sh') || f.endsWith('.py')) : [];
|
|
963
|
+
|
|
964
|
+
const profile = {
|
|
965
|
+
name,
|
|
966
|
+
savedAt: new Date().toISOString(),
|
|
967
|
+
hooks: hooks.map(h => h.replace(/\.(sh|py)$/, '')),
|
|
968
|
+
settings: existsSync(SETTINGS_PATH) ? JSON.parse(readFileSync(SETTINGS_PATH, 'utf-8')) : {},
|
|
969
|
+
};
|
|
970
|
+
|
|
971
|
+
const profilePath = join(profilesDir, `${name}.json`);
|
|
972
|
+
writeFileSync(profilePath, JSON.stringify(profile, null, 2));
|
|
973
|
+
|
|
974
|
+
console.log();
|
|
975
|
+
console.log(c.green + ` ✓ Profile "${name}" saved (${hooks.length} hooks)` + c.reset);
|
|
976
|
+
console.log(c.dim + ` File: ${profilePath}` + c.reset);
|
|
977
|
+
console.log(c.dim + ` Load: npx cc-safe-setup --profile ${name}` + c.reset);
|
|
978
|
+
console.log();
|
|
979
|
+
}
|
|
980
|
+
|
|
931
981
|
async function suggest() {
|
|
932
982
|
const { execSync } = await import('child_process');
|
|
933
983
|
const { readdirSync } = await import('fs');
|
|
@@ -4261,6 +4311,7 @@ async function main() {
|
|
|
4261
4311
|
if (FULL) return fullSetup();
|
|
4262
4312
|
if (DOCTOR) return doctor();
|
|
4263
4313
|
if (WATCH) return watch();
|
|
4314
|
+
if (SAVE_PROFILE_IDX !== -1) return saveProfile(SAVE_PROFILE);
|
|
4264
4315
|
if (SUGGEST) return suggest();
|
|
4265
4316
|
if (WHY_IDX !== -1) return why(WHY_HOOK);
|
|
4266
4317
|
if (REPLAY) return replay();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cc-safe-setup",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.6.0",
|
|
4
4
|
"description": "One command to make Claude Code safe. 59 hooks (8 built-in + 51 examples). 26 CLI commands: dashboard, create, audit, lint, diff, migrate, compare, generate-ci. 284 tests.",
|
|
5
5
|
"main": "index.mjs",
|
|
6
6
|
"bin": {
|