bashgate 0.1.0__py3-none-any.whl
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.
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bashgate
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Claude Code PreToolUse hook that screens bash commands with path validation
|
|
5
|
+
Author: Mog Nesbitt
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/mogest/bashgate
|
|
8
|
+
Project-URL: Repository, https://github.com/mogest/bashgate
|
|
9
|
+
Project-URL: Issues, https://github.com/mogest/bashgate/issues
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
13
|
+
Requires-Python: >=3.10
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest; extra == "dev"
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
|
|
20
|
+
# bashgate
|
|
21
|
+
|
|
22
|
+
A [Claude Code](https://docs.anthropic.com/en/docs/claude-code) hook that automatically approves bash commands you've allowlisted, while still prompting for everything else. It also validates that file paths stay inside your project directory — something Claude Code's built-in `permissionDecision: "allow"` rules don't do.
|
|
23
|
+
|
|
24
|
+
## Why use this?
|
|
25
|
+
|
|
26
|
+
Claude Code asks permission before running bash commands. You can add `Bash(...)` rules in `settings.json` to auto-approve certain commands, but those rules bypass Claude Code's path validation — meaning an allowed command could read or write files anywhere on your system.
|
|
27
|
+
|
|
28
|
+
bashgate gives you the same auto-approval convenience with two improvements:
|
|
29
|
+
|
|
30
|
+
- **Path validation** — commands that reference paths outside your project directory are flagged for approval, even if the command itself is allowlisted
|
|
31
|
+
- **Fine-grained control** — allow specific subcommands (e.g. `git push` but not `git reset --hard`), block dangerous flags, and match argument patterns
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
Requires Python 3.10+.
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
pipx install bashgate
|
|
39
|
+
bashgate install
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
`bashgate install` registers the hook in `~/.claude/settings.json` and copies a sensible default config to `~/.claude/bashgate.json` if one doesn't already exist.
|
|
43
|
+
|
|
44
|
+
## How it works
|
|
45
|
+
|
|
46
|
+
When Claude Code wants to run a bash command, bashgate intercepts it and makes one of three decisions:
|
|
47
|
+
|
|
48
|
+
- **Allow** — the command matches your allowlist and all paths are within the project directory
|
|
49
|
+
- **Ask** — the command is recognised but has a risky flag, targets a path outside the project, or hits a deny rule. Claude Code prompts you as normal
|
|
50
|
+
- **Fall through** — the command isn't in the config at all, so Claude Code's default permission system handles it
|
|
51
|
+
|
|
52
|
+
Compound commands (`&&`, `||`, `;`, `|`) are only auto-approved if every part is individually allowed. Shell features like variable expansion, backticks, and process substitution always trigger a prompt.
|
|
53
|
+
|
|
54
|
+
## Configuration
|
|
55
|
+
|
|
56
|
+
bashgate looks for config in two places:
|
|
57
|
+
|
|
58
|
+
1. **Global** — `~/.claude/bashgate.json`
|
|
59
|
+
2. **Local** — `.bashgate.json` files found by walking from the project directory up to the filesystem root
|
|
60
|
+
|
|
61
|
+
All found configs are merged, with the nearest-to-project file taking highest precedence. This lets you add project-specific rules (e.g. allowing `mix test` only in Elixir projects) on top of your global defaults.
|
|
62
|
+
|
|
63
|
+
If you don't want local configs to be able to weaken or disable your global rules, set `"ignore_local_configs": true` in your global config.
|
|
64
|
+
|
|
65
|
+
### Quick start
|
|
66
|
+
|
|
67
|
+
The default config (`bashgate.default.json`) ships with sensible rules for common commands. After `bashgate install`, you'll have a working setup that auto-approves things like `git status`, `ls`, `cat`, and `rg` while still prompting for destructive operations.
|
|
68
|
+
|
|
69
|
+
### Config format
|
|
70
|
+
|
|
71
|
+
The config is a JSON file with a `commands` array. Entries can be simple strings or detailed objects.
|
|
72
|
+
|
|
73
|
+
**Simple string** — prefix-matches the full command:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"commands": [
|
|
78
|
+
"cat",
|
|
79
|
+
"ls",
|
|
80
|
+
"mise exec -- bundle exec rspec"
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`"cat"` matches `cat foo.txt`, `cat -n bar.py`, etc.
|
|
86
|
+
|
|
87
|
+
**Object entry** — for commands that need subcommand control or deny rules:
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"commands": [
|
|
92
|
+
{
|
|
93
|
+
"command": "git",
|
|
94
|
+
"flags_with_args": ["-C", "-c"],
|
|
95
|
+
"allow": {
|
|
96
|
+
"subcommands": [
|
|
97
|
+
"status",
|
|
98
|
+
"diff",
|
|
99
|
+
"log",
|
|
100
|
+
{
|
|
101
|
+
"subcommand": "push",
|
|
102
|
+
"ask": {
|
|
103
|
+
"flags": ["--force", "-f"]
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
This allows `git status`, `git diff`, `git log`, and `git push` — but prompts if `git push` is used with `--force`. Any other git subcommand (like `git reset`) falls through to Claude Code's default prompting.
|
|
114
|
+
|
|
115
|
+
### Entry reference
|
|
116
|
+
|
|
117
|
+
| Field | Description |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `command` | The command name to match (required for object entries) |
|
|
120
|
+
| `flags_with_args` | Flags that consume the next token (e.g. `-C dir`) — needed so bashgate can correctly identify the subcommand |
|
|
121
|
+
| `allow.subcommands` | List of allowed subcommands (strings or objects with their own rules) |
|
|
122
|
+
| `allow.any_path` | `true` to skip path validation entirely, or `{"position": N}` to skip it for the Nth positional argument (useful for `sed` and `grep` where the first argument is a pattern, not a path) |
|
|
123
|
+
| `allow.flags_with_any_path` | Flags whose values should be exempt from path validation |
|
|
124
|
+
| `deny.flags` | Flags that should always be blocked |
|
|
125
|
+
| `deny.arg_regex` | Regex pattern matched against arguments — triggers a block if matched |
|
|
126
|
+
| `deny.message` | Custom message shown when a deny rule triggers |
|
|
127
|
+
| `ask.flags` | Flags that should trigger a prompt (same as deny but results in "ask" instead of "deny") |
|
|
128
|
+
| `ask.arg_regex` | Regex pattern that triggers a prompt if matched |
|
|
129
|
+
|
|
130
|
+
### Additional config options
|
|
131
|
+
|
|
132
|
+
| Field | Default | Description |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| `enabled` | `true` | Set to `false` to disable bashgate entirely (falls through to Claude Code defaults) |
|
|
135
|
+
| `disable_inside_sandbox` | `false` | Set to `true` to disable bashgate when Claude Code's sandbox is active |
|
|
136
|
+
| `ignore_local_configs` | `false` | Set to `true` in the **global** config to skip local `.bashgate.json` discovery entirely. Prevents project-level configs from weakening or disabling protection. |
|
|
137
|
+
| `allowed_directories` | `[]` | Additional directories that should be treated as valid path targets (supports relative paths resolved from the config file's location) |
|
|
138
|
+
|
|
139
|
+
## Security note: local config files
|
|
140
|
+
|
|
141
|
+
bashgate merges `.bashgate.json` files found in or above your project directory. This means a cloned repository could include a `.bashgate.json` that loosens your rules — for example, allowing commands or paths you wouldn't normally approve.
|
|
142
|
+
|
|
143
|
+
If you work with untrusted repositories, set `"ignore_local_configs": true` in your global `~/.claude/bashgate.json` to prevent any local config from being loaded.
|
|
144
|
+
|
|
145
|
+
## Validating your config
|
|
146
|
+
|
|
147
|
+
```sh
|
|
148
|
+
bashgate validate
|
|
149
|
+
bashgate validate --config path/to/config.json
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
This checks for structural errors, unknown keys, and invalid regex patterns.
|
|
153
|
+
|
|
154
|
+
## `find` considered annoying
|
|
155
|
+
|
|
156
|
+
You'll find bashgate trips up on `find` quite a bit because of its awkward syntax. I'd suggest
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
{
|
|
160
|
+
"command": "find",
|
|
161
|
+
"deny": {
|
|
162
|
+
"message": "use `fd` instead of `find`"
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
and install the excellent `fd` to do your finding for you instead.
|
|
168
|
+
|
|
169
|
+
## Debugging
|
|
170
|
+
|
|
171
|
+
If commands aren't being handled as expected:
|
|
172
|
+
|
|
173
|
+
```sh
|
|
174
|
+
# In your hook config, add --debug:
|
|
175
|
+
bashgate hook --debug
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
This logs decisions to `~/.claude/bashgate-debug.log`.
|
|
179
|
+
|
|
180
|
+
## License
|
|
181
|
+
|
|
182
|
+
MIT
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
bashgate.py,sha256=kc4f_O4eT5dp57IOMgNDkLAtpcck1nKF0L1HMMSn2v4,42904
|
|
2
|
+
bashgate-0.1.0.dist-info/licenses/LICENSE,sha256=ooqGHevWLCTxUzsSdT1F4mAA7QUD8KsWd1RUN1hckMk,1068
|
|
3
|
+
bashgate-0.1.0.dist-info/METADATA,sha256=e--SvIUrYMSl_xIbM_966j6Vwe-mGjsPS2igZm0ycDU,7346
|
|
4
|
+
bashgate-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
5
|
+
bashgate-0.1.0.dist-info/entry_points.txt,sha256=K7DTXSuRpJ-HLxb1_016WZw76GW-3VLQbTemib7Hb58,43
|
|
6
|
+
bashgate-0.1.0.dist-info/top_level.txt,sha256=Skz0YKLemVXkQJCFnjNixTwV4YuJxvPic0rYbmB712Q,9
|
|
7
|
+
bashgate-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mog Nesbitt
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
bashgate
|