block-no-verify 1.1.1 → 1.1.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.
package/README.md CHANGED
@@ -8,13 +8,29 @@ When using AI coding assistants like Claude Code, Gemini CLI, Cursor, or others,
8
8
 
9
9
  This package provides a CLI that can block any git commands that include `--no-verify`, working with any AI tool that supports command hooks.
10
10
 
11
+ ## Used By
12
+
13
+ <a href="https://github.com/langgenius/dify">
14
+ <img src="https://github.com/langgenius.png" width="50" height="50" alt="Dify" title="Dify - Open-source LLM app development platform">
15
+ </a>
16
+ <a href="https://centy.io">
17
+ <img src="https://github.com/centy-io.png" width="50" height="50" alt="Centy" title="Centy">
18
+ </a>
19
+ <a href="https://worktree.io">
20
+ <img src="https://github.com/worktree-io.png" width="50" height="50" alt="Worktree" title="Worktree">
21
+ </a>
22
+
11
23
  ## Installation
12
24
 
25
+ Add as a dev dependency to ensure a consistent, pinned version:
26
+
13
27
  ```bash
14
- pnpm add -g block-no-verify
28
+ pnpm add -D block-no-verify
29
+ # or
30
+ npm install --save-dev block-no-verify
15
31
  ```
16
32
 
17
- Or use without installation via `pnpm dlx block-no-verify` or `npx block-no-verify`.
33
+ Then use it with `pnpm exec block-no-verify` or `npm exec block-no-verify`.
18
34
 
19
35
  ## Quick Start
20
36
 
@@ -47,7 +63,7 @@ Add to your `.claude/settings.json`:
47
63
  "hooks": [
48
64
  {
49
65
  "type": "command",
50
- "command": "pnpm dlx block-no-verify"
66
+ "command": "pnpm exec block-no-verify"
51
67
  }
52
68
  ]
53
69
  }
@@ -72,7 +88,7 @@ Add to your `.gemini/settings.json`:
72
88
  {
73
89
  "name": "block-no-verify",
74
90
  "type": "command",
75
- "command": "pnpm dlx block-no-verify",
91
+ "command": "pnpm exec block-no-verify",
76
92
  "description": "Block --no-verify flags in git commands",
77
93
  "timeout": 5000
78
94
  }
@@ -97,7 +113,7 @@ Create `.cursor/hooks.json` in your project root:
97
113
  "hooks": {
98
114
  "beforeShellExecution": [
99
115
  {
100
- "command": "pnpm dlx block-no-verify"
116
+ "command": "pnpm exec block-no-verify"
101
117
  }
102
118
  ]
103
119
  }
@@ -126,7 +142,7 @@ echo '{"tool_input":{"command":"git commit --no-verify"}}' | block-no-verify
126
142
 
127
143
  ## CLI Options
128
144
 
129
- ```
145
+ ```text
130
146
  block-no-verify [options] [command]
131
147
 
132
148
  Options:
