xtrm-tools 2.0.3 → 2.1.1

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/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xtrm-cli",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "Claude Code tools installer (skills, hooks, MCP servers)",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",
package/config/hooks.json CHANGED
@@ -12,6 +12,11 @@
12
12
  }
13
13
  ],
14
14
  "PreToolUse": [
15
+ {
16
+ "matcher": "Write|Edit|MultiEdit",
17
+ "script": "main-guard.mjs",
18
+ "timeout": 5000
19
+ },
15
20
  {
16
21
  "matcher": "Read|Edit",
17
22
  "script": "serena-workflow-reminder.py"
@@ -24,6 +29,34 @@
24
29
  {
25
30
  "matcher": "Edit|Write",
26
31
  "script": "type-safety-enforcement.py"
32
+ },
33
+ {
34
+ "matcher": "Grep|Glob|Bash",
35
+ "script": "gitnexus/gitnexus-hook.cjs",
36
+ "timeout": 8000
37
+ },
38
+ {
39
+ "matcher": "Edit|Write|MultiEdit|NotebookEdit|mcp__serena__*",
40
+ "script": "beads-edit-gate.mjs",
41
+ "timeout": 5000
42
+ },
43
+ {
44
+ "matcher": "Bash",
45
+ "script": "beads-commit-gate.mjs",
46
+ "timeout": 5000
47
+ }
48
+ ],
49
+ "PostToolUse": [
50
+ {
51
+ "matcher": "Bash",
52
+ "script": "beads-close-memory-prompt.mjs",
53
+ "timeout": 5000
54
+ }
55
+ ],
56
+ "Stop": [
57
+ {
58
+ "script": "beads-stop-gate.mjs",
59
+ "timeout": 5000
27
60
  }
28
61
  ]
29
62
  },
package/hooks/README.md CHANGED
@@ -154,13 +154,13 @@ Installed globally to `~/.claude/hooks/` by `xtrm install`. Require Node.js.
154
154
  - `git commit` directly on protected branches
155
155
  - `git push` to protected branches
156
156
 
157
- **Configuration** (injected into `~/.claude/settings.json`):
157
+ **Configuration** (global Claude config):
158
158
  ```json
159
159
  {
160
160
  "hooks": {
161
161
  "PreToolUse": [{
162
162
  "matcher": "Edit|Write|MultiEdit|NotebookEdit|Bash",
163
- "hooks": [{ "type": "command", "command": "~/.claude/hooks/main-guard.mjs", "timeout": 5000 }]
163
+ "hooks": [{ "type": "command", "command": "node \"~/.claude/hooks/main-guard.mjs\"", "timeout": 5000 }]
164
164
  }]
165
165
  }
166
166
  }
@@ -256,4 +256,4 @@ Use `xtrm install` to deploy all hooks automatically. For manual setup:
256
256
 
257
257
  3. Merge hook entries into `~/.claude/settings.json`.
258
258
 
259
- 4. Restart Claude Code.
259
+ 4. Restart Claude Code.
@@ -33,11 +33,25 @@ try {
33
33
  }
34
34
 
35
35
  const tool = input.tool_name ?? '';
36
+ const hookEventName = input.hook_event_name ?? 'PreToolUse';
37
+
38
+ function deny(reason) {
39
+ process.stdout.write(JSON.stringify({
40
+ systemMessage: reason,
41
+ hookSpecificOutput: {
42
+ hookEventName,
43
+ permissionDecision: 'deny',
44
+ permissionDecisionReason: reason,
45
+ },
46
+ }));
47
+ process.stdout.write('\n');
48
+ process.exit(0);
49
+ }
36
50
 
37
51
  const WRITE_TOOLS = new Set(['Edit', 'Write', 'MultiEdit', 'NotebookEdit']);
38
52
 
39
53
  if (WRITE_TOOLS.has(tool)) {
40
- process.stderr.write(
54
+ deny(
41
55
  `⛔ You are on '${branch}' — never edit files directly on master.\n\n` +
42
56
  'Full workflow:\n' +
43
57
  ' 1. git checkout -b feature/<name> ← start here\n' +
@@ -48,7 +62,6 @@ if (WRITE_TOOLS.has(tool)) {
48
62
  ' 6. gh pr create --fill && gh pr merge --squash\n' +
49
63
  ' 7. git checkout master && git reset --hard origin/master\n'
50
64
  );
51
- process.exit(2);
52
65
  }
53
66
 
54
67
  const WORKFLOW =
@@ -89,11 +102,10 @@ if (tool === 'Bash') {
89
102
 
90
103
  // Specific messages for common blocked operations
91
104
  if (/^git\s+commit\b/.test(cmd)) {
92
- process.stderr.write(
105
+ deny(
93
106
  `\u26D4 Don't commit directly to '${branch}' \u2014 use a feature branch.\n\n` +
94
107
  WORKFLOW
95
108
  );
96
- process.exit(2);
97
109
  }
98
110
 
99
111
  if (/^git\s+push\b/.test(cmd)) {
@@ -102,7 +114,7 @@ if (tool === 'Bash') {
102
114
  const explicitProtected = protectedBranches.some(b => lastToken === b || lastToken.endsWith(`:${b}`));
103
115
  const impliedProtected = tokens.length <= 3 && protectedBranches.includes(branch);
104
116
  if (explicitProtected || impliedProtected) {
105
- process.stderr.write(
117
+ deny(
106
118
  `\u26D4 Don't push directly to '${branch}' \u2014 use the PR workflow.\n\n` +
107
119
  'Next steps:\n' +
108
120
  ' 5. git push -u origin <feature-branch> \u2190 push your branch\n' +
@@ -113,14 +125,13 @@ if (tool === 'Bash') {
113
125
  "If you're not on a feature branch yet:\n" +
114
126
  ' git checkout -b feature/<name> (then re-commit and push)\n'
115
127
  );
116
- process.exit(2);
117
128
  }
118
129
  // Pushing to a feature branch — allow
119
130
  process.exit(0);
120
131
  }
121
132
 
122
133
  // Default deny — block everything else on protected branches
123
- process.stderr.write(
134
+ deny(
124
135
  `\u26D4 Bash is restricted on '${branch}' \u2014 use a feature branch for file writes and script execution.\n\n` +
125
136
  'Allowed on protected branches:\n' +
126
137
  ' git status / log / diff / branch / fetch / pull / stash\n' +
@@ -133,7 +144,6 @@ if (tool === 'Bash') {
133
144
  ' 1. git checkout -b feature/<name> \u2190 move to a feature branch, or\n' +
134
145
  ' 2. MAIN_GUARD_ALLOW_BASH=1 <command> (escape hatch, use sparingly)\n'
135
146
  );
136
- process.exit(2);
137
147
  }
138
148
 
139
149
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xtrm-tools",
3
- "version": "2.0.3",
3
+ "version": "2.1.1",
4
4
  "description": "Claude Code tools installer (skills, hooks, MCP servers)",
5
5
  "license": "MIT",
6
6
  "type": "module",