xtrm-tools 2.0.1 → 2.0.3

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 (29) hide show
  1. package/README.md +0 -2
  2. package/cli/dist/index.cjs +19 -19
  3. package/cli/dist/index.cjs.map +1 -1
  4. package/cli/package.json +1 -1
  5. package/hooks/README.md +107 -4
  6. package/hooks/beads-close-memory-prompt.mjs +49 -0
  7. package/hooks/beads-commit-gate.mjs +64 -0
  8. package/hooks/beads-edit-gate.mjs +72 -0
  9. package/hooks/beads-gate-utils.mjs +121 -0
  10. package/hooks/beads-stop-gate.mjs +61 -0
  11. package/hooks/main-guard.mjs +139 -0
  12. package/package.json +4 -3
  13. package/project-skills/py-quality-gate/.claude/settings.json +1 -1
  14. package/project-skills/service-skills-set/.claude/skills/creating-service-skills/SKILL.md +12 -12
  15. package/project-skills/service-skills-set/.claude/skills/creating-service-skills/references/script_quality_standards.md +13 -0
  16. package/project-skills/service-skills-set/.claude/skills/creating-service-skills/references/service_skill_system_guide.md +14 -0
  17. package/project-skills/service-skills-set/.claude/skills/creating-service-skills/scripts/__pycache__/bootstrap.cpython-314.pyc +0 -0
  18. package/project-skills/service-skills-set/.claude/skills/scoping-service-skills/SKILL.md +6 -6
  19. package/project-skills/service-skills-set/.claude/skills/updating-service-skills/SKILL.md +1 -1
  20. package/project-skills/service-skills-set/.claude/skills/using-service-skills/SKILL.md +2 -2
  21. package/project-skills/service-skills-set/.claude/skills/using-service-skills/scripts/__pycache__/skill_activator.cpython-314.pyc +0 -0
  22. package/project-skills/service-skills-set/.claude/skills/using-service-skills/scripts/__pycache__/test_skill_activator.cpython-314-pytest-9.0.2.pyc +0 -0
  23. package/project-skills/service-skills-set/.claude/skills/using-service-skills/scripts/skill_activator.py +2 -2
  24. package/project-skills/service-skills-set/.claude/skills/using-service-skills/scripts/test_skill_activator.py +58 -0
  25. package/project-skills/ts-quality-gate/.claude/settings.json +1 -1
  26. package/project-skills/main-guard/.claude/hooks/main-guard.cjs +0 -188
  27. package/project-skills/main-guard/.claude/settings.json +0 -16
  28. package/project-skills/main-guard/.claude/skills/using-main-guard/SKILL.md +0 -135
  29. package/project-skills/main-guard/README.md +0 -163
@@ -20,7 +20,7 @@ immediately useful to any agent working on the service.
20
20
 
21
21
  ## Mandatory Two-Phase Workflow
22
22
 
23
- **Both phases are required. Never skip Phase 2.**
23
+ **Use both phases every time.** Phase 1 gives structure; Phase 2 grounds the skill in real service behavior.
24
24
 
25
25
  ---
26
26
 
@@ -65,7 +65,7 @@ python3 "$CLAUDE_PROJECT_DIR/.claude/skills/creating-service-skills/scripts/deep
65
65
 
66
66
  ---
67
67
 
68
- ### Phase 2: Agentic Deep Dive (Non-Negotiable)
68
+ ### Phase 2: Agentic Deep Dive
69
69
 
70
70
  After the skeleton exists, answer every research question by reading the actual
71
71
  source code. Use **Serena LSP tools exclusively** — never read entire files.
@@ -118,10 +118,10 @@ source code. Use **Serena LSP tools exclusively** — never read entire files.
118
118
 
119
119
  ---
120
120
 
121
- ### Phase 2 Script Writing (Required — No Stubs)
121
+ ### Phase 2 Script Writing (Complete Implementation)
122
122
 
123
- After research is complete, replace ALL `[PENDING RESEARCH]` stubs in `scripts/`.
124
- Each script must be fully implemented no TODOs, no placeholder SQL.
123
+ After research is complete, replace all `[PENDING RESEARCH]` stubs in `scripts/`.
124
+ Scripts should be ready to run end-to-end, without TODO markers or placeholder SQL.
125
125
 
126
126
  #### Mandatory DB Connection Pattern (all scripts that touch the DB)
