cc-safe-setup 11.4.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 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**. 40 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)
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
@@ -0,0 +1,15 @@
1
+ #!/bin/bash
2
+ # aws-region-guard.sh — Warn when AWS commands target unexpected regions
3
+ # TRIGGER: PreToolUse MATCHER: "Bash"
4
+ COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
5
+ [ -z "$COMMAND" ] && exit 0
6
+ echo "$COMMAND" | grep -qE '^\s*aws\s' || exit 0
7
+ EXPECTED="${CC_AWS_REGION:-us-east-1}"
8
+ if echo "$COMMAND" | grep -qE '\-\-region\s+(\S+)'; then
9
+ REGION=$(echo "$COMMAND" | grep -oE '\-\-region\s+(\S+)' | awk '{print $2}')
10
+ if [ "$REGION" != "$EXPECTED" ]; then
11
+ echo "WARNING: AWS command targeting $REGION (expected: $EXPECTED)." >&2
12
+ echo "Verify this is the correct region." >&2
13
+ fi
14
+ fi
15
+ exit 0
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.4.0",
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": {