block-no-verify 1.1.2 → 1.1.5
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 +60 -10
- package/dist/blocked-github-mcp-tool.d.ts +3 -0
- package/dist/blocked-github-mcp-tool.d.ts.map +1 -0
- package/dist/blocked-github-mcp-tool.js +2 -0
- package/dist/blocked-github-mcp-tool.js.map +1 -0
- package/dist/check-command-options.d.ts +11 -0
- package/dist/check-command-options.d.ts.map +1 -0
- package/dist/check-command-options.js +2 -0
- package/dist/check-command-options.js.map +1 -0
- package/dist/check-command.d.ts +9 -4
- package/dist/check-command.d.ts.map +1 -1
- package/dist/check-command.js +17 -4
- package/dist/check-command.js.map +1 -1
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.d.ts.map +1 -1
- package/dist/cli-help.js +6 -3
- package/dist/cli-help.js.map +1 -1
- package/dist/cli.js +4 -2
- package/dist/cli.js.map +1 -1
- package/dist/detect-github-mcp-tool.d.ts +12 -0
- package/dist/detect-github-mcp-tool.d.ts.map +1 -0
- package/dist/detect-github-mcp-tool.js +26 -0
- package/dist/detect-github-mcp-tool.js.map +1 -0
- package/dist/extract-from-json.d.ts +6 -0
- package/dist/extract-from-json.d.ts.map +1 -0
- package/dist/extract-from-json.js +73 -0
- package/dist/extract-from-json.js.map +1 -0
- package/dist/extracted-json.d.ts +8 -0
- package/dist/extracted-json.d.ts.map +1 -0
- package/dist/extracted-json.js +2 -0
- package/dist/extracted-json.js.map +1 -0
- package/dist/get-property.d.ts +5 -0
- package/dist/get-property.d.ts.map +1 -0
- package/dist/get-property.js +13 -0
- package/dist/get-property.js.map +1 -0
- package/dist/github-mcp-tools.d.ts +10 -0
- package/dist/github-mcp-tools.d.ts.map +1 -0
- package/dist/github-mcp-tools.js +18 -0
- package/dist/github-mcp-tools.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/json-helpers.d.ts +5 -0
- package/dist/json-helpers.d.ts.map +1 -0
- package/dist/json-helpers.js +7 -0
- package/dist/json-helpers.js.map +1 -0
- package/dist/parse-input.d.ts.map +1 -1
- package/dist/parse-input.js +21 -102
- package/dist/parse-input.js.map +1 -1
- package/dist/parse-result.d.ts +6 -0
- package/dist/parse-result.d.ts.map +1 -1
- package/package.json +31 -28
package/README.md
CHANGED
|
@@ -1,26 +1,55 @@
|
|
|
1
1
|
# block-no-verify
|
|
2
2
|
|
|
3
|
-
A platform-agnostic security tool that blocks the `--no-verify` flag
|
|
3
|
+
A platform-agnostic security tool that blocks ways AI agents can bypass local git hooks. It flags the `--no-verify` flag, `core.hooksPath` overrides, and GitHub MCP tool calls that write through the GitHub API.
|
|
4
4
|
|
|
5
5
|
## Why?
|
|
6
6
|
|
|
7
|
-
When using AI coding assistants like Claude Code, Gemini CLI, Cursor, or others, you might have git hooks (pre-commit, pre-push) that enforce code quality, run tests, or perform security checks.
|
|
7
|
+
When using AI coding assistants like Claude Code, Gemini CLI, Cursor, or others, you might have git hooks (pre-commit, pre-push) that enforce code quality, run tests, or perform security checks. Agents can side-step those hooks in three common ways:
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- passing `--no-verify` to a git command,
|
|
10
|
+
- overriding `core.hooksPath` (e.g. `git -c core.hooksPath=/dev/null ...`),
|
|
11
|
+
- calling GitHub MCP tools such as `mcp__github__push_files` that commit or merge directly through the GitHub API, skipping the local hook chain entirely.
|
|
12
|
+
|
|
13
|
+
This package provides a CLI that can block all three, working with any AI tool that supports command / tool-use hooks.
|
|
10
14
|
|
|
11
15
|
## Used By
|
|
12
16
|
|
|
13
17
|
<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">
|
|
18
|
+
<img src="https://github.com/langgenius.png" width="50" height="50" alt="Dify" title="Dify - Open-source LLM app development platform (133k★)">
|
|
19
|
+
</a>
|
|
20
|
+
<a href="https://github.com/nicolargo/glances">
|
|
21
|
+
<img src="https://github.com/nicolargo.png" width="50" height="50" alt="Glances" title="Glances - Cross-platform system monitoring tool (32k★)">
|
|
22
|
+
</a>
|
|
23
|
+
<a href="https://github.com/pubkey/rxdb">
|
|
24
|
+
<img src="https://github.com/pubkey.png" width="50" height="50" alt="RxDB" title="RxDB - Local-first database for JavaScript applications (23k★)">
|
|
25
|
+
</a>
|
|
26
|
+
<a href="https://github.com/promptfoo/promptfoo">
|
|
27
|
+
<img src="https://github.com/promptfoo.png" width="50" height="50" alt="Promptfoo" title="Promptfoo - LLM testing and evaluation framework (18k★)">
|
|
28
|
+
</a>
|
|
29
|
+
<a href="https://github.com/YFGaia/dify-plus">
|
|
30
|
+
<img src="https://github.com/YFGaia.png" width="50" height="50" alt="Dify Plus" title="Dify Plus - Enhanced Dify distribution (2k★)">
|
|
31
|
+
</a>
|
|
32
|
+
<a href="https://github.com/forcedotcom/salesforcedx-vscode">
|
|
33
|
+
<img src="https://github.com/forcedotcom.png" width="50" height="50" alt="Salesforce Extensions for VS Code" title="Salesforce Extensions for VS Code (1k★)">
|
|
34
|
+
</a>
|
|
35
|
+
<a href="https://centy.io">
|
|
36
|
+
<img src="https://github.com/centy-io.png" width="50" height="50" alt="Centy" title="Centy">
|
|
37
|
+
</a>
|
|
38
|
+
<a href="https://worktree.io">
|
|
39
|
+
<img src="https://github.com/worktree-io.png" width="50" height="50" alt="Worktree" title="Worktree">
|
|
15
40
|
</a>
|
|
16
41
|
|
|
17
42
|
## Installation
|
|
18
43
|
|
|
44
|
+
Add as a dev dependency to ensure a consistent, pinned version:
|
|
45
|
+
|
|
19
46
|
```bash
|
|
20
|
-
pnpm add -
|
|
47
|
+
pnpm add -D block-no-verify
|
|
48
|
+
# or
|
|
49
|
+
npm install --save-dev block-no-verify
|
|
21
50
|
```
|
|
22
51
|
|
|
23
|
-
|
|
52
|
+
Then use it with `pnpm exec block-no-verify` or `npm exec block-no-verify`.
|
|
24
53
|
|
|
25
54
|
## Quick Start
|
|
26
55
|
|
|
@@ -42,7 +71,7 @@ echo "git push --no-verify" | block-no-verify
|
|
|
42
71
|
|
|
43
72
|
### Claude Code
|
|
44
73
|
|
|
45
|
-
Add to your `.claude/settings.json
|
|
74
|
+
Add to your `.claude/settings.json`. The first matcher handles shell commands (`--no-verify`, `core.hooksPath`); the second matches any GitHub MCP tool so direct-to-API writes can also be blocked:
|
|
46
75
|
|
|
47
76
|
```json
|
|
48
77
|
{
|
|
@@ -53,7 +82,16 @@ Add to your `.claude/settings.json`:
|
|
|
53
82
|
"hooks": [
|
|
54
83
|
{
|
|
55
84
|
"type": "command",
|
|
56
|
-
"command": "pnpm
|
|
85
|
+
"command": "pnpm exec block-no-verify"
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"matcher": "mcp__github__.*",
|
|
91
|
+
"hooks": [
|
|
92
|
+
{
|
|
93
|
+
"type": "command",
|
|
94
|
+
"command": "pnpm exec block-no-verify"
|
|
57
95
|
}
|
|
58
96
|
]
|
|
59
97
|
}
|
|
@@ -78,7 +116,7 @@ Add to your `.gemini/settings.json`:
|
|
|
78
116
|
{
|
|
79
117
|
"name": "block-no-verify",
|
|
80
118
|
"type": "command",
|
|
81
|
-
"command": "pnpm
|
|
119
|
+
"command": "pnpm exec block-no-verify",
|
|
82
120
|
"description": "Block --no-verify flags in git commands",
|
|
83
121
|
"timeout": 5000
|
|
84
122
|
}
|
|
@@ -103,7 +141,7 @@ Create `.cursor/hooks.json` in your project root:
|
|
|
103
141
|
"hooks": {
|
|
104
142
|
"beforeShellExecution": [
|
|
105
143
|
{
|
|
106
|
-
"command": "pnpm
|
|
144
|
+
"command": "pnpm exec block-no-verify"
|
|
107
145
|
}
|
|
108
146
|
]
|
|
109
147
|
}
|
|
@@ -157,6 +195,18 @@ The following git commands are monitored for `--no-verify`:
|
|
|
157
195
|
- `git rebase`
|
|
158
196
|
- `git am`
|
|
159
197
|
|
|
198
|
+
## Blocked GitHub MCP Tools
|
|
199
|
+
|
|
200
|
+
When a Claude Code / MCP-compatible payload includes a `tool_name`, the following GitHub MCP tools are blocked because they write through the GitHub API and therefore skip local git hooks:
|
|
201
|
+
|
|
202
|
+
- `mcp__github__create_or_update_file`
|
|
203
|
+
- `mcp__github__delete_file`
|
|
204
|
+
- `mcp__github__push_files`
|
|
205
|
+
- `mcp__github__merge_pull_request`
|
|
206
|
+
- `mcp__github__update_pull_request_branch`
|
|
207
|
+
|
|
208
|
+
Read-only GitHub MCP tools (e.g. `mcp__github__get_file_contents`, `mcp__github__list_pull_requests`) are not blocked.
|
|
209
|
+
|
|
160
210
|
## Behavior
|
|
161
211
|
|
|
162
212
|
| Command | Blocked? | Notes |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocked-github-mcp-tool.d.ts","sourceRoot":"","sources":["../src/blocked-github-mcp-tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAEhE,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocked-github-mcp-tool.js","sourceRoot":"","sources":["../src/blocked-github-mcp-tool.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional context for {@link checkCommand}.
|
|
3
|
+
*/
|
|
4
|
+
export interface CheckCommandOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Name of the tool being invoked, when available. Used to detect GitHub
|
|
7
|
+
* MCP tool calls that would bypass local git hooks.
|
|
8
|
+
*/
|
|
9
|
+
toolName?: string;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=check-command-options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-command-options.d.ts","sourceRoot":"","sources":["../src/check-command-options.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-command-options.js","sourceRoot":"","sources":["../src/check-command-options.ts"],"names":[],"mappings":""}
|
package/dist/check-command.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
import type { CheckCommandOptions } from './check-command-options.js';
|
|
1
2
|
import type { CheckResult } from './check-result.js';
|
|
2
3
|
/**
|
|
3
|
-
* Checks a command input for --no-verify flag usage
|
|
4
|
+
* Checks a command input for --no-verify flag usage, hooks path override, or
|
|
5
|
+
* a direct GitHub MCP tool invocation that would bypass local git hooks.
|
|
4
6
|
*
|
|
5
|
-
* @param input - The command input to check (typically from stdin in
|
|
6
|
-
*
|
|
7
|
+
* @param input - The command input to check (typically from stdin in AI agent
|
|
8
|
+
* hooks). May be an empty string when the invocation is a non-shell tool
|
|
9
|
+
* call (e.g. an MCP tool).
|
|
10
|
+
* @param options - Optional context such as the invoked tool name.
|
|
11
|
+
* @returns CheckResult indicating whether the command should be blocked.
|
|
7
12
|
*/
|
|
8
|
-
export declare function checkCommand(input: string): CheckResult;
|
|
13
|
+
export declare function checkCommand(input: string, options?: CheckCommandOptions): CheckResult;
|
|
9
14
|
//# sourceMappingURL=check-command.d.ts.map
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"check-command.d.ts","sourceRoot":"","sources":["../src/check-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAMpD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,mBAAmB,GAC5B,WAAW,CAkCb"}
|
package/dist/check-command.js
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
import { detectGitCommand } from './detect-git-command.js';
|
|
2
|
+
import { detectBlockedGithubMcpTool } from './detect-github-mcp-tool.js';
|
|
2
3
|
import { hasNoVerifyFlag } from './has-no-verify-flag.js';
|
|
3
4
|
import { hasHooksPathOverride } from './has-hooks-path-override.js';
|
|
4
5
|
/**
|
|
5
|
-
* Checks a command input for --no-verify flag usage
|
|
6
|
+
* Checks a command input for --no-verify flag usage, hooks path override, or
|
|
7
|
+
* a direct GitHub MCP tool invocation that would bypass local git hooks.
|
|
6
8
|
*
|
|
7
|
-
* @param input - The command input to check (typically from stdin in
|
|
8
|
-
*
|
|
9
|
+
* @param input - The command input to check (typically from stdin in AI agent
|
|
10
|
+
* hooks). May be an empty string when the invocation is a non-shell tool
|
|
11
|
+
* call (e.g. an MCP tool).
|
|
12
|
+
* @param options - Optional context such as the invoked tool name.
|
|
13
|
+
* @returns CheckResult indicating whether the command should be blocked.
|
|
9
14
|
*/
|
|
10
|
-
export function checkCommand(input) {
|
|
15
|
+
export function checkCommand(input, options) {
|
|
16
|
+
const toolName = options === undefined || options === null ? undefined : options.toolName;
|
|
17
|
+
const blockedMcpTool = detectBlockedGithubMcpTool(toolName);
|
|
18
|
+
if (blockedMcpTool !== null) {
|
|
19
|
+
return {
|
|
20
|
+
blocked: true,
|
|
21
|
+
reason: `BLOCKED: ${blockedMcpTool} bypasses local git hooks by writing through the GitHub API. Use local git commands so hooks can run.`,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
11
24
|
const gitCommand = detectGitCommand(input);
|
|
12
25
|
if (!gitCommand) {
|
|
13
26
|
return { blocked: false };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-command.js","sourceRoot":"","sources":["../src/check-command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"check-command.js","sourceRoot":"","sources":["../src/check-command.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAEnE;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAa,EACb,OAA6B;IAE7B,MAAM,QAAQ,GACZ,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAA;IAC1E,MAAM,cAAc,GAAG,0BAA0B,CAAC,QAAQ,CAAC,CAAA;IAC3D,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;QAC5B,OAAO;YACL,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,YAAY,cAAc,uGAAuG;SAC1I,CAAA;IACH,CAAC;IAED,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-help.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLI help text
|
|
3
3
|
*/
|
|
4
|
-
export declare const HELP_TEXT = "block-no-verify - Block --no-verify flags
|
|
4
|
+
export declare const HELP_TEXT = "block-no-verify - Block ways to bypass local git hooks\n\nBlocks --no-verify flags, core.hooksPath overrides, and GitHub MCP tool calls\nthat write through the GitHub API (e.g. mcp__github__push_files).\n\nUSAGE:\n block-no-verify [options] [command]\n\nOPTIONS:\n --format <type> Input format: auto, plain, claude-code, json (default: auto)\n --help, -h Show this help message\n --version, -v Show version number\n\nINPUT METHODS:\n 1. Command argument:\n block-no-verify \"git commit --no-verify -m 'test'\"\n\n 2. Stdin (plain text):\n echo \"git commit --no-verify\" | block-no-verify\n\n 3. Stdin (JSON - auto-detected):\n echo '{\"command\":\"git commit --no-verify\"}' | block-no-verify\n\n 4. Stdin (Claude Code format):\n echo '{\"tool_input\":{\"command\":\"git commit\"}}' | block-no-verify --format claude-code\n\nSUPPORTED JSON FIELDS:\n When using JSON input, the following fields are recognized:\n - tool_input.command (Claude Code format)\n - command\n - cmd\n - input\n - shell\n - script\n\nEXIT CODES:\n 0 - Command / tool call is allowed\n 2 - Command / tool call is blocked (bypasses git hooks)\n 1 - An error occurred\n\nEXAMPLES:\n # Claude Code hook (.claude/settings.json)\n {\n \"hooks\": {\n \"PreToolUse\": [{\n \"matcher\": \"Bash\",\n \"hooks\": [{ \"type\": \"command\", \"command\": \"block-no-verify\" }]\n }]\n }\n }\n\n # Cursor hook (.cursor/hooks.json)\n {\n \"hooks\": {\n \"beforeShellExecution\": [{\n \"command\": \"pnpm dlx block-no-verify\"\n }]\n }\n }\n\n # Generic AI tool integration\n block-no-verify --format plain \"git push --no-verify\"\n\n # Pipe from another command\n your-ai-tool get-command | block-no-verify";
|
|
5
5
|
//# sourceMappingURL=cli-help.d.ts.map
|
package/dist/cli-help.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"cli-help.d.ts","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,SAAS,qvDAgEuB,CAAA"}
|
package/dist/cli-help.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLI help text
|
|
3
3
|
*/
|
|
4
|
-
export const HELP_TEXT = `block-no-verify - Block
|
|
4
|
+
export const HELP_TEXT = `block-no-verify - Block ways to bypass local git hooks
|
|
5
|
+
|
|
6
|
+
Blocks --no-verify flags, core.hooksPath overrides, and GitHub MCP tool calls
|
|
7
|
+
that write through the GitHub API (e.g. mcp__github__push_files).
|
|
5
8
|
|
|
6
9
|
USAGE:
|
|
7
10
|
block-no-verify [options] [command]
|
|
@@ -34,8 +37,8 @@ SUPPORTED JSON FIELDS:
|
|
|
34
37
|
- script
|
|
35
38
|
|
|
36
39
|
EXIT CODES:
|
|
37
|
-
0 - Command is allowed
|
|
38
|
-
2 - Command is blocked (
|
|
40
|
+
0 - Command / tool call is allowed
|
|
41
|
+
2 - Command / tool call is blocked (bypasses git hooks)
|
|
39
42
|
1 - An error occurred
|
|
40
43
|
|
|
41
44
|
EXAMPLES:
|
package/dist/cli-help.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG
|
|
1
|
+
{"version":3,"file":"cli-help.js","sourceRoot":"","sources":["../src/cli-help.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6CAgEoB,CAAA"}
|
package/dist/cli.js
CHANGED
|
@@ -56,8 +56,10 @@ async function main() {
|
|
|
56
56
|
if (!rawInput.trim()) {
|
|
57
57
|
process.exit(EXIT_CODES.ALLOWED);
|
|
58
58
|
}
|
|
59
|
-
const { command } = parseInput(rawInput, args.format);
|
|
60
|
-
const result =
|
|
59
|
+
const { command, toolName } = parseInput(rawInput, args.format);
|
|
60
|
+
const result = toolName === undefined
|
|
61
|
+
? checkCommand(command)
|
|
62
|
+
: checkCommand(command, { toolName });
|
|
61
63
|
if (result.blocked) {
|
|
62
64
|
console.error(result.reason);
|
|
63
65
|
process.exit(EXIT_CODES.BLOCKED);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAErD,MAAM,OAAO,GAAG,OAAO,CAAA;AAEvB,KAAK,UAAU,SAAS;IACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,IAAI,GAAG,EAAE,CAAA;QAEb,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QAEjC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;YAC/B,IAAI,IAAI,KAAK,CAAA;QACf,CAAC,CAAC,CAAA;QAEF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YAC3B,OAAO,CAAC,IAAI,CAAC,CAAA;QACf,CAAC,CAAC,CAAA;QAEF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE;YAC9B,MAAM,CAAC,GAAG,CAAC,CAAA;QACb,CAAC,CAAC,CAAA;QAEF,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACxB,OAAO,CAAC,EAAE,CAAC,CAAA;QACb,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACtB,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAC9D,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAA;IACjD,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;AAChC,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAA;QAE1D,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YACtB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACpB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC;QAED,mCAAmC;QACnC,IAAI,QAAgB,CAAA;QACpB,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC1B,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAA;QACzB,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAA;QAC9B,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAErD,MAAM,OAAO,GAAG,OAAO,CAAA;AAEvB,KAAK,UAAU,SAAS;IACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,IAAI,GAAG,EAAE,CAAA;QAEb,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QAEjC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;YAC/B,IAAI,IAAI,KAAK,CAAA;QACf,CAAC,CAAC,CAAA;QAEF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YAC3B,OAAO,CAAC,IAAI,CAAC,CAAA;QACf,CAAC,CAAC,CAAA;QAEF,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE;YAC9B,MAAM,CAAC,GAAG,CAAC,CAAA;QACb,CAAC,CAAC,CAAA;QAEF,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACxB,OAAO,CAAC,EAAE,CAAC,CAAA;QACb,CAAC;IACH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACtB,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAA;IAC9D,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAA;IACjD,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;AAChC,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAA;QAE1D,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;YACtB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;YACpB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC;QAED,mCAAmC;QACnC,IAAI,QAAgB,CAAA;QACpB,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC1B,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAA;QACzB,CAAC;aAAM,CAAC;YACN,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAA;QAC9B,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QAC/D,MAAM,MAAM,GACV,QAAQ,KAAK,SAAS;YACpB,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC;YACvB,CAAC,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;QAEzC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YAC5B,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACtE,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QAChC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IAChC,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { BlockedGithubMcpTool } from './blocked-github-mcp-tool.js';
|
|
2
|
+
/**
|
|
3
|
+
* Checks whether a tool name refers to a GitHub MCP tool that bypasses local
|
|
4
|
+
* git hooks.
|
|
5
|
+
*
|
|
6
|
+
* @param toolName - The tool name reported by the AI agent (e.g. from a
|
|
7
|
+
* Claude Code `PreToolUse` payload).
|
|
8
|
+
* @returns The matched blocked tool name, or null when the tool is not a
|
|
9
|
+
* blocked GitHub MCP tool.
|
|
10
|
+
*/
|
|
11
|
+
export declare function detectBlockedGithubMcpTool(toolName: string | undefined | null): BlockedGithubMcpTool | null;
|
|
12
|
+
//# sourceMappingURL=detect-github-mcp-tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-github-mcp-tool.d.ts","sourceRoot":"","sources":["../src/detect-github-mcp-tool.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAGxE;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAClC,oBAAoB,GAAG,IAAI,CAiB7B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BLOCKED_GITHUB_MCP_TOOLS } from './github-mcp-tools.js';
|
|
2
|
+
/**
|
|
3
|
+
* Checks whether a tool name refers to a GitHub MCP tool that bypasses local
|
|
4
|
+
* git hooks.
|
|
5
|
+
*
|
|
6
|
+
* @param toolName - The tool name reported by the AI agent (e.g. from a
|
|
7
|
+
* Claude Code `PreToolUse` payload).
|
|
8
|
+
* @returns The matched blocked tool name, or null when the tool is not a
|
|
9
|
+
* blocked GitHub MCP tool.
|
|
10
|
+
*/
|
|
11
|
+
export function detectBlockedGithubMcpTool(toolName) {
|
|
12
|
+
if (toolName === undefined || toolName === null) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const trimmed = toolName.trim();
|
|
16
|
+
if (trimmed === '') {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
for (const blocked of BLOCKED_GITHUB_MCP_TOOLS) {
|
|
20
|
+
if (trimmed === blocked) {
|
|
21
|
+
return blocked;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=detect-github-mcp-tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-github-mcp-tool.js","sourceRoot":"","sources":["../src/detect-github-mcp-tool.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAEhE;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CACxC,QAAmC;IAEnC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAA;IAC/B,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,wBAAwB,EAAE,CAAC;QAC/C,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YACxB,OAAO,OAAO,CAAA;QAChB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ExtractedJson } from './extracted-json.js';
|
|
2
|
+
/**
|
|
3
|
+
* Attempts to parse input as JSON and extract the command + tool name.
|
|
4
|
+
*/
|
|
5
|
+
export declare function tryExtractFromJson(input: string): ExtractedJson | null;
|
|
6
|
+
//# sourceMappingURL=extract-from-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-from-json.d.ts","sourceRoot":"","sources":["../src/extract-from-json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAuDxD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CA6BtE"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { getProperty } from './get-property.js';
|
|
2
|
+
import { hasProperty } from './json-helpers.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extracts a `tool_name` field when present at the top level of the JSON
|
|
5
|
+
* payload (Claude Code / Gemini CLI shape).
|
|
6
|
+
*/
|
|
7
|
+
function extractToolName(parsed) {
|
|
8
|
+
if (!hasProperty(parsed, 'tool_name')) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const value = getProperty(parsed, 'tool_name');
|
|
12
|
+
if (typeof value === 'string') {
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
function extractClaudeCodeCommand(parsed, toolName) {
|
|
18
|
+
if (!hasProperty(parsed, 'tool_input')) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const toolInput = getProperty(parsed, 'tool_input');
|
|
22
|
+
if (typeof toolInput === 'object' && toolInput !== null) {
|
|
23
|
+
if (hasProperty(toolInput, 'command')) {
|
|
24
|
+
const command = getProperty(toolInput, 'command');
|
|
25
|
+
if (typeof command === 'string') {
|
|
26
|
+
return { command, toolName };
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// tool_input present without a string command (e.g. MCP tool invocation).
|
|
31
|
+
return { command: null, toolName };
|
|
32
|
+
}
|
|
33
|
+
function extractGenericCommand(parsed, toolName) {
|
|
34
|
+
const genericKeys = ['command', 'cmd', 'input', 'shell', 'script'];
|
|
35
|
+
for (const key of genericKeys) {
|
|
36
|
+
if (hasProperty(parsed, key)) {
|
|
37
|
+
const value = getProperty(parsed, key);
|
|
38
|
+
if (typeof value === 'string') {
|
|
39
|
+
return { command: value, toolName };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Attempts to parse input as JSON and extract the command + tool name.
|
|
47
|
+
*/
|
|
48
|
+
export function tryExtractFromJson(input) {
|
|
49
|
+
try {
|
|
50
|
+
const parsed = JSON.parse(input);
|
|
51
|
+
if (typeof parsed !== 'object' || parsed === null) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const toolName = extractToolName(parsed);
|
|
55
|
+
const claudeCode = extractClaudeCodeCommand(parsed, toolName);
|
|
56
|
+
if (claudeCode !== null) {
|
|
57
|
+
return claudeCode;
|
|
58
|
+
}
|
|
59
|
+
const generic = extractGenericCommand(parsed, toolName);
|
|
60
|
+
if (generic !== null) {
|
|
61
|
+
return generic;
|
|
62
|
+
}
|
|
63
|
+
// JSON parsed but no recognized command field. Still surface tool name.
|
|
64
|
+
if (toolName !== null) {
|
|
65
|
+
return { command: null, toolName };
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=extract-from-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-from-json.js","sourceRoot":"","sources":["../src/extract-from-json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extracted-json.d.ts","sourceRoot":"","sources":["../src/extracted-json.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extracted-json.js","sourceRoot":"","sources":["../src/extracted-json.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-property.d.ts","sourceRoot":"","sources":["../src/get-property.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ7D"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type-safe property access using Object.entries
|
|
3
|
+
*/
|
|
4
|
+
export function getProperty(obj, key) {
|
|
5
|
+
const entries = Object.entries(obj);
|
|
6
|
+
for (const entry of entries) {
|
|
7
|
+
if (entry[0] === key) {
|
|
8
|
+
return entry[1];
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=get-property.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-property.js","sourceRoot":"","sources":["../src/get-property.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,GAAW;IAClD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACnC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub MCP tools that bypass local git hooks.
|
|
3
|
+
*
|
|
4
|
+
* These MCP tools communicate directly with the GitHub API, meaning they do
|
|
5
|
+
* not trigger local pre-commit, pre-push, commit-msg, or other client-side
|
|
6
|
+
* hooks. Blocking them prevents AI agents from side-stepping the validations
|
|
7
|
+
* enforced by those hooks.
|
|
8
|
+
*/
|
|
9
|
+
export declare const BLOCKED_GITHUB_MCP_TOOLS: readonly ["mcp__github__create_or_update_file", "mcp__github__delete_file", "mcp__github__push_files", "mcp__github__merge_pull_request", "mcp__github__update_pull_request_branch"];
|
|
10
|
+
//# sourceMappingURL=github-mcp-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-mcp-tools.d.ts","sourceRoot":"","sources":["../src/github-mcp-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,wBAAwB,sLAQ3B,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub MCP tools that bypass local git hooks.
|
|
3
|
+
*
|
|
4
|
+
* These MCP tools communicate directly with the GitHub API, meaning they do
|
|
5
|
+
* not trigger local pre-commit, pre-push, commit-msg, or other client-side
|
|
6
|
+
* hooks. Blocking them prevents AI agents from side-stepping the validations
|
|
7
|
+
* enforced by those hooks.
|
|
8
|
+
*/
|
|
9
|
+
export const BLOCKED_GITHUB_MCP_TOOLS = [
|
|
10
|
+
// Content writes that bypass pre-commit / commit-msg hooks
|
|
11
|
+
'mcp__github__create_or_update_file',
|
|
12
|
+
'mcp__github__delete_file',
|
|
13
|
+
'mcp__github__push_files',
|
|
14
|
+
// Branch / merge operations that bypass pre-push hooks
|
|
15
|
+
'mcp__github__merge_pull_request',
|
|
16
|
+
'mcp__github__update_pull_request_branch',
|
|
17
|
+
];
|
|
18
|
+
//# sourceMappingURL=github-mcp-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-mcp-tools.js","sourceRoot":"","sources":["../src/github-mcp-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,2DAA2D;IAC3D,oCAAoC;IACpC,0BAA0B;IAC1B,yBAAyB;IACzB,uDAAuD;IACvD,iCAAiC;IACjC,yCAAyC;CACjC,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,11 @@ 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
13
|
export { hasHooksPathOverride } from './has-hooks-path-override.js';
|
|
14
|
+
export { detectBlockedGithubMcpTool } from './detect-github-mcp-tool.js';
|
|
15
|
+
export { BLOCKED_GITHUB_MCP_TOOLS } from './github-mcp-tools.js';
|
|
16
|
+
export type { BlockedGithubMcpTool } from './blocked-github-mcp-tool.js';
|
|
14
17
|
export { checkCommand } from './check-command.js';
|
|
18
|
+
export type { CheckCommandOptions } from './check-command-options.js';
|
|
15
19
|
export { parseInput } from './parse-input.js';
|
|
16
20
|
export type { InputFormat } from './input-format.js';
|
|
17
21
|
export type { ParseResult } from './parse-result.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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,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"}
|
|
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,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAChE,YAAY,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AACrE,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
|
@@ -9,6 +9,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
11
|
export { hasHooksPathOverride } from './has-hooks-path-override.js';
|
|
12
|
+
export { detectBlockedGithubMcpTool } from './detect-github-mcp-tool.js';
|
|
13
|
+
export { BLOCKED_GITHUB_MCP_TOOLS } from './github-mcp-tools.js';
|
|
12
14
|
export { checkCommand } from './check-command.js';
|
|
13
15
|
export { parseInput } from './parse-input.js';
|
|
14
16
|
//# 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,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,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,0BAA0B,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AAEhE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-helpers.d.ts","sourceRoot":"","sources":["../src/json-helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE7D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-helpers.js","sourceRoot":"","sources":["../src/json-helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,GAAW;IAClD,OAAO,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;AACvD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-input.d.ts","sourceRoot":"","sources":["../src/parse-input.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parse-input.d.ts","sourceRoot":"","sources":["../src/parse-input.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA8CpD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,WAAW,CAmB3E"}
|
package/dist/parse-input.js
CHANGED
|
@@ -1,111 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const parsed = JSON.parse(input);
|
|
7
|
-
if (typeof parsed !== 'object' || parsed === null) {
|
|
8
|
-
return null;
|
|
9
|
-
}
|
|
10
|
-
// Check for Claude Code format: { tool_input: { command: "..." } }
|
|
11
|
-
if (hasProperty(parsed, 'tool_input')) {
|
|
12
|
-
const toolInput = getProperty(parsed, 'tool_input');
|
|
13
|
-
if (typeof toolInput === 'object' && toolInput !== null) {
|
|
14
|
-
if (hasProperty(toolInput, 'command')) {
|
|
15
|
-
const command = getProperty(toolInput, 'command');
|
|
16
|
-
if (typeof command === 'string') {
|
|
17
|
-
return command;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
// Generic JSON formats
|
|
23
|
-
const genericKeys = ['command', 'cmd', 'input', 'shell', 'script'];
|
|
24
|
-
for (const key of genericKeys) {
|
|
25
|
-
if (hasProperty(parsed, key)) {
|
|
26
|
-
const value = getProperty(parsed, key);
|
|
27
|
-
if (typeof value === 'string') {
|
|
28
|
-
return value;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
// If JSON but no recognized command field, return null
|
|
33
|
-
return null;
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
// Not valid JSON
|
|
37
|
-
return null;
|
|
1
|
+
import { tryExtractFromJson } from './extract-from-json.js';
|
|
2
|
+
function resolveExtracted(input) {
|
|
3
|
+
const extracted = tryExtractFromJson(input);
|
|
4
|
+
if (extracted === null) {
|
|
5
|
+
return { command: input, toolName: null };
|
|
38
6
|
}
|
|
7
|
+
return {
|
|
8
|
+
command: extracted.command === null ? input : extracted.command,
|
|
9
|
+
toolName: extracted.toolName,
|
|
10
|
+
};
|
|
39
11
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
function hasProperty(obj, key) {
|
|
44
|
-
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Type-safe property access using Object.entries
|
|
48
|
-
*/
|
|
49
|
-
function getProperty(obj, key) {
|
|
50
|
-
const entries = Object.entries(obj);
|
|
51
|
-
for (const entry of entries) {
|
|
52
|
-
if (entry[0] === key) {
|
|
53
|
-
return entry[1];
|
|
54
|
-
}
|
|
12
|
+
function buildResult(command, format, toolName) {
|
|
13
|
+
if (toolName === null) {
|
|
14
|
+
return { command, format };
|
|
55
15
|
}
|
|
56
|
-
return
|
|
16
|
+
return { command, format, toolName };
|
|
57
17
|
}
|
|
58
|
-
/**
|
|
59
|
-
* Parses input in Claude Code format
|
|
60
|
-
*/
|
|
61
|
-
function parseClaudeCode(input) {
|
|
62
|
-
try {
|
|
63
|
-
const parsed = JSON.parse(input);
|
|
64
|
-
if (typeof parsed !== 'object' || parsed === null) {
|
|
65
|
-
return input;
|
|
66
|
-
}
|
|
67
|
-
if (hasProperty(parsed, 'tool_input')) {
|
|
68
|
-
const toolInput = getProperty(parsed, 'tool_input');
|
|
69
|
-
if (typeof toolInput === 'object' && toolInput !== null) {
|
|
70
|
-
if (hasProperty(toolInput, 'command')) {
|
|
71
|
-
const command = getProperty(toolInput, 'command');
|
|
72
|
-
if (typeof command === 'string') {
|
|
73
|
-
return command;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return input;
|
|
79
|
-
}
|
|
80
|
-
catch {
|
|
81
|
-
// If not valid JSON, treat as plain text
|
|
82
|
-
return input;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Parses input in generic JSON format
|
|
87
|
-
*/
|
|
88
|
-
function parseJson(input) {
|
|
89
|
-
const command = tryParseJson(input);
|
|
90
|
-
if (command !== null) {
|
|
91
|
-
return command;
|
|
92
|
-
}
|
|
93
|
-
return input;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Auto-detects format and parses input
|
|
97
|
-
*/
|
|
98
18
|
function parseAuto(input) {
|
|
99
19
|
const trimmed = input.trim();
|
|
100
|
-
// Try JSON first if it looks like JSON
|
|
101
20
|
if (trimmed.startsWith('{')) {
|
|
102
|
-
const
|
|
103
|
-
if (
|
|
104
|
-
return
|
|
21
|
+
const extracted = tryExtractFromJson(trimmed);
|
|
22
|
+
if (extracted !== null) {
|
|
23
|
+
return buildResult(extracted.command === null ? input : extracted.command, 'json', extracted.toolName);
|
|
105
24
|
}
|
|
106
25
|
}
|
|
107
|
-
|
|
108
|
-
return { command: input, format: 'plain' };
|
|
26
|
+
return buildResult(input, 'plain', null);
|
|
109
27
|
}
|
|
110
28
|
/**
|
|
111
29
|
* Parses input according to the specified format
|
|
@@ -135,12 +53,13 @@ export function parseInput(input, format) {
|
|
|
135
53
|
return { command: input, format: 'plain' };
|
|
136
54
|
}
|
|
137
55
|
if (resolvedFormat === 'claude-code') {
|
|
138
|
-
|
|
56
|
+
const extracted = resolveExtracted(input);
|
|
57
|
+
return buildResult(extracted.command, 'claude-code', extracted.toolName);
|
|
139
58
|
}
|
|
140
59
|
if (resolvedFormat === 'json') {
|
|
141
|
-
|
|
60
|
+
const extracted = resolveExtracted(input);
|
|
61
|
+
return buildResult(extracted.command, 'json', extracted.toolName);
|
|
142
62
|
}
|
|
143
|
-
// resolvedFormat === 'auto'
|
|
144
63
|
return parseAuto(input);
|
|
145
64
|
}
|
|
146
65
|
//# sourceMappingURL=parse-input.js.map
|
package/dist/parse-input.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-input.js","sourceRoot":"","sources":["../src/parse-input.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parse-input.js","sourceRoot":"","sources":["../src/parse-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAS3D,SAAS,gBAAgB,CAAC,KAAa;IACrC,MAAM,SAAS,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAC3C,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;IAC3C,CAAC;IACD,OAAO;QACL,OAAO,EAAE,SAAS,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO;QAC/D,QAAQ,EAAE,SAAS,CAAC,QAAQ;KAC7B,CAAA;AACH,CAAC;AAED,SAAS,WAAW,CAClB,OAAe,EACf,MAAmB,EACnB,QAAuB;IAEvB,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;IAC5B,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;AACtC,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAE5B,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAA;QAC7C,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,OAAO,WAAW,CAChB,SAAS,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,EACtD,MAAM,EACN,SAAS,CAAC,QAAQ,CACnB,CAAA;QACH,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;AAC1C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,MAAoB;IAC5D,MAAM,cAAc,GAClB,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAA;IAE3D,IAAI,cAAc,KAAK,OAAO,EAAE,CAAC;QAC/B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;IAC5C,CAAC;IAED,IAAI,cAAc,KAAK,aAAa,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;QACzC,OAAO,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAA;IAC1E,CAAC;IAED,IAAI,cAAc,KAAK,MAAM,EAAE,CAAC;QAC9B,MAAM,SAAS,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;QACzC,OAAO,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAA;IACnE,CAAC;IAED,OAAO,SAAS,CAAC,KAAK,CAAC,CAAA;AACzB,CAAC"}
|
package/dist/parse-result.d.ts
CHANGED
|
@@ -5,5 +5,11 @@ import type { InputFormat } from './input-format.js';
|
|
|
5
5
|
export interface ParseResult {
|
|
6
6
|
command: string;
|
|
7
7
|
format: InputFormat;
|
|
8
|
+
/**
|
|
9
|
+
* Name of the tool being invoked, when the input format exposes it (e.g.
|
|
10
|
+
* Claude Code's `tool_name` field). Used to detect direct GitHub MCP calls
|
|
11
|
+
* that would bypass local git hooks.
|
|
12
|
+
*/
|
|
13
|
+
toolName?: string;
|
|
8
14
|
}
|
|
9
15
|
//# sourceMappingURL=parse-result.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parse-result.d.ts","sourceRoot":"","sources":["../src/parse-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"parse-result.d.ts","sourceRoot":"","sources":["../src/parse-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAEpD;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,WAAW,CAAA;IACnB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "block-no-verify",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
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
|
},
|
|
@@ -44,37 +61,23 @@
|
|
|
44
61
|
},
|
|
45
62
|
"homepage": "https://github.com/tupe12334/block-no-verify#readme",
|
|
46
63
|
"devDependencies": {
|
|
47
|
-
"@commitlint/cli": "^20.
|
|
48
|
-
"@commitlint/config-conventional": "^20.
|
|
64
|
+
"@commitlint/cli": "^20.5.0",
|
|
65
|
+
"@commitlint/config-conventional": "^20.5.0",
|
|
49
66
|
"@cspell/dict-he": "^4.0.5",
|
|
50
|
-
"@
|
|
51
|
-
"@
|
|
52
|
-
"
|
|
53
|
-
"
|
|
67
|
+
"@release-it/conventional-changelog": "^10.0.6",
|
|
68
|
+
"@types/node": "^25.5.0",
|
|
69
|
+
"@vitest/coverage-v8": "^4.1.1",
|
|
70
|
+
"cspell": "^9.7.0",
|
|
71
|
+
"eslint": "^9.39.4",
|
|
54
72
|
"eslint-config-agent": "^1.9.3",
|
|
55
73
|
"eslint-config-publishable-package-json": "^1.0.0",
|
|
56
74
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
57
75
|
"husky": "^9.1.7",
|
|
58
|
-
"knip": "^5.
|
|
59
|
-
"lint-staged": "^16.
|
|
60
|
-
"prettier": "^3.
|
|
61
|
-
"release-it": "^19.2.
|
|
76
|
+
"knip": "^5.88.1",
|
|
77
|
+
"lint-staged": "^16.4.0",
|
|
78
|
+
"prettier": "^3.8.1",
|
|
79
|
+
"release-it": "^19.2.4",
|
|
62
80
|
"typescript": "^5.9.3",
|
|
63
|
-
"vitest": "^4.
|
|
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"
|
|
81
|
+
"vitest": "^4.1.1"
|
|
79
82
|
}
|
|
80
|
-
}
|
|
83
|
+
}
|