127
127
 
@@ -207,10 +207,10 @@ Required features:
207
207
 
208
208
  See [references/script_quality_standards.md](references/script_quality_standards.md) for complete templates.
209
209
 
210
- #### `scripts/Makefile` (required — always present)
210
+ #### `scripts/Makefile` (required)
211
211
 
212
- The scaffolder creates a stub `Makefile` in Phase 1. In Phase 2 you **must verify it is
213
- correct and complete** it is the primary entry point users and agents use to run diagnostics.
212
+ The scaffolder creates a stub `Makefile` in Phase 1. In Phase 2, verify it is
213
+ correct and complete because it is the primary entry point for diagnostics.
214
214
 
215
215
  **Standard template** (copy verbatim, replace `<service-id>` comment only):
216
216
 
@@ -261,11 +261,11 @@ db:
261
261
 
262
262
  **Rules for the delegated Phase 2 agent:**
263
263
 
264
- 1. **Do not remove or rename the standard targets** they form the stable interface.
264
+ 1. **Keep standard targets stable** avoid removing or renaming them because downstream workflows depend on them.
265
265
  2. **Add service-specific targets** below the standard block if the service needs them (e.g. `make auth`, `make schema`, `make backfill`).
266
- 3. **The `_VENV` auto-detect path (`../../../../venv/bin/python3`) is fixed** — it resolves from `scripts/` → service dir → `skills/` → `.claude/` → project root → `venv/`. Do not change the depth.
267
- 4. **Recipe lines use a real tab character**, not spaces. Makefile syntax requires this.
268
- 5. **Verify with `make help`** after writing the Python path shown must resolve to the project venv, not system python.
266
+ 3. **Keep the `_VENV` auto-detect path (`../../../../venv/bin/python3`) unchanged** — it resolves from `scripts/` → service dir → `skills/` → `.claude/` → project root → `venv/`.
267
+ 4. **Use real tab characters in recipe lines** so Makefile parsing works consistently.
268
+ 5. **Run `make help` after updates** and confirm the Python path resolves to the project venv.
269
269
 
270
270
  ---
271
271
 
@@ -6,6 +6,19 @@
6
6
 
7
7
  ---
8
8
 