@@ -0,0 +1,4 @@
1
+ import type { TestCommand } from './test-command.js';
2
+ /** Commands that should be allowed (no --no-verify or hooks bypass) */
3
+ export declare const ALLOWED_COMMANDS: TestCommand[];
4
+ //# sourceMappingURL=allowed-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowed-commands.d.ts","sourceRoot":"","sources":["../../src/agents/allowed-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,uEAAuE;AACvE,eAAO,MAAM,gBAAgB,EAAE,WAAW,EA4CzC,CAAA"}
@@ -0,0 +1,47 @@
1
+ /** Commands that should be allowed (no --no-verify or hooks bypass) */
2
+ export const ALLOWED_COMMANDS = [
3
+ // Normal git commands
4
+ { command: 'git commit -m "test"', description: 'normal commit' },
5
+ {
6
+ command: 'git commit -m "feat: add feature"',
7
+ description: 'commit with conventional message',
8
+ },
9
+ { command: 'git push origin main', description: 'normal push' },
10
+ { command: 'git push -u origin feature', description: 'push with upstream' },
11
+ { command: 'git merge feature', description: 'normal merge' },
12
+ { command: 'git cherry-pick abc123', description: 'normal cherry-pick' },
13
+ { command: 'git rebase main', description: 'normal rebase' },
14
+ { command: 'git am < patch', description: 'normal am' },
15
+ // Git commands that don't support --no-verify
16
+ { command: 'git status', description: 'git status' },
17
+ { command: 'git log --oneline', description: 'git log' }, // cspell:disable-line
18
+ { command: 'git diff', description: 'git diff' },
19
+ { command: 'git branch -a', description: 'git branch' },
20
+ { command: 'git checkout main', description: 'git checkout' },
21
+ { command: 'git pull origin main', description: 'git pull' },
22
+ { command: 'git fetch --all', description: 'git fetch' },
23
+ { command: 'git stash', description: 'git stash' },
24
+ // Non-git commands
25
+ { command: 'npm install', description: 'npm install' },
26
+ { command: 'pnpm build', description: 'pnpm build' },
27
+ { command: 'yarn test', description: 'yarn test' },
28
+ { command: 'ls -la', description: 'ls command' },
29
+ { command: 'echo "hello"', description: 'echo command' },
30
+ // -n flag in non-commit contexts (different meaning)
31
+ { command: 'git push -n origin main', description: 'push -n (dry-run)' },
32
+ { command: 'git merge -n feature', description: 'merge -n (no commit)' },
33
+ {
34
+ command: 'git cherry-pick -n abc123',
35
+ description: 'cherry-pick -n (no commit)',
36
+ },
37
+ // Commands with special characters
38
+ {
39
+ command: 'git commit -m "feat(scope): add feature #123"',
40
+ description: 'special chars',
41
+ },
42
+ {
43
+ command: 'git commit -m "fix: handle edge case @user"',
44
+ description: '@ mention',
45
+ },
46
+ ];
47
+ //# sourceMappingURL=allowed-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowed-commands.js","sourceRoot":"","sources":["../../src/agents/allowed-commands.ts"],"names":[],"mappings":"AAEA,uEAAuE;AACvE,MAAM,CAAC,MAAM,gBAAgB,GAAkB;IAC7C,sBAAsB;IACtB,EAAE,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,eAAe,EAAE;IACjE;QACE,OAAO,EAAE,mCAAmC;QAC5C,WAAW,EAAE,kCAAkC;KAChD;IACD,EAAE,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,aAAa,EAAE;IAC/D,EAAE,OAAO,EAAE,4BAA4B,EAAE,WAAW,EAAE,oBAAoB,EAAE;IAC5E,EAAE,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,cAAc,EAAE;IAC7D,EAAE,OAAO,EAAE,wBAAwB,EAAE,WAAW,EAAE,oBAAoB,EAAE;IACxE,EAAE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,eAAe,EAAE;IAC5D,EAAE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,WAAW,EAAE;IACvD,8CAA8C;IAC9C,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE;IACpD,EAAE,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,sBAAsB;IAChF,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE;IAChD,EAAE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY,EAAE;IACvD,EAAE,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,cAAc,EAAE;IAC7D,EAAE,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,UAAU,EAAE;IAC5D,EAAE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,WAAW,EAAE;IACxD,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE;IAClD,mBAAmB;IACnB,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE;IACtD,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE;IACpD,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE;IAClD,EAAE,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE;IAChD,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,cAAc,EAAE;IACxD,qDAAqD;IACrD,EAAE,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,mBAAmB,EAAE;IACxE,EAAE,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,sBAAsB,EAAE;IACxE;QACE,OAAO,EAAE,2BAA2B;QACpC,WAAW,EAAE,4BAA4B;KAC1C;IACD,mCAAmC;IACnC;QACE,OAAO,EAAE,+CAA+C;QACxD,WAAW,EAAE,eAAe;KAC7B;IACD;QACE,OAAO,EAAE,6CAA6C;QACtD,WAAW,EAAE,WAAW;KACzB;CACF,CAAA"}
@@ -0,0 +1,4 @@
1
+ import type { TestCommand } from './test-command.js';
2
+ /** Commands that should be blocked (contain --no-verify or hooks bypass) */
3
+ export declare const BLOCKED_COMMANDS: TestCommand[];
4
+ //# sourceMappingURL=blocked-commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocked-commands.d.ts","sourceRoot":"","sources":["../../src/agents/blocked-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,4EAA4E;AAC5E,eAAO,MAAM,gBAAgB,EAAE,WAAW,EAoEzC,CAAA"}
@@ -0,0 +1,71 @@
1
+ /** Commands that should be blocked (contain --no-verify or hooks bypass) */
2
+ export const BLOCKED_COMMANDS = [
3
+ // --no-verify flag
4
+ {
5
+ command: 'git commit --no-verify -m "test"',
6
+ description: 'commit with --no-verify',
7
+ },
8
+ {
9
+ command: 'git commit -m "test" --no-verify',
10
+ description: 'commit with --no-verify at end',
11
+ },
12
+ {
13
+ command: 'git push --no-verify origin main',
14
+ description: 'push with --no-verify',
15
+ },
16
+ {
17
+ command: 'git push origin main --no-verify',
18
+ description: 'push with --no-verify at end',
19
+ },
20
+ {
21
+ command: 'git merge --no-verify feature',
22
+ description: 'merge with --no-verify',
23
+ },
24
+ {
25
+ command: 'git cherry-pick --no-verify abc123',
26
+ description: 'cherry-pick with --no-verify',
27
+ },
28
+ {
29
+ command: 'git rebase --no-verify main',
30
+ description: 'rebase with --no-verify',
31
+ },
32
+ { command: 'git am --no-verify < patch', description: 'am with --no-verify' },
33
+ // -n shorthand (only for commit)
34
+ { command: 'git commit -n -m "test"', description: 'commit with -n flag' },
35
+ { command: 'git commit -m "test" -n', description: 'commit with -n at end' },
36
+ {
37
+ command: 'git commit -nm "test"',
38
+ description: 'commit with combined -nm flags',
39
+ },
40
+ // Edge cases
41
+ {
42
+ command: 'ls && git commit --no-verify -m "test"',
43
+ description: 'chained with --no-verify',
44
+ },
45
+ {
46
+ command: 'git -C /path commit --no-verify -m "test"',
47
+ description: '-C flag with --no-verify',
48
+ },
49
+ {
50
+ command: 'git commit --no-verify -m "test"',
51
+ description: 'extra whitespace',
52
+ },
53
+ // core.hooksPath override (bypass hooks by redirecting hooks directory)
54
+ {
55
+ command: 'git -c core.hooksPath=/dev/null push',
56
+ description: 'hooksPath=/dev/null push',
57
+ },
58
+ {
59
+ command: 'git -c core.hooksPath=/dev/null commit -m "test"',
60
+ description: 'hooksPath commit',
61
+ },
62
+ {
63
+ command: 'git -c core.hooksPath= push origin main',
64
+ description: 'empty hooksPath push',
65
+ },
66
+ {
67
+ command: 'git -c "core.hooksPath=/dev/null" push',
68
+ description: 'quoted hooksPath push',
69
+ },
70
+ ];
71
+ //# sourceMappingURL=blocked-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blocked-commands.js","sourceRoot":"","sources":["../../src/agents/blocked-commands.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAkB;IAC7C,mBAAmB;IACnB;QACE,OAAO,EAAE,kCAAkC;QAC3C,WAAW,EAAE,yBAAyB;KACvC;IACD;QACE,OAAO,EAAE,kCAAkC;QAC3C,WAAW,EAAE,gCAAgC;KAC9C;IACD;QACE,OAAO,EAAE,kCAAkC;QAC3C,WAAW,EAAE,uBAAuB;KACrC;IACD;QACE,OAAO,EAAE,kCAAkC;QAC3C,WAAW,EAAE,8BAA8B;KAC5C;IACD;QACE,OAAO,EAAE,+BAA+B;QACxC,WAAW,EAAE,wBAAwB;KACtC;IACD;QACE,OAAO,EAAE,oCAAoC;QAC7C,WAAW,EAAE,8BAA8B;KAC5C;IACD;QACE,OAAO,EAAE,6BAA6B;QACtC,WAAW,EAAE,yBAAyB;KACvC;IACD,EAAE,OAAO,EAAE,4BAA4B,EAAE,WAAW,EAAE,qBAAqB,EAAE;IAC7E,iCAAiC;IACjC,EAAE,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,qBAAqB,EAAE;IAC1E,EAAE,OAAO,EAAE,yBAAyB,EAAE,WAAW,EAAE,uBAAuB,EAAE;IAC5E;QACE,OAAO,EAAE,uBAAuB;QAChC,WAAW,EAAE,gCAAgC;KAC9C;IACD,aAAa;IACb;QACE,OAAO,EAAE,wCAAwC;QACjD,WAAW,EAAE,0BAA0B;KACxC;IACD;QACE,OAAO,EAAE,2CAA2C;QACpD,WAAW,EAAE,0BAA0B;KACxC;IACD;QACE,OAAO,EAAE,wCAAwC;QACjD,WAAW,EAAE,kBAAkB;KAChC;IACD,wEAAwE;IACxE;QACE,OAAO,EAAE,sCAAsC;QAC/C,WAAW,EAAE,0BAA0B;KACxC;IACD;QACE,OAAO,EAAE,kDAAkD;QAC3D,WAAW,EAAE,kBAAkB;KAChC;IACD;QACE,OAAO,EAAE,yCAAyC;QAClD,WAAW,EAAE,sBAAsB;KACpC;IACD;QACE,OAAO,EAAE,wCAAwC;QACjD,WAAW,EAAE,uBAAuB;KACrC;CACF,CAAA"}
@@ -0,0 +1,5 @@
1
+ export interface TestCommand {
2
+ command: string;
3
+ description: string;
4
+ }
5
+ //# sourceMappingURL=test-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-command.d.ts","sourceRoot":"","sources":["../../src/agents/test-command.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;CACpB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-command.js","sourceRoot":"","sources":["../../src/agents/test-command.ts"],"names":[],"mappings":""}
@@ -1,13 +1,9 @@
1
1
  /**
2
2
  * Test commands for agent format testing
3
3
  */