9
+ ## Table of Contents
10
+
11
+ - [Mandatory DB Connection Pattern](#mandatory-db-connection-pattern)
12
+ - [Schema Verification Before Writing Any SQL](#schema-verification-before-writing-any-sql)
13
+ - [Makefile Standard](#makefile-standard)
14
+ - [Design Principles](#design-principles)
15
+ - [health_probe.py Standards](#health_probepy-standards)
16
+ - [log_hunter.py Standards](#log_hunterpy-standards)
17
+ - [Specialist Script Standards](#specialist-script-standards)
18
+ - [Common Pitfalls](#common-pitfalls)
19
+
20
+ ---
21
+
9
22
  ## Mandatory DB Connection Pattern
10
23
 
11
24
  **Every script that touches the database MUST use this exact pattern.** No exceptions.
@@ -5,6 +5,20 @@
5
5
 
6
6
  ---
7
7
 
8
+ ## Table of Contents
9
+
10
+ - [1. System Overview](#1-system-overview)
11
+ - [2. System Architecture](#2-system-architecture)
12
+ - [3. Mandatory Two-Phase Workflow](#3-mandatory-two-phase-workflow)
13
+ - [4. Service Type Classification](#4-service-type-classification)
14
+ - [5. Directory Structure](#5-directory-structure)
15
+ - [6. Skill Lifecycle](#6-skill-lifecycle)
16
+ - [7. Quality Gates](#7-quality-gates)
17
+ - [8. Best Practices](#8-best-practices)
18
+ - [9. Anti-Patterns](#9-anti-patterns)
19
+
20
+ ---
21
+
8
22
  ## 1. System Overview
9
23
 
10
24
  The **Service Skill System** transforms an AI agent from a generic assistant into a service-aware operator. Each Docker service in your project gets a dedicated **skill package**: a structured combination of operational documentation and executable diagnostic scripts.
@@ -24,7 +24,7 @@ in the conversation.
24
24
 
25
25
  ### Step 1 — Read the Registry
26
26
 
27
- Run this **immediately**, before any reasoning:
27
+ Run this at the start, before deep task reasoning:
28
28
 
29
29
  ```bash
30
30
  python3 "$CLAUDE_PROJECT_DIR/.claude/skills/scoping-service-skills/scripts/scope.py"
@@ -73,7 +73,7 @@ Using the registry output, reason about which service(s) the task involves. Matc
73
73
 
74
74
  ### Step 4 — Output XML Scope Block
75
75
 
76
- Emit this block **before doing anything else**:
76
+ Emit this block before moving into implementation:
77
77
 
78
78
  ```xml
79
79
  <scope>
@@ -120,15 +120,15 @@ For each `<service>` with `<load>now</load>`, immediately read the skill file:
120
120
  Read: .claude/skills/<service-id>/SKILL.md
121
121
  ```
122
122
 
123
- **Do not proceed with the task until all matched skills are loaded.**
123
+ Load all matched skills before proceeding with the task.
124
124
  Adopt the expert persona, constraints, and diagnostic approach from each loaded skill.
125
125
 
126
126
  ---
127
127
 
128
128
  ### Step 6 — Execute
129
129
 
130
- Follow the workflow phases in order. For `investigation` tasks, **never skip the
131
- regression-test phase**a fix without a test is incomplete.
130
+ Follow the workflow phases in order. For `investigation` tasks, include the
131
+ regression-test phase — it keeps fixes durable.
132
132
 
133
133
  ---
134
134
 
@@ -187,7 +187,7 @@ load-skill → answer
187
187
 
188
188
  ## Regression Test Binding
189
189
 
190
- When `intent = investigation` and a fix has been applied, always write a regression
190
+ When `intent = investigation` and a fix has been applied, write a regression
191
191
  test. Use this decision tree:
192
192
 
193
193
  ```
@@ -109,7 +109,7 @@ Write to:
109
109
  - ✅ `.claude/skills/*/SKILL.md` — skill documentation updates
110
110
  - ✅ `.claude/skills/service-registry.json` — territory and sync timestamp updates
111
111
 
112
- Do not:
112
+ Avoid:
113
113
  - ❌ Modify source code (read-only access to service territories)
114
114
  - ❌ Delete skills or registry entries
115
115
 
@@ -78,8 +78,8 @@ If no registered expert covers the user's need:
78
78
 
79
79
  ## Session Start Hook
80
80
 
81
- The catalog injection is **not** handled by skill frontmatter hooks (SessionStart
82
- is not supported in skill-level hooks). It is configured in `.claude/settings.json`:
81
+ The catalog injection is not handled by skill frontmatter hooks. Configure it in
82
+ `.claude/settings.json` using `SessionStart`:
83
83
 
84
84
  ```json
85
85
  {
@@ -19,7 +19,7 @@ from pathlib import Path
19
19
  BOOTSTRAP_DIR = Path(__file__).parent.parent.parent / "creating-service-skills" / "scripts"
20
20
  sys.path.insert(0, str(BOOTSTRAP_DIR))
21
21
 
22
- from bootstrap import RootResolutionError, get_project_root, load_registry # noqa: E402
22
+ from bootstrap import RootResolutionError, get_project_root, load_registry # noqa: E402 # type: ignore[import-not-found]
23
23
 
24
24
 
25
25
  def match_territory(file_path: str, territory: list[str], project_root: Path) -> bool:
@@ -109,7 +109,7 @@ def main() -> None:
109
109
 
110
110
  try:
111
111
  project_root = Path(get_project_root())
112
- services = load_registry()
112
+ services = load_registry().get("services", {})
113
113
  except (RootResolutionError, Exception):
114
114
  sys.exit(0)
115
115
 
@@ -0,0 +1,58 @@
1
+ """Tests for skill_activator.py — load_registry integration."""
2
+ import io
3
+ import json
4
+ import sys
5
+ import unittest
6
+ from pathlib import Path
7
+ from unittest.mock import patch
8
+
9
+ scripts_dir = Path(__file__).parent
10
+ sys.path.insert(0, str(scripts_dir))
11
+ sys.path.insert(0, str(scripts_dir.parent.parent / "creating-service-skills" / "scripts"))
12
+
13
+ import skill_activator
14
+
15
+
16
+ REGISTRY_WITH_VERSION = {
17
+ "version": "1.0",
18
+ "services": {
19
+ "my-service": {
20
+ "territory": ["src/my-service/**"],
21
+ "name": "My Service",
22
+ "skill_path": ".claude/skills/my-service/SKILL.md",
23
+ }
24
+ },
25
+ }
26
+
27
+ HOOK_INPUT = json.dumps({
28
+ "tool_name": "Write",
29
+ "tool_input": {"file_path": "src/my-service/foo.py"},
30
+ "hook_event_name": "PreToolUse",
31
+ "session_id": "test",
32
+ "cwd": "/fake/project",
33
+ })
34
+
35
+
36
+ class TestMainWithVersionedRegistry(unittest.TestCase):
37
+ def test_main_does_not_crash_when_registry_has_version_key(self):
38
+ """main() must not crash with AttributeError when load_registry returns
39
+ {"version": ..., "services": {...}} — the full registry dict.
40
+ It should output valid JSON context for the matched service.
41
+ """
42
+ with patch("skill_activator.load_registry", return_value=REGISTRY_WITH_VERSION), \
43
+ patch("skill_activator.get_project_root", return_value="/fake/project"), \
44
+ patch("sys.stdin", io.StringIO(HOOK_INPUT)), \
45
+ patch("sys.stdout", new_callable=io.StringIO) as mock_stdout:
46
+ try:
47
+ skill_activator.main()
48
+ except SystemExit:
49
+ pass
50
+ output = mock_stdout.getvalue()
51
+
52
+ self.assertTrue(output, "Expected JSON output but got nothing")
53
+ result = json.loads(output)
54
+ self.assertIn("hookSpecificOutput", result)
55
+
56
+
57
+ if __name__ == "__main__":
58
+ unittest.main()
@@ -2,7 +2,7 @@
2
2
  "hooks": {
3
3
  "PostToolUse": [
4
4
  {
5
- "matcher": "Write|Edit",
5
+ "matcher": "Write|Edit|MultiEdit",
6
6
  "hooks": [
7
7
  {
8
8
  "type": "command",
@@ -1,188 +0,0 @@
1
- #!/usr/bin/env node
2
- /**
3
- * Main Guard - Git branch protection hook for Claude Code.
4
- * Blocks direct edits to main/master branches and enforces feature branch workflow.
5
- *
6
- * Exit codes:
7
- * 0 - Allowed (not on protected branch, or operation allowed)
8
- * 1 - Fatal error
9
- * 2 - Blocked (attempted edit on protected branch)
10
- */
11
-
12
- const { execSync } = require('child_process');
13
- const path = require('path');
14
- const fs = require('fs');
15
-
16
- // Colors
17
- const colors = {
18
- red: '\x1b[0;31m',
19
- green: '\x1b[0;32m',
20
- yellow: '\x1b[0;33m',
21
- blue: '\x1b[0;34m',
22
- cyan: '\x1b[0;36m',
23
- reset: '\x1b[0m',
24
- };
25
-
26
- function log(msg, color = '') {
27
- console.error(`${color}${msg}${colors.reset}`);
28
- }
29
-
30
- function logInfo(msg) { log(`[INFO] ${msg}`, colors.blue); }
31
- function logError(msg) { log(`[ERROR] ${msg}`, colors.red); }
32
- function logSuccess(msg) { log(`[OK] ${msg}`, colors.green); }
33
- function logWarning(msg) { log(`[WARN] ${msg}`, colors.yellow); }
34
-
35
- /**
36
- * Get current git branch name
37
- */
38
- function getCurrentBranch() {
39
- try {
40
- return execSync('git rev-parse --abbrev-ref HEAD', { encoding: 'utf8' }).trim();
41
- } catch (e) {
42
- logWarning('Could not determine git branch');
43
- return null;
44
- }
45
- }
46
-
47
- /**
48
- * Check if branch is protected
49
- */
50
- function isProtectedBranch(branch) {
51
- if (!branch) return false;
52
-
53
- // Get protected branches from config or use defaults
54
- const protectedPatterns = process.env.MAIN_GUARD_PROTECTED_BRANCHES
55
- ? process.env.MAIN_GUARD_PROTECTED_BRANCHES.split(',')
56
- : ['main', 'master', 'develop'];
57
-
58
- return protectedPatterns.some(pattern => {
59
- const regex = new RegExp(`^${pattern.replace('*', '.*')}$`);
60
- return regex.test(branch);
61
- });
62
- }
63
-
64
- /**
65
- * Get feature branch name suggestion based on task
66
- */
67
- function suggestBranchName(input) {
68
- const toolName = input.tool_name || '';
69
- const prompt = input.user_prompt || '';
70
-
71
- // Extract potential task identifier
72
- const match = prompt.match(/(?:issue|ticket|task|bug|feat)[#:-]?\s*(\d+|[a-z-]+)/i) ||
73
- prompt.match(/^([a-z-]+)/i);
74
-
75
- if (match) {
76
- const prefix = toolName.includes('Edit') || toolName.includes('Write') ? 'fix' : 'feat';
77
- return `${prefix}/${match[1].toLowerCase().replace(/\s+/g, '-')}`;
78
- }
79
-
80
- return 'feature/task';
81
- }
82
-
83
- /**
84
- * Parse JSON input from stdin
85
- */
86
- function parseInput() {
87
- let inputData = '';
88
-
89
- try {
90
- inputData = fs.readFileSync(0, 'utf8');
91
- } catch (e) {
92
- return null;
93
- }
94
-
95
- if (!inputData.trim()) {
96
- return null;
97
- }
98
-
99
- try {
100
- return JSON.parse(inputData);
101
- } catch (e) {
102
- logWarning('Invalid JSON input');
103
- return null;
104
- }
105
- }
106
-
107
- /**
108
- * Print blocked message with instructions
109
- */
110
- function printBlocked(branch, suggestedBranch) {
111
- log('', colors.red);
112
- log('═══════════════════════════════════════════════════════════', colors.red);
113
- log(' 🛑 BLOCKED: Direct edits to protected branches', colors.red);
114
- log('═══════════════════════════════════════════════════════════', colors.red);
115
- log('', colors.reset);
116
- log(` Current branch: ${colors.yellow}${branch}${colors.reset}`, colors.reset);
117
- log('', colors.reset);
118
- log(' You cannot edit files directly on a protected branch.', colors.reset);
119
- log(' This prevents accidental commits and enforces code review.', colors.reset);
120
- log('', colors.reset);
121
- log(' 📋 To proceed:', colors.cyan);
122
- log(` 1. Create a feature branch: ${colors.green}git checkout -b ${suggestedBranch}${colors.reset}`, colors.reset);
123
- log(` 2. Make your changes on that branch`, colors.reset);
124
- log(` 3. Push and create a pull request`, colors.reset);
125
- log('', colors.reset);
126
- log('═══════════════════════════════════════════════════════════', colors.red);
127
- log('', colors.reset);
128
- }
129
-
130
- /**
131
- * Print success message
132
- */
133
- function printSuccess(branch) {
134
- log('', colors.green);
135
- log(`✅ Git workflow check passed`, colors.green);
136
- log(` Branch: ${branch}`, colors.green);
137
- log('', colors.reset);
138
- }
139
-
140
- /**
141
- * Main entry point
142
- */
143
- function main() {
144
- log('');
145
- log('🔒 Main Guard - Branch Protection Check', colors.blue);
146
- log('─────────────────────────────────────────', colors.blue);
147
-
148
- // Parse input
149
- const input = parseInput();
150
-
151
- // Get current branch
152
- const branch = getCurrentBranch();
153
-
154
- if (!branch) {
155
- logWarning('Not in a git repository - skipping branch protection');
156
- log('', colors.yellow);
157
- log('👉 Not a git repository - continuing without branch protection', colors.yellow);
158
- log('', colors.reset);
159
- process.exit(0);
160
- }
161
-
162
- logInfo(`Current branch: ${branch}`);
163
-
164
- // Check if protected
165
- if (isProtectedBranch(branch)) {
166
- const suggestedBranch = suggestBranchName(input || {});
167
- printBlocked(branch, suggestedBranch);
168
- process.exit(2);
169
- }
170
-
171
- // Not a protected branch - allow
172
- printSuccess(branch);
173
- process.exit(0);
174
- }
175
-
176
- // Handle errors
177
- process.on('unhandledRejection', (error) => {
178
- logError(`Unhandled error: ${error.message}`);
179
- process.exit(1);
180
- });
181
-
182
- // Run
183
- try {
184
- main();
185
- } catch (error) {
186
- logError(`Fatal error: ${error.message}`);
187
- process.exit(1);
188
- }
@@ -1,16 +0,0 @@
1
- {
2
- "hooks": {
3
- "PreToolUse": [
4
- {
5
- "matcher": "Write|Edit|MultiEdit",
6
- "hooks": [
7
- {
8
- "type": "command",
9
- "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/main-guard.cjs\"",
10
- "timeout": 5
11
- }
12
- ]
13
- }
14
- ]
15
- }
16
- }
@@ -1,135 +0,0 @@
1
- # Using Main Guard
2
-
3
- **Main Guard** enforces Git branch protection by blocking direct edits to protected branches (main, master, develop).
4
-
5
- ## What It Does
6
-
7
- - **Blocks direct edits** to protected branches
8
- - **Enforces feature branch workflow**
9
- - **Suggests branch names** based on your task
10
- - **Prevents accidental commits** to main/master
11
-
12
- ## How It Works
13
-
14
- When you attempt to write or edit files:
15
-
16
- 1. PreToolUse hook fires before Write/Edit
17
- 2. Runs `main-guard.js` to check current branch
18
- 3. If on protected branch: **blocks the action**
19
- 4. If on feature branch: **allows the action**
20
-
21
- ## Protected Branches
22
-
23
- By default, these branches are protected:
24
- - `main`
25
- - `master`
26
- - `develop`
27
-
28
- Customize via environment variable:
29
- ```bash
30
- export MAIN_GUARD_PROTECTED_BRANCHES="main,master,develop,production"
31
- ```
32
-
33
- ## Installation
34
-
35
- ```bash
36
- # Install project skill
37
- xtrm install project main-guard
38
- ```
39
-
40
- ## Usage
41
-
42
- ### When Blocked
43
-
44
- If you try to edit files on a protected branch, you'll see:
45
-
46
- ```
47
- 🛑 BLOCKED: Direct edits to protected branches
48
-
49
- Current branch: main
50
-
51
- You cannot edit files directly on a protected branch.
52
-
53
- 📋 To proceed:
54
- 1. Create a feature branch: git checkout -b feat/task-name
55
- 2. Make your changes on that branch
56
- 3. Push and create a pull request
57
- ```
58
-
59
- ### Branch Name Suggestions
60
-
61
- The hook suggests branch names based on your task:
62
- - `feat/issue-123` - For feature requests
63
- - `fix/bug-456` - For bug fixes
64
- - `feat/description` - For general features
65
-
66
- ## Configuration
67
-
68
- ### Environment Variables
69
-
70
- ```bash
71
- # Custom protected branches
72
- export MAIN_GUARD_PROTECTED_BRANCHES="main,master,develop,staging"
73
-
74
- # Support wildcards
75
- export MAIN_GUARD_PROTECTED_BRANCHES="main,master,release/*,hotfix/*"
76
- ```
77
-
78
- ## Exit Codes
79
-
80
- | Code | Meaning |
81
- |------|---------|
82
- | 0 | Allowed (not on protected branch) |
83
- | 1 | Fatal error |
84
- | 2 | Blocked (on protected branch) |
85
-
86
- ## Workflow
87
-
88
- ### Recommended Git Flow
89
-
90
- ```bash
91
- # Start new feature
92
- git checkout main
93
- git pull origin main
94
- git checkout -b feat/my-feature
95
-
96
- # Make changes (main-guard allows this)
97
- # ... edit files ...
98
-
99
- # Commit and push
100
- git add .
101
- git commit -m "feat: add my feature"
102
- git push -u origin feat/my-feature
103
-
104
- # Create PR on GitHub/GitLab
105
- ```
106
-
107
- ### Hotfix Flow
108
-
109
- ```bash
110
- # Emergency fix
111
- git checkout main
112
- git checkout -b hotfix/urgent-fix
113
-
114
- # Make changes, commit, push
115
- # Create PR with expedited review
116
- ```
117
-
118
- ## Troubleshooting
119
-
120
- **"Not in a git repository"**
121
- - Hook skips gracefully when not in git repo
122
- - No protection applied outside git projects
123
-
124
- **"Could not determine git branch"**
125
- - Ensure git is installed and working
126
- - Check if `.git` folder exists
127
-
128
- **Hook not running**
129
- - Verify PreToolUse hook in `.claude/settings.json`
130
- - Check Node.js is installed
131
-
132
- ## See Also
133
-
134
- - Full documentation: `.claude/docs/main-guard-readme.md`
135
- - Git flow: https://nvie.com/posts/a-successful-git-branching-model/