4
- interface TestCommand {
5
- command: string;
6
- description: string;
7
- }
4
+ export type { TestCommand } from './test-command.js';
8
5
  export declare const testCommands: {
9
- BLOCKED_COMMANDS: TestCommand[];
10
- ALLOWED_COMMANDS: TestCommand[];
6
+ BLOCKED_COMMANDS: import("./test-command.js").TestCommand[];
7
+ ALLOWED_COMMANDS: import("./test-command.js").TestCommand[];
11
8
  };
12
- export {};
13
9
  //# sourceMappingURL=test-commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"test-commands.d.ts","sourceRoot":"","sources":["../../src/agents/test-commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;CACpB;AAiHD,eAAO,MAAM,YAAY;;;CAGxB,CAAA"}
1
+ {"version":3,"file":"test-commands.d.ts","sourceRoot":"","sources":["../../src/agents/test-commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD,eAAO,MAAM,YAAY;;;CAGxB,CAAA"}
@@ -1,109 +1,8 @@
1
1
  /**
2
2
  * Test commands for agent format testing
3
3
  */
4
- /**
5
- * Commands that should be blocked (contain --no-verify)
6
- */
7
- const BLOCKED_COMMANDS = [
8
- // --no-verify flag
9
- {
10
- command: 'git commit --no-verify -m "test"',
11
- description: 'commit with --no-verify',
12
- },
13
- {
14
- command: 'git commit -m "test" --no-verify',
15
- description: 'commit with --no-verify at end',
16
- },
17
- {
18
- command: 'git push --no-verify origin main',
19
- description: 'push with --no-verify',
20
- },
21
- {
22
- command: 'git push origin main --no-verify',
23
- description: 'push with --no-verify at end',
24
- },
25
- {
26
- command: 'git merge --no-verify feature',
27
- description: 'merge with --no-verify',
28
- },
29
- {
30
- command: 'git cherry-pick --no-verify abc123',
31
- description: 'cherry-pick with --no-verify',
32
- },
33
- {
34
- command: 'git rebase --no-verify main',
35
- description: 'rebase with --no-verify',
36
- },
37
- { command: 'git am --no-verify < patch', description: 'am with --no-verify' },
38
- // -n shorthand (only for commit)
39
- { command: 'git commit -n -m "test"', description: 'commit with -n flag' },
40
- { command: 'git commit -m "test" -n', description: 'commit with -n at end' },
41
- {
42
- command: 'git commit -nm "test"',
43
- description: 'commit with combined -nm flags',
44
- },
45
- // Edge cases
46
- {
47
- command: 'ls && git commit --no-verify -m "test"',
48
- description: 'chained command with --no-verify',
49
- },
50
- {
51
- command: 'git -C /path commit --no-verify -m "test"',
52
- description: 'git with -C flag and --no-verify',
53
- },
54
- {
55
- command: 'git commit --no-verify -m "test"',
56
- description: 'extra whitespace with --no-verify',
57
- },
58
- ];
59
- /**
60
- * Commands that should be allowed (no --no-verify)
61
- */
62
- const ALLOWED_COMMANDS = [
63
- // Normal git commands
64
- { command: 'git commit -m "test"', description: 'normal commit' },
65
- {
66
- command: 'git commit -m "feat: add feature"',
67
- description: 'commit with conventional message',
68
- },
69
- { command: 'git push origin main', description: 'normal push' },
70
- { command: 'git push -u origin feature', description: 'push with upstream' },
71
- { command: 'git merge feature', description: 'normal merge' },
72
- { command: 'git cherry-pick abc123', description: 'normal cherry-pick' },
73
- { command: 'git rebase main', description: 'normal rebase' },
74
- { command: 'git am < patch', description: 'normal am' },
75
- // Git commands that don't support --no-verify
76
- { command: 'git status', description: 'git status' },
77
- { command: 'git log --oneline', description: 'git log with oneline' }, // cspell:disable-line
78
- { command: 'git diff', description: 'git diff' },
79
- { command: 'git branch -a', description: 'git branch' },
80
- { command: 'git checkout main', description: 'git checkout' },
81
- { command: 'git pull origin main', description: 'git pull' },
82
- { command: 'git fetch --all', description: 'git fetch' },
83
- { command: 'git stash', description: 'git stash' },
84
- // Non-git commands
85
- { command: 'npm install', description: 'npm install' },
86
- { command: 'pnpm build', description: 'pnpm build' },
87
- { command: 'yarn test', description: 'yarn test' },
88
- { command: 'ls -la', description: 'ls command' },
89
- { command: 'echo "hello"', description: 'echo command' },
90
- // -n flag in non-commit contexts (different meaning)
91
- { command: 'git push -n origin main', description: 'push dry-run with -n' },
92
- { command: 'git merge -n feature', description: 'merge with -n (no commit)' },
93
- {
94
- command: 'git cherry-pick -n abc123',
95
- description: 'cherry-pick with -n (no commit)',
96
- },
97
- // Commands with special characters
98
- {
99
- command: 'git commit -m "feat(scope): add feature #123"',
100
- description: 'commit with special chars',
101
- },
102
- {
103
- command: 'git commit -m "fix: handle edge case @user"',
104
- description: 'commit with @ mention',
105
- },
106
- ];
4
+ import { BLOCKED_COMMANDS } from './blocked-commands.js';
5
+ import { ALLOWED_COMMANDS } from './allowed-commands.js';
107
6
  export const testCommands = {
108
7
  BLOCKED_COMMANDS,
109
8
  ALLOWED_COMMANDS,
@@ -1 +1 @@
1
- {"version":3,"file":"test-commands.js","sourceRoot":"","sources":["../../src/agents/test-commands.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test-commands.js","sourceRoot":"","sources":["../../src/agents/test-commands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAIxD,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,gBAAgB;IAChB,gBAAgB;CACjB,CAAA"}
@@ -1,6 +1,6 @@
1
1
  import type { CheckResult } from './check-result.js';
2
2
  /**
3
- * Checks a command input for --no-verify flag usage
3
+ * Checks a command input for --no-verify flag usage or hooks path override
4
4
  *
5
5
  * @param input - The command input to check (typically from stdin in Claude Code hooks)
6
6
  * @returns CheckResult indicating whether the command should be blocked
@@ -1 +1 @@
1
- {"version":3,"file":"check-command.d.ts","sourceRoot":"","sources":["../src/check-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAIpD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAgBvD"}
1
+ {"version":3,"file":"check-command.d.ts","sourceRoot":"","sources":["../src/check-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAKpD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAwBvD"}
@@ -1,7 +1,8 @@
1
1
  import { detectGitCommand } from './detect-git-command.js';
2
2
  import { hasNoVerifyFlag } from './has-no-verify-flag.js';
3
+ import { hasHooksPathOverride } from './has-hooks-path-override.js';
3
4
  /**
4
- * Checks a command input for --no-verify flag usage
5
+ * Checks a command input for --no-verify flag usage or hooks path override
5
6
  *
6
7
  * @param input - The command input to check (typically from stdin in Claude Code hooks)
7
8
  * @returns CheckResult indicating whether the command should be blocked
@@ -18,6 +19,13 @@ export function checkCommand(input) {
18
19
  gitCommand,
19
20
  };
20
21
  }
22
+ if (hasHooksPathOverride(input)) {
23
+ return {
24
+ blocked: true,
25
+ reason: `BLOCKED: Overriding core.hooksPath is not allowed with git ${gitCommand}. Git hooks must not be bypassed.`,
26
+ gitCommand,
27
+ };
28
+ }
21
29
  return { blocked: false, gitCommand };
22
30
  }
23
31
  //# sourceMappingURL=check-command.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"check-command.js","sourceRoot":"","sources":["../src/check-command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAEzD;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;IAE1C,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;IAC3B,CAAC;IAED,IAAI,eAAe,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC;QACvC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,qDAAqD,UAAU,mCAAmC;YAC1G,UAAU;SACX,CAAA;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAA;AACvC,CAAC"}
1
+ {"version":3,"file":"check-command.js","sourceRoot":"","sources":["../src/check-command.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAEnE;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;IAE1C,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;IAC3B,CAAC;IAED,IAAI,eAAe,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC;QACvC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,qDAAqD,UAAU,mCAAmC;YAC1G,UAAU;SACX,CAAA;IACH,CAAC;IAED,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,8DAA8D,UAAU,mCAAmC;YACnH,UAAU;SACX,CAAA;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAA;AACvC,CAAC"}
package/dist/cli.js CHANGED
File without changes
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Checks if the input contains a -c core.hooksPath= override
3
+ * which is used to bypass git hooks by redirecting the hooks directory
4
+ */
5
+ export declare function hasHooksPathOverride(input: string): boolean;
6
+ //# sourceMappingURL=has-hooks-path-override.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"has-hooks-path-override.d.ts","sourceRoot":"","sources":["../src/has-hooks-path-override.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAI3D"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Checks if the input contains a -c core.hooksPath= override
3
+ * which is used to bypass git hooks by redirecting the hooks directory
4
+ */
5
+ export function hasHooksPathOverride(input) {
6
+ // Match: -c core.hooksPath=<value> with optional quotes around the value
7
+ // Handles: -c core.hooksPath=/dev/null, -c "core.hooksPath=", -c 'core.hooksPath=/tmp'
8
+ return /-c\s+["']?core\.hooksPath\s*=/.test(input);
9
+ }
10
+ //# sourceMappingURL=has-hooks-path-override.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"has-hooks-path-override.js","sourceRoot":"","sources":["../src/has-hooks-path-override.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,yEAAyE;IACzE,uFAAuF;IACvF,OAAO,+BAA+B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AACpD,CAAC"}
package/dist/index.d.ts CHANGED
@@ -10,6 +10,7 @@ export type { CheckResult } from './check-result.js';
10
10
  export { EXIT_CODES } from './exit-codes.js';
11
11
  export { detectGitCommand } from './detect-git-command.js';
12
12
  export { hasNoVerifyFlag } from './has-no-verify-flag.js';
13
+ export { hasHooksPathOverride } from './has-hooks-path-override.js';
13
14
  export { checkCommand } from './check-command.js';
14
15
  export { parseInput } from './parse-input.js';
15
16
  export type { InputFormat } from './input-format.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAA;AACxD,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAA;AACxD,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA"}
package/dist/index.js CHANGED
@@ -8,6 +8,7 @@ export { GIT_COMMANDS_WITH_NO_VERIFY } from './types.js';
8
8
  export { EXIT_CODES } from './exit-codes.js';
9
9
  export { detectGitCommand } from './detect-git-command.js';
10
10
  export { hasNoVerifyFlag } from './has-no-verify-flag.js';
11
+ export { hasHooksPathOverride } from './has-hooks-path-override.js';
11
12
  export { checkCommand } from './check-command.js';
12
13
  export { parseInput } from './parse-input.js';
13
14
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAA;AAGxD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAA;AAGxD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "block-no-verify",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
4
4
  "description": "CLI tool to block --no-verify flag in git commands. Prevents AI agents from bypassing git hooks.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,6 +17,22 @@
17
17
  "files": [
18
18
  "dist"
19
19
  ],
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "dev": "tsc --watch",
23
+ "test": "vitest",
24
+ "test:watch": "vitest --watch",
25
+ "test:coverage": "vitest --coverage",
26
+ "lint": "eslint .",
27
+ "lint:fix": "eslint . --fix",
28
+ "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
29
+ "format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
30
+ "spell": "cspell lint '**/*.{ts,js,md,json}' --gitignore",
31
+ "spell:check": "cspell lint '**/*.{ts,js,md,json}' --gitignore",
32
+ "knip": "knip",
33
+ "prepare": "husky",
34
+ "release": "release-it"
35
+ },
20
36
  "keywords": [
21
37
  "git",
22
38
  "no-verify",
@@ -32,6 +48,7 @@
32
48
  "engines": {
33
49
  "node": ">=20.0.0"
34
50
  },
51
+ "packageManager": "pnpm@10.26.2",
35
52
  "publishConfig": {
36
53
  "access": "public"
37
54
  },
@@ -47,6 +64,7 @@
47
64
  "@commitlint/cli": "^20.3.1",
48
65
  "@commitlint/config-conventional": "^20.3.1",
49
66
  "@cspell/dict-he": "^4.0.5",
67
+ "@release-it/conventional-changelog": "^10.0.6",
50
68
  "@types/node": "^25.0.3",
51
69
  "@vitest/coverage-v8": "^4.0.16",
52
70
  "cspell": "^9.4.0",
@@ -61,20 +79,5 @@
61
79
  "release-it": "^19.2.3",
62
80
  "typescript": "^5.9.3",
63
81
  "vitest": "^4.0.16"
64
- },
65
- "scripts": {
66
- "build": "tsc",
67
- "dev": "tsc --watch",
68
- "test": "vitest",
69
- "test:watch": "vitest --watch",
70
- "test:coverage": "vitest --coverage",
71
- "lint": "eslint .",
72
- "lint:fix": "eslint . --fix",
73
- "format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
74
- "format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
75
- "spell": "cspell lint '**/*.{ts,js,md,json}' --gitignore",
76
- "spell:check": "cspell lint '**/*.{ts,js,md,json}' --gitignore",
77
- "knip": "knip",
78
- "release": "release-it"
79
82
  }
80
- }
83
+ }